当我使用与寻址模式相同的表达式计算地址时,为什么 gdb 不向我显示 BSS 数组中的变化?

Why isn't gdb showing me the change in a BSS array when I calculate the address with the same expression as the addressing mode?

在 .bss 段中编写了具有大缓冲区的简单程序

h_vals:
    resq 99999

然后尝试增加一些数组单元格的值。

mov rcx, [h_vals+8*rax]
inc rcx
mov [h_vals+8*rax], rcx

仍然在 gdb 中看到在执行第三条指令之前和之后相同的值 (0)。

x/dg &h_vals &h_vals + 8 * $rax
0x6d68c0: 0

为什么当我尝试检查我存储的地址时仍然看到 0?

mov 显然确实移动了数据;如果失败,您的程序将出现段错误。

没有调试信息的符号的默认大小是 4 个字节。您可以使用 ptype h_vals 来检查 gdb 对它的看法。

记住 gdb 的语法像 C 一样工作,即使你正在调试 asm。在 C 中,向指针添加一些内容会偏移那么多元素,而不是那么多字节。

&h_vals &h_vals + 8 * $rax 未在 gdb 中评估您期望的地址。 (另外,我认为 &h_vals &h_vals 是一个错字,并不是你实际 运行。)

因为 gdb 认为 &h_vals 是一个 int*&h_vals + offset 将产生 4 * offset 的字节偏移量,就像 C 中的 h_vals[offset] 一样。所以你的地址在 gdb 中进行 x 挖掘实际上是 [h_vals + 8 * 4 * rax].

另一种检查方法:p /x &h_valsp /x $rax 分开。您可以自己计算并与您在 x/ 输出中看到的地址进行比较。


此处最安全的解决方案是转换为 char*:

x /dg  8 * $rax + (char*)&h_vals

或者:在 .c 中定义符号,以便编译器为它们生成调试信息(因为您不想手动执行)。

例如将 unsigned long h_vals[99999]; 放入您使用 gcc -c -g vars.c 编译的 .c 中,并将 link 生成的 .o 与 YASM 从您的 .asm.

创建的 .o