为什么rax寄存器中没有显示值?

问题描述 投票:0回答:1

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 $12, %rsp   /* allocate space for variable */
        push $3
        push $2
        push $1
        mov -4(%rbp), %rax
        mov %rbp, %rsp
        pop %rbp

我正在尝试了解有关堆栈的更多信息。我想使用1, 2, 3的偏移量从堆栈(rbp)访问一些变量。我的目标是将值压入rax,然后在调试器中检查寄存器。但是,当我这样做时:

(gdb) x/d $rax
0x0:    Cannot access memory at address 0x0
assembly x86-64 callstack att
1个回答
1
投票

push $3是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 $12, %rsp跳过的空间。高4字节从保存的RBP值的底部开始。这两件事都是0,因为Linux在初始化新进程时将它们清零了。

您从内存加载到RAX的值永远不会成为指针,因此,对于GDB的x命令来说,它作为arg没有意义。 x检查给定地址的内存。 would的意义是x /16gx $rsp在RSP之上转储16个qword。

还请注意,sub $12, %rsp看起来像是从32位代码中天真的移植过来的。这会使堆栈未对齐。在_start,它已经对齐了16。_startnot一个函数;没有什么叫它,你不能从它那里ret。您无需保存旧的RBP,甚至根本不需要使用RBP进行任何操作。通常,一个指向堆栈(RSP)的指针就足够了。

在确实被调用的函数的顶部,RSP-8将按16字节对齐,因此一按即可重新对齐堆栈。

© www.soinside.com 2019 - 2024. All rights reserved.