I am working very hard to get this protected mode working, but I'm still stuck. This is how my code looks like now:
Code:
1 VGA_COLOR_LIGHT_RED equ 0xC
2 VGA_COLOR_LIGHT_GREEN equ 0xA
3
4 ;pos bg fg ch
5 %macro write_c 4
6 mov bx, 0x10
7 mov es, bx
8 mov bx, %1
9 shl bx, 0x1
10 mov ah, %2
11 shl ah, 0x4
12 or ah, %3
13 mov al, %4
14 mov [es:bx], ax
15 %endmacro
16
17 %macro set_magic_number 0
18 times 510 - ( $ - $$ ) db 0
19 db 0x55, 0xAA
20 %endmacro
21
22 org 0x7C00
23
24 00000000 FA cli
25
26 00000001 0F0116[2C00] lgdt [gdt_ptr]
27
28 00000006 0F20C0 mov eax, cr0
29 00000009 0C01 or al, 1
30 0000000B 0F22C0 mov cr0, eax
31
32 0000000E EA[1300]0800 jmp 0x8:next
33 next:
34
35 write_c 0, VGA_COLOR_LIGHT_RED, VGA_COLOR_LIGHT_GREEN, 'X'
36 00000013 BB1000 <1> mov bx, 0x10
37 00000016 8EC3 <1> mov es, bx
38 00000018 BB0000 <1> mov bx, %1
39 0000001B D1E3 <1> shl bx, 0x1
40 0000001D B40C <1> mov ah, %2
41 0000001F C0E404 <1> shl ah, 0x4
42 00000022 80CC0A <1> or ah, %3
43 00000025 B058 <1> mov al, %4
44 00000027 268907 <1> mov [es:bx], ax
45
46 0000002A EBFE stop: jmp stop
47
48
49
50
51 gdt_ptr:
52 0000002C 0017 db 0,8*3-1
53 0000002E 00007C32 db 0,0,0x7C,0x32
54
55 ; null descriptor
56 00000032 0000000000000000 dq 0
57
58 ; code descriptor
59 ; #0-------------- #1-------------- #2------ #3#4#5#6#7#8 #9#A-- #B#C#D#E#F------
60 ; 0b1111111111111111_0000000000000000_00000000_0_1_0_1_1_00_1_1111_0_0_1_0_00000000
61 0000003A FFFF00000059F200 db 0xff,0xff, 0x00,0x00, 0x00, 0x59, 0xf2, 0x00
62
63 ; data descriptor:
64 ; #0-------------- #1-------------- #2------ #3#4#5#6#7#8 #9#A-- #B#C#D#E#F------
65 ; 0b1111111111111111_0000101110000000_00000000_0_1_0_0_1_00_1_1111_0_0_1_0_00000000
66 00000042 FFFF0B800049F200 db 0xff,0xff, 0x0b,0x80, 0x00, 0x49, 0xf2, 0x00
67
68 set_magic_number
69 0000004A 00<rept> <1> times 510 - ( $ - $$ ) db 0
70 000001FE 55AA <1> db 0x55, 0xAA
I am not using interrupts so I don't need an IDT because I am writting to the screen though video memory (0x8B000).
In the line number 32 I make a far jump to 0x8:next to set the cs register with the second descriptor (Each descriptor's size is 8 bytes and the second is the code descriptor, so I think I should use 0x8).
In the line 16 I load 'es' with the value 0x10 because the data descriptor is the second descriptor and 0x8*2 = 0x10
This time I use db with commas instead of dw, dd or dq because I don't want to have problems with little endian.
These are now the values of the descriptors:
#0 & #A: Limit with the maximum possible value. This is a test program that is only supposed to print something in screen. I don't want problems with the size.
#1, #2 & #F: Base at the start of the memory.
#3: If the segment has been accessed or not. Therefore, zero
#4: Read/Write. I don't want to have problems so I set this to 1
#5: Direction/Conforming. Zero means no privilege level needed to use.
#6: Executable. This is only in the first case.
#7: Reserved, always 1
#8: Kernel privilege.
#9: Present. I want to use it. Therefore 1.
#B & #C: Reserved, always zero.
#D: Size. As Octocontrabass suggest I use 32 bit.
#E: Granularity. I think I don't need it.
I am spending a lot of time trying to find a way to get this working and I really would appreciate a minimal example that only have GDT and print something using it. This tutorial
http://wiki.osdev.org/GDT_Tutorial use C code, but I want to do this in NASM.