Trying to make my very first GDT
Posted: Sun Nov 12, 2017 4:07 pm
I am trying to enter the protected mode without labels because I want to be sure that I understand how everything works. This is my code, that should print the characters from 'A' to 'F':In the lines from 14 to 19 I set up the GDT and start the protected mode.
In the line number 21 I make a far jump that should make the program print the caracters from 'A' to 'F'.
In the line 44 I put the size of the GDT. Each entry has a size of 8 bytes and I only have 2 entries: The null descriptor (because everybody recommends to put it) and the descriptor that I want to test. Total: 16 bytes (0x10)
In the line 45 I put the start location of the GDT: 0x7C00 (where the bootloader is loaded) + 0x0083 = 0x7C83
In the line 47 I set the null descriptor
In the line 49 I set the maximum size possible for a segment, as also did in line 52 with the four ones
In the line 50 I put the location where I would like to set the code segment: the location of the print_c 'A' instruction.
In the line 51 I set the access byte with the following values:
- bit 0: This bit tells us whether the segment is accessed by CPU, so it should be set to zero
- bit 1: Make the code segment read-only instead of unreadable
- bit 2: Not conforming. This way we don't need any privileges
- bit 3: Is a code segment, so it should be executable.
- bit 4: Reserved, always 1
- bit 5 and 6: 11 (3 in binary) because is the lowest privilege level.This way the segment is more accessible. Anyway, bit 2 make this bit useless.
- bit 7: Wheter the segment is present or not. I don't get it, but I set it to 1 because I think it should be 1 to be usable.
The first 4 bits in the line 52 are the size again, so I set it to 1111 because I want it to be the greatest possible so I don't have problems with the size (I'm just testing the GDT)
The last 4 bits in the line 52 I set the entry flag bits this way:
- bit 0 and 1: Reserved, always zero
- bit 2: size --> zero (16 bit mode)
- bit 3: granularity --> I don't want this, so zero.
And finally the line 53 with the last byte of the address of the segment.
However, this doesn't do anything. What I am missing?
Code: Select all
1 %macro set_magic_number 0.nolist
2 times 510 - ( $ - $$ ) db 0
3 db 0x55, 0xAA
4 %endmacro
5
6 %macro print_c 1.nolist
7 mov ah, 0x0E
8 mov al, %1
9 int 0x10
10 %endmacro
11
12 00000000 FA cli
13
14 00000001 B8C007 mov ax, 0x07C0
15 00000004 8EC0 mov es, ax
16 00000006 260F01167D00 lgdt [es:0x007D]
17 0000000C 0F20C0 mov eax, cr0
18 0000000F 0C01 or al, 1
19 00000011 0F22C0 mov cr0, eax
20 00000014 FB sti
21 00000015 EA00000100 jmp 0x0001:0x0000
22
23 0000001A B40EB030CD10 print_c '0'
24 00000020 B40EB031CD10 print_c '1'
25 00000026 B40EB032CD10 print_c '2'
26 0000002C B40EB033CD10 print_c '3'
27 00000032 B40EB034CD10 print_c '4'
28 00000038 B40EB035CD10 print_c '5'
29 0000003E B40EB036CD10 print_c '6'
30 00000044 B40EB037CD10 print_c '7'
31 0000004A B40EB038CD10 print_c '8'
32 00000050 B40EB039CD10 print_c '9'
33 00000056 B40EB041CD10 print_c 'A'
34 0000005C B40EB042CD10 print_c 'B'
35 00000062 B40EB043CD10 print_c 'C'
36 00000068 B40EB044CD10 print_c 'D'
37 0000006E B40EB045CD10 print_c 'E'
38 00000074 B40EB046CD10 print_c 'F'
39
40 0000007A FB sti
41
42 0000007B EBFE stop:jmp stop
43
44 0000007D 0010 db 0x00,0x10
45 0000007F 00007C7B db 0x00,0x00,0x7C,0x83
46
47 00000083 0000000000000000 dq 0x0
48
49 0000008B FFFF dw 0xFF_FF
50 0000008D 007C56 db 0x00,0x7C,0x56
51 00000090 4F db 0b01011111
52 00000091 F0 db 0b1111_0000
53 00000092 00 db 0x00
54
55 00000093 00<rept>55AA set_magic_number
In the line number 21 I make a far jump that should make the program print the caracters from 'A' to 'F'.
In the line 44 I put the size of the GDT. Each entry has a size of 8 bytes and I only have 2 entries: The null descriptor (because everybody recommends to put it) and the descriptor that I want to test. Total: 16 bytes (0x10)
In the line 45 I put the start location of the GDT: 0x7C00 (where the bootloader is loaded) + 0x0083 = 0x7C83
In the line 47 I set the null descriptor
In the line 49 I set the maximum size possible for a segment, as also did in line 52 with the four ones
In the line 50 I put the location where I would like to set the code segment: the location of the print_c 'A' instruction.
In the line 51 I set the access byte with the following values:
- bit 0: This bit tells us whether the segment is accessed by CPU, so it should be set to zero
- bit 1: Make the code segment read-only instead of unreadable
- bit 2: Not conforming. This way we don't need any privileges
- bit 3: Is a code segment, so it should be executable.
- bit 4: Reserved, always 1
- bit 5 and 6: 11 (3 in binary) because is the lowest privilege level.This way the segment is more accessible. Anyway, bit 2 make this bit useless.
- bit 7: Wheter the segment is present or not. I don't get it, but I set it to 1 because I think it should be 1 to be usable.
The first 4 bits in the line 52 are the size again, so I set it to 1111 because I want it to be the greatest possible so I don't have problems with the size (I'm just testing the GDT)
The last 4 bits in the line 52 I set the entry flag bits this way:
- bit 0 and 1: Reserved, always zero
- bit 2: size --> zero (16 bit mode)
- bit 3: granularity --> I don't want this, so zero.
And finally the line 53 with the last byte of the address of the segment.
However, this doesn't do anything. What I am missing?