73 lines
1.7 KiB
NASM
73 lines
1.7 KiB
NASM
SECTION .text
|
|
USE16
|
|
|
|
%include "gdt.asm"
|
|
%include "thunk.asm"
|
|
|
|
stage2.entry:
|
|
mov si, stage_msg
|
|
call print
|
|
mov al, '3'
|
|
call print_char
|
|
call print_line
|
|
|
|
; enable A20-Line via IO-Port 92, might not work on all motherboards
|
|
in al, 0x92
|
|
or al, 2
|
|
out 0x92, al
|
|
|
|
protected_mode:
|
|
; disable interrupts
|
|
cli
|
|
|
|
; load protected mode GDT
|
|
lgdt [gdtr]
|
|
|
|
; set protected mode bit of cr0
|
|
mov eax, cr0
|
|
or eax, 1
|
|
mov cr0, eax
|
|
|
|
; far jump to load CS with 32 bit segment
|
|
; We need to do this because we are entering 32-bit mode,
|
|
; but the instruction pipeline still has 16-bit instructions.
|
|
;
|
|
; gdt.pm32_code is a multiple of 8, so it always ends with three zero bits.
|
|
; The GDT spec abuses this fact, and uses these last three bits to store other
|
|
; data (table type and privilege). In this case, 000 is what we need anyway.
|
|
;
|
|
; Also note that CS isn't an address in protected mode---it's a GDT descriptor.
|
|
jmp gdt.pm32_code:protected_mode_inner
|
|
|
|
; We can now use 32-bit instructions!
|
|
USE32
|
|
|
|
protected_mode_inner:
|
|
; load all the other segments with 32 bit data segments
|
|
mov eax, gdt.pm32_data
|
|
mov ds, eax
|
|
mov es, eax
|
|
mov fs, eax
|
|
mov gs, eax
|
|
mov ss, eax
|
|
|
|
; Place stage 3 stack at 448 KiB
|
|
; (512KiB minus 64KiB disk buffer)
|
|
mov esp, 0x70000
|
|
|
|
; push arguments to `start()`
|
|
mov eax, thunk.int10
|
|
push eax
|
|
|
|
; Call `start()`.
|
|
; 0x18 skips ELF headers.
|
|
mov eax, [stage3 + 0x18]
|
|
call eax
|
|
|
|
.halt:
|
|
; Halt if `start()` ever returns (it shouldn't, but just in case)
|
|
; Without this, we'll try to execute whatever comes next in memory.
|
|
cli
|
|
hlt
|
|
jmp .halt
|