使用 qemu 运行我的代码,在调用之后switch_to_32_pm
,Qemu 开始发疯并不断清除屏幕并显示“从硬盘启动”。-curses
(我必须补充一点,由于某种原因我无法运行( -curses: curses or iconv support is disabled
)(我真的应该切换到 linux ......)。
这是相关代码:
引导程序
[org 0x7c00]
[bits 16]
; initialise stack
mov bp, 0x9000
mov sp, bp
call switch_to_32_pm
jmp $
%include "gdt.asm"
%include "switch_to_pm.asm"
[bits 32]
BEGIN_PM:
jmp $
; bootsector padding
times 510-($-$$) db 0
dw 0xaa55
gdt.asm
gdt_start:
gdt_null: ; null descriptor
dd 0x0
dd 0x0
gdt_code: ; code segment descriptor
dw 0xffff ; limit (bits 0-15)
dw 0x0 ; base (bits 0-15)
db 0x0 ; base (bits 16 -23)
db 10011010b ; 1st flags, type flags
db 11001111b ; 2nd flags, Limit (bits 16-19)
db 0x0 ; base (bits 24 - 31)
gdt_data: ; data segment descriptor
dw 0xffff ; limit (bits 0-15)
dw 0x0 ; base (bits 0-15)
db 0x0 ; base (bits 16 -23)
db 10010010b ; 1st flags, type flags
db 11001111b ; 2nd flags, Limit (bits 16-19)
db 0x0 ; base (bits 24 - 31)
gdt_end:
gdt_descriptor:
dw gdt_end - gdt_start - 1 ; size of the gdt
dd gdt_start ; gdt start address
; some handy constants
CODE_SEG equ gdt_code - gdt_start
DATA_SEG equ gdt_data - gdt_start
switch_to_pm.asm
[bits 16]
; switch to 32bit protected mode
switch_to_32_pm:
; disable interrupts
cli
; switch to 32bit protected mode
lgdt [gdt_descriptor]
mov eax, cr0 ; move cr0 to eax
or eax, 0x1 ; set the first bit of eax
mov cr0 , eax ; update cr0
jmp CODE_SEG:init_32_pm ; make a far jump
; this forces the cpu to flush it's cache
; of pre fetched instructions
[bits 32]
; We're now in 32bit mode! 4gb hip hip hooray!
; init stack
init_32_pm:
mov ax, DATA_SEG ; point all segment regs to our data sector in gdt
mov ds, ax
mov ss, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ebp, 0x90000 ; set the stack at the top of free space
mov esp, ebp
call BEGIN_PM