- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我已经学习 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/
是: PUSHQ %reg POPFQ 在 x86_64 上设置标志的最直接方法? 最佳答案 这一切都取决于旗帜。 一些标志允许您直接设置位。例如,STC设置进位标志,CLC清除进位标志。如果你想操纵
我是一名优秀的程序员,十分优秀!