在使用非常簡單的引導加載程序時,我發現在運行到保護模式之前將某些內容分配給數據段(ds)會導致處理器故障。如果數據段非零,保護模式將失敗
此代碼工作得很好:
[BITS 16]
[ORG 0x7c00]
xor ax,ax
mov ds,ax
cli
lgdt [gdt_descriptor]
mov eax, cr0
or eax,1
mov cr0, eax
jmp CODE_SEG:now
[BITS 32]
now:
jmp $
db 0
gdt_start:
gdt_null:
dd 0x0
dd 0x0
gdt_cs:
dw 0xFFFF ; Limit
dw 0x0000 ; Base
db 0x0000 ; Base 23:16
db 10011011b
db 11011111b
db 0x0000
gdt_ds:
dw 0xFFFF ; Limit
dw 0x0000 ; Base
db 0x0000 ; Base 23:16
db 10010011b
db 11011111b
db 0x0000
gdt_end
gdt_descriptor:
dw gdt_end - gdt_start - 1
dd gdt_start
CODE_SEG equ gdt_cs - gdt_start
DATA_SEG equ gdt_ds - gdt_start
times 510-($-$$) db 0 ; fill sector w/ 0's
db 0x55 ; req'd by some BIOSes
db 0xAA
這一個使處理器重新啓動:
[BITS 16]
[ORG 0x7c00]
mov ax,0x10 ;<-- Pre-assigning data segment
mov ds,ax
cli
lgdt [gdt_descriptor]
mov eax, cr0
or eax,1
mov cr0, eax
jmp CODE_SEG:now
[BITS 32]
now:
jmp $
db 0
gdt_start:
gdt_null:
dd 0x0
dd 0x0
gdt_cs:
dw 0xFFFF ; Limit
dw 0x0000 ; Base
db 0x0000 ; Base 23:16
db 10011011b
db 11011111b
db 0x0000
gdt_ds:
dw 0xFFFF ; Limit
dw 0x0000 ; Base
db 0x0000 ; Base 23:16
db 10010011b
db 11011111b
db 0x0000
gdt_end
gdt_descriptor:
dw gdt_end - gdt_start - 1
dd gdt_start
CODE_SEG equ gdt_cs - gdt_start
DATA_SEG equ gdt_ds - gdt_start
times 510-($-$$) db 0 ; fill sector w/ 0's
db 0x55 ; req'd by some BIOSes
db 0xAA
我編這與NASM和我一起跑VMWARE它。
爲什麼會發生這種情況?
您正在加載具有錯誤值的'ds'。你爲什麼期望它工作? –
如果文檔指定ds在加載保護模式的長跳轉之前必須爲非零值。除此之外,0x10是正確的值,跳進保護模式後,我可以將ds設置爲0x10,並且工作正常 – felknight
@Felipe:Jonathon的答案正確;但只涉及你現在遇到的一個具體問題。您還有很多其他問題,包括依靠虛假信息(「ds必須在跳轉前不爲零」),不理解實模式段加載和保護模式段加載之間的差異,錯誤地假設BIOS使某些寄存器處於特定狀態甚至在引導加載程序的第一個512字節中切換到保護模式是一個設計錯誤。 – Brendan