Assembly 在GDB(实模式,连接到QEMU)中,在特定条件下的特定点,stepo和nexti似乎打破了断点机制

Assembly 在GDB(实模式,连接到QEMU)中,在特定条件下的特定点,stepo和nexti似乎打破了断点机制,assembly,gdb,breakpoints,qemu,real-mode,Assembly,Gdb,Breakpoints,Qemu,Real Mode,最小工作示例来源: 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-($-$$)

最小工作示例来源:

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
@失败:

否 以下gdb命令启用远程协议调试,并显示gdb和QEMU gdbserver之间的交换:
set debug remote 1

QEMU在exchange中的回复看起来合理,但gdb最终在地址0x5ea7c17处设置断点,这是错误的。它似乎将
sp
处的4个字节解释为返回地址,而不是仅2个字节。0x7c17是实际返回地址,0xea和0x5是引导扇区代码的前两个字节。

Yes,
ebp
由gdb在堆栈遍历期间用于确定堆栈帧和回溯。当然,这仍然有效。错误甚至可能在qemu gdb存根中。在任何情况下,gdb都不是一个很好的16位实模式调试器。作为附带问题,欢迎对简单引导程序开发周期和调试工具提出任何其他建议。请使用BOCHS。这绝对是引导加载程序和调试切换到32或64位模式的最佳建议。它的内置调试器可以为您解码GDT、IDT和page表,以确保您的代码按照您认为的方式设置它们。和解码/打印异常详细信息。考虑到关于实模式调试的帖子中有一半在某个时候提到过它,这是有道理的。这肯定会有帮助。我试试看。谢谢,你说得对。离答案又近了一步。命令
set debug remote 1
绝对有用。谢谢你。遗憾的是,它并没有揭示GDB本身的内部结构——与解决问题的$ebp的链接(在本例中,它也可能与stepi和nexti/stepo有关)。有什么想法吗?GDB函数
insert\u step\u resume\u breakpoint\u at\u caller
负责设置一个断点,该断点应该在
ni
之后捕获执行。GDB命令
set debug frame 1
使其转储与处理堆栈帧相关的信息。带有和不带有
bp
初始化的情况会导致不同的调试输出。来自
设置调试帧1
(扩展后,我假设)
信息帧的信息与调用方的
插入步骤恢复断点有关?我已经注意到
信息框
中假定的返回地址是错误的,因此它与此函数之间的连接是缺少的链接。如果是,请将此添加到您的答案中,以便我将其标记为已接受的解决方案。另外,GDB为什么要查看$ebp作为返回地址?它是否假定使用了
enter
/
leave