In case this helps somebody in the future:
This code worked for me:
gdt.s
section .data
gdt:
.null:
dq 0
.code:
dw 0xFFFF
dw 0x0000
db 0x00
db 0x9A
db 0xCF
db 0x00
.data:
dw 0xFFFF
dw 0x0000
db 0x00
db 0x92
db 0xCF
db 0x00
gdtr:
dw $-gdt-1
dd gdt
section .text
global init_global_descriptor_table
init_global_descriptor_table:
lgdt [gdtr]
jmp 0x08:.reload_cs
.reload_cs:
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
ret
paging.c
enum flags {
Present = 1 << 0,
ReadWrite = 1 << 1,
AccessAll = 1 << 2,
WriteThroughCashing = 1 << 3,
DisableCashing = 1 << 4,
Accessed = 1 << 5,
Dirty = 1 << 6, // only for page-table-entries
MPages = 1 << 7,
Global = 1 << 8, // only for page-table-entries
};
struct entry {
unsigned int flags : 9;
unsigned int available : 3;
unsigned int addr : 20;
};
extern void load_paging_directory(int *ptr);
void init_paging() {
struct entry *dir = (struct entry *)0x00105000;
struct entry *t1 = (struct entry *)0x00106000;
for (int i = 0; i < 1024; i++) {
dir[i] = (struct entry){0};
if (i <= 262) t1[i] = (struct entry){Present | ReadWrite, 0, i};
}
dir[0] = (struct entry){Present, 0, (int)t1 >> 12};
load_paging_directory((int *)dir);
}
paging_asm.s
global load_paging_directory
load_paging_directory:
push ebp,
mov ebp, esp
mov eax, [ebp + 8]
mov cr3, eax
mov eax, cr0
or eax, 0x80000001
mov cr0, eax
mov esp, ebp
pop ebp
ret
My mistake was that my struct had the address field in the low bits and the flags field in the high bits. This was the cause for some very strange behavior. In the end it did not crash at mov cr0, eax but rather at mov esp, ebp. Thank you to every person who commented.
The question has been solved using this struct:
struct entry {
unsigned int flags : 9;
unsigned int available : 3;
unsigned int addr : 20;
};
User contributions licensed under CC BY-SA 3.0