我一直在研究和撰寫引導加載程式。為了切換到 32 位模式,我使用了本教程:https ://www.youtube.com/watch?v=pXzortxPZR8&list=PLxN4E629pPnKKqYsNVXpmCza8l0Jb6l8-&index=4
它說要寫入您可以使用的視頻記憶體
mov [0xb8000], byte 'A'
這實際上并沒有寫任何東西。我知道代碼是由第一階段引導加載程式成功加載的,因為下一階段文本正在被寫入螢屏,而它仍處于 16 位模式。這個錯誤是因為我的代碼寫入記憶體還是我一開始沒有成功切換到 32 位模式?
[bits 16]
[org 0x7e00]
mov bx, nextStage
call print
;Enable A20 bit, allowing memory > 1Mib
in al, 0x92
or al, 2
out 0x92, al
;GDT = Global Descriptor Table
;Defines memory layout
;Works with sections of memory, we need 3
;Required for some weird reason
GDTNullSeg:
dd 0x0
dd 0x0
;Defines segment for storing code
GDTCodeSeg:
dw 0xFFFF ;Limit
dw 0x0000 ;Base (low)
db 0x00 ;Base (medium)
db 0b10011010 ;Flags
db 0b11001111 ;Flags Upper Limit
db 0x00 ;Base (high)
;Defines segment for storing data
GDTDataSeg:
dw 0xFFFF
dw 0x0000
db 0x00
db 0b10010010
db 0b11001111
db 0x00
;This is how code and data are seperated so they can be stored in the same place in a von neumnan architecture
GDTEnd:
;What is passed to CPU register when GDT is passed, describes GDT
descriptorGDT:
GDTSize:
;GDT size
dw GDTEnd - GDTNullSeg - 1
;GDT address
dd GDTNullSeg
GDTCodeSegSize equ GDTCodeSeg - GDTNullSeg
GDTDataSegSize equ GDTDataSeg - GDTNullSeg
cli
lgdt [descriptorGDT]
mov eax, cr0
or eax, 1
mov cr0, eax
;Far jump, GDTCodeSeg is the segment to jump too, startProtectedMode is the offset (location to jump to in that segment)
;Needed to flush cpu pipelines as if we are changing mode while unknown things are happerning it could lead to unexpected results
jmp GDTCodeSeg:startProtectedMode
jmp $
%include "src/print.asm"
nextStage: db "Successfully entered 2nd stage bootloader.", 0
[bits 32]
startProtectedMode:
;Before anything else we need to point segment registers to new data defined in GDT
mov ax, GDTDataSeg
mov ds, ax
mov ss, ax
mov es, ax
mov fs, ax
mov gs, ax
;Redefine stack pointer to larger value now we have 4GiB of memory to work with
mov ebp, 0x90000
mov esp, ebp
mov al, 'A'
mov ax, 0x0F
mov [0xb8000], ax
jmp $
times 512-($-$$) db 0
編輯:根據 Sep Rolands 的回答,我已經移動了 GDT 定義并更改了對顯存代碼的寫入,導致:
---
jmp $
%include "src/print.asm"
%include "src/GDT.asm"
stage2Info: db 0xA, 0xD, "Successfully entered stage 2 bootloader.", 0
---
;mov esp, ebp
mov ax, 0x0F41
mov [0xb8000], ax
jmp $
---
但是,這會導致引導回圈。
uj5u.com熱心網友回復:
一旦您的代碼列印了nextStage訊息并啟用了 A20,GDT 資料中的執行就會失敗!結果是不可預測的。要么將這些資料項放在其他地方,要么在該指令中
插入一個。jmpcli
正確代碼:
mov ax, 0x0F41 ; BrightWhiteOnBlack 'A'
mov [0xb8000], ax
uj5u.com熱心網友回復:
32 位模式的 jmp 指令不正確:
jmp GDTCodeSeg:startProtectedMode
應該:
jmp GDTCodeSegSize:startProtectedMode
還有這個類似的問題:
mov ax, GDTDataSeg
應該:
mov ax, GDTDataSegSize
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/464756.html
上一篇:嘗試切換到32位模式時啟動回圈
