gpt4 book ai didi

c - 如果C文件只有一个函数,为什么开头的pushq和movq还存在?

转载 作者:行者123 更新时间:2023-11-30 16:19:05 26 4
gpt4 key购买 nike

我已经学习 AT&T 汇编几个月了,我发现很难理解 .s 文件中的一些重复指令。特别是,

main:
pushq %rbp
movq %rsp, %rbp

来 self 的书using ,我得出结论,pushq将调用函数的64位地址压入调用堆栈,或者保存;而 movq 将 %rsp 寄存器中的值(我认为是地址)复制到 %rbp 寄存器。也就是说,它们都包含栈基地址。

此外,其他来源(感谢 Govind)也很好地解释了这个问题: What is the purpose of the RBP register in x86_64 assembler?

我明白了,我已经知道 Pushq %rbp 保存调用者的帧指针或保存前一个堆栈帧的地址,但如果这是我在 C 程序中调用的唯一函数,那么“前一个堆栈帧”是什么然后?比如,在我的主函数调用之前 %rbp 中存储了什么?

例如,如果我的主函数调用一个名为 foo() 的函数,那么我的 .S 文件中的 asm 代码将如下所示:

foo:

pushq %rbp
movq %rsp, %rbp

#whatever instruction

ret

在这种情况下,我知道什么被插入%rbp(main中调用指令的地址)。然后保存它是有意义的,因为我们需要返回到主函数(w/ret)。但是,如果 main 是 C 中唯一的函数,为什么我们必须在 main 中执行此操作呢?

最佳答案

这两行是函数序言的一部分,用于设置新的堆栈(或激活)帧。第一个,pushq %rbp将基指针压入堆栈。第二个,movq %rsp, %rbp将基指针移动到堆栈指针。至少应该有另一行,我们从堆栈点中减去一些值,这具有向下移动堆栈点的效果。

回想一下,在 Intel 平台上,堆栈向下增长,基指针 (rbp) 表示堆栈底部,而堆栈指针 (rsp) 指向堆栈顶部。

现在,在 64 位机器上,有更多的寄存器,因此减少了对使用堆栈进行临时存储的依赖,因此这些指令可能不会出现在 64 位代码上。

这些说明是调用约定的一部分,或者是如何调用函数的一部分,您的书应该描述调用函数所需的内容。但请注意,32 位 Intel 和 64 位 Intel 之间在函数调用方式方面存在差异。

我们返回的地址(rip 中的值 - 指令指针)由调用者压入堆栈,并且不会在被调用者代码中看到。通常,您可以通过 call <fnct_name> 调用函数但是,这可以用以下序列替换:

 pushq %rip
jmp <fnct_address>

(可能语法错误 - 我不太使用 AT&T 语法)。

现在,我们对堆栈所做的操作需要在函数 Epilog 中取消,因此我们基本上向堆栈点添加一些值(即将堆栈指针移回到我们开始的位置),弹出 ebp堆栈,以便基指针返回到调用者中的位置,然后我们弹出 eip,以便程序知道在哪里恢复执行。

关于c - 如果C文件只有一个函数,为什么开头的pushq和movq还存在?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55711485/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com