我目前遵循啓用GDT分段的指南。我使用GNU彙編程序,用Bochs進行仿真。無法理解啓用GDT分段,即更新CS寄存器
我知道我需要用GDT描述符加載GDT寄存器。我已經完成了,接下來的步驟是現在將所有帶有偏移量的段寄存器加載到代碼/數據段描述符的各個位置。這樣做的代碼表述爲以下幾點:
reloadSegments:
; Reload CS register containing code selector:
JMP 0x08:reload_CS ; 0x08 points at the new code selector
.reload_CS:
; Reload data segment registers:
MOV AX, 0x10 ; 0x10 points at the new data selector
MOV DS, AX
MOV ES, AX
MOV FS, AX
MOV GS, AX
MOV SS, AX
RET
我不能,但是,瞭解它是如何可能與不跳轉到的顯然是必然結果偏移隱式加載CS寄存器的任何存儲位置是尖通過CS:IP對 - 即,如果代碼段描述符位於GDT_start + 0x10處,並且我試圖將0x10加載到CS寄存器,則虛擬機跳轉到0x10:IP,並且我從不輸入.reload_CS標籤。
我日常的版本(在& T語法):
_start:
// Disable interrupts
cli
// Load GDT register with location of GDT
lgdt 0x3c
// Load location of Code segment descriptor into cs
ljmp $0x2c, $reload_cs
reload_cs:
mov $0x34, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
mov %ax, %ss
loop:
jmp loop
PS:我不知道爲什麼ljmp $0x2c, reload_cs
不起作用 - 前綴reload_cs
與$
編譯但標籤通常並不需要此語法我的經驗...
這是一個很大的跳躍,不確定哪一部分會讓你感到困惑?它會跳轉到給定的地址,同時也重新加載'CS'。這是你的工作,建立'GDT',讓你跳到正確的位置。如果段基址爲'0',並且處於'org 0'模式,則它將是正確的。 PS:'lgdt 0x3c'很**可疑。 – Jester
嗯,我讀到'cs'必須包含代碼段相對於GDT的偏移量,但'cs'也構成了指向下一條指令的指針,即'cs:ip' - 因此我最終跳到' 0x2c:reload_cs',它不是'reload_cs'的位置。到目前爲止,我能理解的唯一解決方案是設計GDT中代碼段的位置以保持'cs'不變,這很荒謬。我覺得我錯過了關於彙編程序的一些基本知識。 –
'cs:ip'在保護模式下使用GDT條目中的基地址。您只需確保在指令中添加了偏移量的基地址將您帶到正確的位置。實現這一點最簡單的方法是在實模式中使用'org 0',並在描述符條目中使基址爲零。 – Jester