Strange memory segment behavior
Posted: Tue Aug 28, 2018 3:31 am
Hello,
I am currently trying to develop a small OS with the help of a tutorial but I ran into something that looks strange and that I don't understand. This is related with memory segments.
This is how my Global Descriptor Table is setup:
The user code and data segment (0x20 and 0x28) are supposed to start at memory address 0x30000 and end 4kiB further which is address 0x31000.
I am therefore not supposed to be able to access memory above 0x31000 in my user code, but here is my user code:
What I found strange and don't understand is that I don't get any error by executing this code and that it actually writes an 'f' in the top left corner of the screen. How is this possible since I am not supposed to be able to access memory above 0x31000?
I would be pleased if anyone had an answer.
Regards
I am currently trying to develop a small OS with the help of a tutorial but I ran into something that looks strange and that I don't understand. This is related with memory segments.
This is how my Global Descriptor Table is setup:
Code: Select all
void init_gdt() {
gdt_ptr.base = (u32)&gdt_entries;
gdt_ptr.limit = sizeof(gdt_entry_t) * GDT_SIZE - 1;
gdt_entries[0] = create_gdt_entry(0, 0, 0, 0); // 0x00
gdt_entries[1] = create_gdt_entry(0, 0xffffffff, 0x98, 0xc0); // code segment 0x08
gdt_entries[2] = create_gdt_entry(0, 0xffffffff, 0x92, 0xc0); // data segment 0x10
gdt_entries[3] = create_gdt_entry(0x00, 0x00, 0x96, 0xc0); // kernel stack 0x18
gdt_entries[4] = create_gdt_entry(0x30000, 0x0, 0xf8, 0xc0); // user code segment 0x20 / 0x23
gdt_entries[5] = create_gdt_entry(0x30000, 0x0, 0xf2, 0xc0); // user data segment 0x28 / 0x2B
gdt_entries[6] = create_gdt_entry(0x00, 0x20, 0xf6, 0xc0); // user stack 0x30 / 0x33
load_gdt((u32)&gdt_ptr);
print_ok();
print("New GDT loaded\n");
}
gdt_entry_t create_gdt_entry(const u32 base, const u32 limit, const u8 access, const u8 gran) {
return (gdt_entry_t) {
.base_low = (base & 0xffff),
.base_middle = (base >> 16) & 0xff,
.base_high = (base >> 24) & 0xff,
.limit_low = limit & 0xffff,
.granularity = (gran & 0xf0) | ((limit >> 16) & 0x0f),
.access = access
};
}
Code: Select all
[bits 32]
[GLOBAL load_gdt]
load_gdt:
mov eax, [esp + 4] ; get pointer passed by stack
lgdt [eax] ; load the gdt pointer
mov ax, 0x10 ; offset in gdt for data segment
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ax, 0x18 ; ...
mov ss, ax
jmp 0x08:flush ; load code segment (0x08 is offset to code segment)
flush:
ret
I am therefore not supposed to be able to access memory above 0x31000 in my user code, but here is my user code:
Code: Select all
void task() {
char *vid = (char *)0x88000; // 0xb8000 - 0x30000
*vid = 'f';
while(1);
}
I would be pleased if anyone had an answer.
Regards