为什么没有值显示在 rax 寄存器中?
Why is no value showing up in the rax register?
AT&T 语法,x86-64:
.text
.globl _start
_start:
push %rbp /* push base pointer on stack */
mov %rsp, %rbp /* base pointer points to top of the stack */
sub , %rsp /* allocate space for variable */
push
push
push
mov -4(%rbp), %rax
mov %rbp, %rsp
pop %rbp
我正在尝试了解有关堆栈的更多信息。我想使用 rbp
的偏移量从堆栈 (1, 2, 3
) 访问一些变量。我的目标是将值推入 rax
,然后在调试器中检查寄存器。但是,当我这样做时:
(gdb) x/d $rax
0x0: Cannot access memory at address 0x0
push
是 64 位推送。 How many bytes does the push instruction push onto the stack when I don't specify the operand size?
但这并不重要,因为在执行第一次推送之前,您已将 RSP 移动到保存的 RBP 值(RBP 指向的位置)下方 12 个字节处。
在静态可执行文件 运行 中的进程启动时 Linux,即在 _start
您显然构建程序的方式中,所有寄存器(RSP 除外)都清零,并且初始 RSP 下方的堆栈内存开始清零。这不是 ABI 官方保证的,但实际上 Linux 是如何工作的。这就是你加载零的原因。
mov -4(%rbp), %rax
加载 8 个字节。该负载的低 4 字节来自您用 sub , %rsp
跳过的 space。高 4 字节从保存的 RBP 值的底部开始。这两件事都是 0
因为 Linux 在初始化新进程时将它们归零。
你从内存加载到 RAX 的值永远不会是一个指针,所以它作为 GDB 的 x
命令的参数没有意义。 x
检查给定地址的内存。 有意义的是 x /16gx $rsp
在 RSP 之上转储 16 个 qword。
另请注意,sub , %rsp
看起来像是天真地从 32 位代码移植过来的。 这会使堆栈错位。在 _start
处,它已经对齐了 16。_start
是 不是 函数;没有任何名称,您不能从中 ret
。您不需要保存旧的 RBP,甚至根本不需要对 RBP 做任何事情;一个指向堆栈的指针 (RSP) 通常就足够了。
在确实被调用的函数的顶部,RSP-8 将按 16 字节对齐,因此一次推送将重新对齐堆栈。
AT&T 语法,x86-64:
.text
.globl _start
_start:
push %rbp /* push base pointer on stack */
mov %rsp, %rbp /* base pointer points to top of the stack */
sub , %rsp /* allocate space for variable */
push
push
push
mov -4(%rbp), %rax
mov %rbp, %rsp
pop %rbp
我正在尝试了解有关堆栈的更多信息。我想使用 rbp
的偏移量从堆栈 (1, 2, 3
) 访问一些变量。我的目标是将值推入 rax
,然后在调试器中检查寄存器。但是,当我这样做时:
(gdb) x/d $rax
0x0: Cannot access memory at address 0x0
push
是 64 位推送。 How many bytes does the push instruction push onto the stack when I don't specify the operand size?
但这并不重要,因为在执行第一次推送之前,您已将 RSP 移动到保存的 RBP 值(RBP 指向的位置)下方 12 个字节处。
在静态可执行文件 运行 中的进程启动时 Linux,即在 _start
您显然构建程序的方式中,所有寄存器(RSP 除外)都清零,并且初始 RSP 下方的堆栈内存开始清零。这不是 ABI 官方保证的,但实际上 Linux 是如何工作的。这就是你加载零的原因。
mov -4(%rbp), %rax
加载 8 个字节。该负载的低 4 字节来自您用 sub , %rsp
跳过的 space。高 4 字节从保存的 RBP 值的底部开始。这两件事都是 0
因为 Linux 在初始化新进程时将它们归零。
你从内存加载到 RAX 的值永远不会是一个指针,所以它作为 GDB 的 x
命令的参数没有意义。 x
检查给定地址的内存。 有意义的是 x /16gx $rsp
在 RSP 之上转储 16 个 qword。
另请注意,sub , %rsp
看起来像是天真地从 32 位代码移植过来的。 这会使堆栈错位。在 _start
处,它已经对齐了 16。_start
是 不是 函数;没有任何名称,您不能从中 ret
。您不需要保存旧的 RBP,甚至根本不需要对 RBP 做任何事情;一个指向堆栈的指针 (RSP) 通常就足够了。
在确实被调用的函数的顶部,RSP-8 将按 16 字节对齐,因此一次推送将重新对齐堆栈。