我正在尝试了解此代码中发生的情况,特别是在__asm__
内。如何单步执行汇编代码,以便我可以打印每个变量而不是什么?
具体来说,我试图通过这个来弄清8()
的含义是什么,看看它是如何知道它在索引2处进入数组的。
/* a[2] = 99 in assembly */
__asm__("\n\
movl $_a, %eax\n\
movl $99, 8(%eax)\n\
");
答案 0 :(得分:5)
stepi
命令一次遍历程序集一条指令。还有nexti
用于单步执行函数调用。这些命令不符合'只有命令的唯一前缀的类型就足够了'适用于大多数命令的规则 - 部分原因是next
和step
命令完全是这些命令的前缀和部分是因为这些不经常使用,而且当它们通常被知道他们真正想要使用它们的人使用时。
info registers
显示了很多寄存器内容。
您还希望使用disassemble
命令查看反汇编。
help
命令提供了有关所有这些命令的更多信息,例如:
(gdb) help info registers
告诉您info registers
显示整数寄存器及其内容,但它也告诉您如果提供寄存器名称,它将限制输出到该寄存器的值:
(gdb) info registers rax
rax 0x0 0
(rax
是eax
的x86_64版本)
第一列是寄存器名称,第二列是十六进制值,第三列是整数值。
help
命令也有用disassemble
。
请记住,gdb对许多命令都有标签完成,这不仅可以用于简单的命令,但很多时候它会为你提供不好的建议 - 但它有时会有所帮助。
在内联汇编中包含一个标签,可以让您在开头轻松创建一个断点。
答案 1 :(得分:3)
我从来没有擅长AT& T语法,但我很确定8(%eax)
部分意味着“地址存储在EAX中的地址后8个字节”,也就是说,它是相对于存储在寄存器中的地址。
英特尔语法中的近似等价物将是这样的(在我的头顶,所以这里完全有可能存在一些小错误......)
mov eax, a
mov DWORD PTR [eax+8], 99
答案 2 :(得分:1)
movl $_a, %eax // load the memory address of a into %eax
movl $99, 8(%eax) // jump 8 bytes and store number 99 (which is a[2])
在我看来,a
是 int 数组( int 在大多数平台中有4个字节)。因此,通过增加4个字节,您将访问数组的下一个项目。为此数组赋值的其他示例包括:
movl $10, (%eax) // store number 10 on the the first position: a[0]
movl $20, 4(%eax) // jump 4 bytes from the address loaded in %eax
// and store number 20 on the next position (a[1])