我写了一个启动代码,在屏幕上打印一些东西,然后重新定位并加载下一个启动代码(VBR)。我使用 vmware 在虚拟机上测试了代码,它可以正常工作,我看到了 vbr 代码的正确输出。 单击此处查看代码的输出。
我希望能够调试我的代码,并且由于 vmware 没有此功能,我想使用可与 IDA 一起使用的 bochs。在 bochs 上运行代码后,我得到了错误:
>>PANIC<< IO write(0x01f0): current command is 20h
调用处理扩展读取的中断(int 13h,函数 42)后发生错误。我检查了扩展并支持它们,因此我编写了另一个实模式程序,该程序仅使用相同的 bios 功能加载 1 个扇区,并且由于某种原因它起作用了。代码之间只有很小的差异。在引导代码中,我用获取参数的函数包装了加载扇区的代码,而在第二个代码中,它没有用函数包装。我将在这里发布代码。
启动代码(仅相关功能,完整版点击这里):
%define AdjustAddress(addr) addr - BASE_ADDRESS + NEW_ADDRESS
%define DAP(obj, member) [obj + DiskAddressPacket. %+ member]
NEW_ADDRESS equ 0x0600
BASE_ADDRESS equ 0x7C00
DAP_SIZE equ DiskAddressPacket_size
struc DiskAddressPacket
.size resb 1
.resv resb 1
.num_of_sectors resb 2
.offset resb 2
.segment resb 2
.lba_start resb 8
endstruc
main:
; code
; ....
; Read the VBR
push 0x01
mov si, [AdjustAddress(parti_pointer)]
push dword PE(si, starting_lba)
push BASE_ADDRESS
push 0x00
call ReadSectors
; code
; ....
; void __stdcall ReadSectors(WORD segment, WORD offset, DWORD lba, WORD count)
ReadSectors:
push bp ; Save bp register value
mov bp, sp ; Setting up stack frame
sub sp, DAP_SIZE ; Allocate a buffer for the DAP data
; Zero out DAP buffer
std ; Set direction flag (decrease di)
mov di, bp
xor al, al
mov cx, DAP_SIZE
repnz stosb ; di = DAP buffer at the end of this operation
; Initialize DAP with correct data
mov byte DAP(di, size), DAP_SIZE
mov bx, word [bp + 0x0C] ; count parameter
mov word DAP(di, num_of_sectors), bx
mov bx, word [bp + 0x04] ; segment parameter
mov word DAP(di, segment), bx
mov bx, word [bp + 0x06] ; offset parameter
mov word DAP(di, offset), bx
mov bx, word [bp + 0x08] ; Low word of LBA parameter
mov word DAP(di, lba_start), bx
mov bx, word [bp + 0x0A] ; High word of LBA parameter
mov word DAP(di, lba_start + 0x02), bx
; Prepare parameters
mov ax, 0x4200 ; Extended read sectors function of int 0x13
mov dx, word [AdjustAddress(drive_index)] ; Drive index
mov si, di ; si = DAP buffer
int 0x13 ; Read the sectors from the disk
jc CheckLBASupport.no_lba_support
mov sp, bp ; Clear the allocated memory
pop bp ; Restore bp register value
ret 0x0A ; Clean the stack and return to the calling code
第二个代码:
cli ; Cancel interrupts
; Set up segments registers
xor ax, ax
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0x7c00
mov ax, 0x4100
mov bx, 0x55aa
int 0x13
; Checking returned value with the debugger
sub sp, DiskAddressPacket_size
mov bp, sp
mov byte [bp], DiskAddressPacket_size
mov byte [bp + 0x01], 0x00
mov word [bp + 0x02], 0x01
mov word [bp + 0x04], 0x7C00
mov word [bp + 0x06], 0x00
mov dword [bp + 0x08], 0x80
mov dword [bp + 0x0c], 0x00
mov ax, 0x4200
mov si, bp
int 0x13
我检查了内存中的 DAP 缓冲区中的两个代码,它是相同的。我无法弄清楚为什么在启动代码上我得到错误而在第二个代码上我没有。有什么我想念的吗?