From c91590e59f6f41b7316edd8587542ed24d0fdb22 Mon Sep 17 00:00:00 2001 From: Carlos Maiolino Date: Thu, 17 Jul 2025 19:20:25 +0200 Subject: Setup GDT and load protected mode Create a GDT table and use it to switch CPU into protected mode. This also gets rid of the print routines. Giving we won't have access to the BIOS interrupts once we switch the CPU to protected mode, they are pointless. Signed-off-by: Carlos Maiolino --- bootloader.asm | 86 +++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 64 insertions(+), 22 deletions(-) diff --git a/bootloader.asm b/bootloader.asm index bf3afb4..f42e702 100644 --- a/bootloader.asm +++ b/bootloader.asm @@ -1,6 +1,8 @@ -ORG 0x0 +ORG 0x7c00 BITS 16 +CODE_SEG equ gdt_code - gdt_start ; 0x8 +DATA_SEG equ gdt_data - gdt_start ; 0x10 _start: jmp short start nop @@ -10,42 +12,82 @@ _start: times 33 db 0 start: - ; Set CS to 0x07c0 with label step2 as its beginning offset - jmp 0x07c0:step2 + ; Set CS to 0 with label step2 as its beginning offset + jmp 0:step2 step2: ; Setup segments cli ; Disable interrupts - mov ax, 0x07c0 + mov ax, 0 mov ds, ax mov es, ax - mov ax, 0x00 mov ss, ax mov sp, 0x7c00 ; Stack segment starts right before ds ; and grows down to 0x0. This works because ; Intel implements a full descending stack sti ; Enable interrupts - jmp $ +.load_protected: + cli + lgdt[gdt_table] + mov eax, cr0 + or eax, 0x1 + mov cr0, eax + jmp CODE_SEG:start_32 + +; GDT table description +gdt_start: +gdt_null: ; First segment Descriptor is always 0 + dd 0x0 + dd 0x0 + +;Second segment descriptor... Code segment - 0x8 +gdt_code: + dw 0xffff ; Segment limit 0-15 + dw 0 ; Base address 0-15 + db 0 ; Base 16-23 + db 0x9a ; Access byte field 0b10011010 + + ; We don't have a 4 bits type, so use a byte type + ; to set both Segment limit high bits and flags + + db 11001111b ; Segment limit 16-19 + ; Flags 0-3 + db 0 ; Base address high bits 24-31 + +;Second segment descriptor... Data segment - 0x10 +gdt_data: + dw 0xffff ; Segment limit 0-15 + dw 0 ; Base address 0-15 + db 0 ; Base 16-23 + db 0x92 ; Access byte field 0b10010010 + db 11001111b ; Segment limit 16-19 + ; Flags 0-3 + db 0 ; Base address high bits 24-31 +gdt_end: + +gdt_table: + dw gdt_end - gdt_start - 1 + dd gdt_start -; Message Print routines -print: - mov bx, 0 -.loop - lodsb - cmp al, 0 - je .done - call print_char - jmp .loop -.done: - ret - -print_char: - mov ah, 0x0e - int 0x10 - ret +[BITS 32] + +; No access to BIOS from now on.... +start_32: + ; Set all segments to the same as the DATA_SEG + mov ax, DATA_SEG + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + + ; Set the stack pointer and base pointer further in mem + mov ebp, 0x00200000 + mov esp, ebp + jmp $ ; Fill in to the end and add bootloader signature times 510 - ($ - $$) db 0 -- cgit v1.2.3