当我使用与寻址模式相同的表达式计算地址时,为什么 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_vals
和 p /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
在 .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_vals
和 p /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.