gpt4 book ai didi

assembly - 气体 : Explanation of . cfi_def_cfa_offset

转载 作者:行者123 更新时间:2023-12-02 00:20:39 27 4
gpt4 key购买 nike

我想要解释 GCC 生成的程序集中与 .cfi_def_cfa_offset 指令一起使用的值。我隐约知道 .cfi 指令涉及调用帧和堆栈展开,但我想更详细地解释为什么,例如,在编译以下 C 程序时 GCC 输出的程序集中使用值 16 和 8在我的 64 位 Ubuntu 机器上。

C 程序:

#include <stdio.h>

int main(int argc, char** argv)
{
printf("%d", 0);
return 0;
}

我在源文件 test.c 上调用了 GCC,如下所示:gcc -S -O3 test.c。我知道 -O3 可以实现非标准优化,但为了简洁起见,我想限制生成的程序集的大小。

生成的程序集:

        .file   "test.c"
.section .rodata.str1.1,"aMS",@progbits,1
.LC0:
.string "%d"
.text
.p2align 4,,15
.globl main
.type main, @function
main:
.LFB22:
.cfi_startproc
subq $8, %rsp
.cfi_def_cfa_offset 16
xorl %edx, %edx
movl $.LC0, %esi
movl $1, %edi
xorl %eax, %eax
call __printf_chk
xorl %eax, %eax
addq $8, %rsp
.cfi_def_cfa_offset 8
ret
.cfi_endproc
.LFE22:
.size main, .-main
.ident "GCC: (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2"
.section .note.GNU-stack,"",@progbits

为什么生成的程序集中的 .cfi_def_cfa_offset 指令使用值 16 和 8?另外,为什么局部函数开始和函数结束标签使用数字 22?

最佳答案

作为DWARF spec第 6.4 节中说:

[...] The call frame is identified by an address on the stack. We refer to this address as the Canonical Frame Address or CFA. Typically, the CFA is defined to be the value of the stack pointer at the call site in the previous frame (which may be different from its value on entry to the current frame).

main() 从其他地方调用(在 libc C 运行时支持代码中),并且在执行 call 指令时执行后,%rsp 将指向堆栈顶部(这是最低地址 - 堆栈向下增长),无论它是什么(具体是什么在这里并不重要):

:                :                              ^
| whatever | <--- %rsp | increasing addresses
+----------------+ |

此时%rsp的值是“调用站点的堆栈指针的值”,即规范定义的CFA。

当执行call指令时,它将把64位(8字节)返回地址压入堆栈:

:                :
| whatever | <--- CFA
+----------------+
| return address | <--- %rsp == CFA - 8
+----------------+

现在我们正在 main 运行代码,它执行 subq $8, %rsp 为自己保留另外 8 个字节的堆栈:

:                :
| whatever | <--- CFA
+----------------+
| return address |
+----------------+
| reserved space | <--- %rsp == CFA - 16
+----------------+

使用.cfi_def_cfa_offset指令在调试信息中声明堆栈指针的变化,您可以看到CFA现在距离当前堆栈指针偏移16个字节。

在函数末尾,addq $8, %rsp指令再次更改堆栈指针,因此插入另一个.cfi_def_cfa_offset指令以指示CFA现在距堆栈指针仅偏移 8 个字节。

(标签中的数字“22”只是一个任意值。编译器将根据一些实现细节(例如基本 block 的内部编号)生成唯一的标签名称。)

关于assembly - 气体 : Explanation of . cfi_def_cfa_offset,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7534420/

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