最小工作示例来源:
use16
org 0x7c00
jmp 0x0000:@start
@start:
cli
mov ax,cs
mov ds,ax
mov es,ax
mov ss,ax
mov sp,0x7c00
sti
mov bp,sp
call @fails
jmp @start
@fails:
nop
retn
times 510-($-$$) db 0
dw 0xAA55
以上内容通过FASM或NASM组装成二进制文件,并写入VHD(x.vhd)的MBR。 QEMU在启用调试支持的情况下启动:qemu-system-i386.exe -m 512 -boot c -net nic -net user -hda x.vhd -no-acpi -s -S -cpu 486
在Cygwin中,使用GDB 9.1-1,然后发出以下命令来运行GDB并将其附加到QEMU,确定体系结构,跳过BIOS代码并在开始时设置断点MBR,加载到0x7c00,然后继续:
gdb
target remote localhost:1234
set architecture i8086
stepi 11
break *0x7c00
continue
nexti 10
此时,$ ip在nop
行。
@fails:
nop ; <---
retn
这里是遇到问题的地方。使用stepi
,在retn
行上放置一个临时断点,继续通过nop
执行并在应有的位置中断。 但是使用stepo
或nexti
,执行的确没有问题,但没有断点]。 GDB进入了无尽的等待。如果在nop
之后手动插入断点(例如,在retn
或jmp @start
上,调用返回的指令以retn
插入),则GDB会在该处中断而不会出现问题。列出此时所有的断点不会产生新的断点,因此nexti
似乎没有在任何地方放置临时断点(或未列出临时断点?)。
[经过大量调查,这是该问题的奇怪“解决方案],让nexti
自动跳过nop
并按原样在此处中断:((1) [C0 ],然后单击set $ebp = 0x7bfa
或(2)注释掉nexti
行。
问题是:
mov bp,sp
似乎在特定位置打破了断点机制?也许在指令之间放置一个断点?还是nexti
以某种方式出现16位代码问题?以下gdb命令启用远程协议调试,并显示gdb和QEMU gdbserver之间的交换显示:nexti
。QEMU在交换中回复看起来很合理,但是gdb最终在地址0x5ea7c17处设置了断点,这是错误的。似乎它将set debug remote 1
的4个字节解释为返回地址,而不是仅2。0x7c17是实际的返回地址,0xea和0x5是引导扇区代码的前两个字节。