[英]What does "invalid command (error code 0x01)" mean within BIOS int 13
我正在和我的一個朋友一起開發一個簡單的引導加載程序,並沒有假裝它變成任何可用的東西。 在編寫了屏幕輸入和 output 函數之后,我們繼續編寫從磁盤讀取扇區的函數,這就是第一個問題出現的地方。 我 state 在 qemu 和 bochs 上一切正常。 對於物理硬件,我不能說同樣的話,我遇到錯誤 0x0001,這意味着Invalid Command 。
但是,我沒有找到有關此錯誤的太多信息。 在我看來,這可能意味着我的某個論點有誤,但我在屏幕上打印了所有日志,並沒有找到任何奇怪的值來證明這種行為是正當的。
我正在從 flash 驅動器啟動。 我認為這也可能是一個問題(因為它不是真正的軟盤),但如果 BIOS 可以加載引導扇區,那么加載下一個扇區也應該沒有問題。
但是,這里是 read_sector function 的代碼:
read_sector:
start_f
pusha
mov (drive_number), %dl # drive number is stored from the main function into a global variable
mov $0x03, %si # try three times
1:
mov $0x0201, %ax
int $disk_int
jnc end
dec %si
jz 2f
xor %ah, %ah
int $disk_int
jmp 1b
2:
movzx %ah, %dx
call printh # print error code
end:
popa
end_f
這里是調用者 function (dl = 0):
# ...
mov $0x0002, %cx
xor %dh, %dh
mov $0x7e00, %bx
call read_sector
# ...
我們可能做錯了什么?
這里的問題出在文件init.s
中。 在初始化代碼段之前,我在drive_number
中輸入了一個值。
當我將此列表翻譯成機器語言時, drive_number
通過引用它所在部分的開頭來計算 drive_number 的地址(在本例中, .text
部分從地址7c00
開始,如 linker 腳本中所指定) :
.text 0x7c00 :
{
*(.text);
}
這意味着指令mov $0, (drive_number)
被翻譯成mov $0, 7c2e
。 然而,這不是一個實際的物理地址,而只是一個偏移量。 在實模式下,通過將特定段寄存器中的值移動 4 位(與乘以 16)相加到偏移量(如本例中的7c2e
)來計算物理地址。 我們經常看到符號AAAA:BBBB
表示地址AAAA * 16 + BBBB
。 為了確定 memory 中用於讀取或寫入某種數據的位置的物理地址,CPU 默認利用存儲在數據段寄存器%ds
中的值。 這意味着我們存儲數據的實際地址確實是ds * 16 + drive_number
。
當 BIOS 跳轉到寫入引導扇區的代碼時,它不能保證段寄存器中的值是我們想要的值。 因此,在每個程序開始時,我們必須初始化這些寄存器以包含我們需要的值。 如果%ds
不為零,則在%ds
初始化為零后, drive_number
對應的物理地址將不一樣,這意味着此 label 指向 memory 中的不同位置,具體取決於%ds
中包含的值。
BIOS 中斷13, 2
要求 dl 包含指示我們應該從哪個驅動器讀取的代碼。 然而,從我們引導的驅動器中讀取文本,無需在手動之后查閱手冊:事實上,BIOS 將與我們引導的驅動器相對應的值放在%dl
中,然后跳轉到07c0:0000
並開始執行引導扇區中的代碼。 在%dl
中使用 BIOS 傳遞的代碼使代碼更加可靠和健壯。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.