在以下代码段中:
int func()
{
int a=7;
return a;
}
值7的代码段是否存储在可执行文件中?或者它是在数据段还是在代码段中?答案取决于操作系统或编译器吗?
答案 0 :(得分:3)
每种可执行格式都有一些部分。其中一个是text
,包含程序集 - 二进制代码。其中一个是heap
,其中找到malloc
- ed数据,其中stack
存储了局部变量。还有其他几个,但现在没关系。以上三种在各地都很常见。
现在,像a
这样的本地数据驻留在堆栈上。在可执行文件中,该值存储在text
部分。
我在您的代码中添加了main
(返回0),使用-g
编译然后objdump -CDgS a.out
并搜索了0x424242
(我已经替换了您的{ {1}}具有在代码中随机出现的可能性较小的值。)
7
如您所见,00000000004004ec <func>:
int func()
{
4004ec: 55 push %rbp
4004ed: 48 89 e5 mov %rsp,%rbp
int a=0x42424242;
4004f0: c7 45 fc 42 42 42 42 movl $0x42424242,-0x4(%rbp)
return a;
4004f7: 8b 45 fc mov -0x4(%rbp),%eax
}
4004fa: 5d pop %rbp
4004fb: c3 retq
表示该值存储在生成的文件中。实际上,通过c7 45 fc 42 42 42 42
:
xxd
您可以在$ xxd a.out | grep 4242
00004f0: c745 fc42 4242 428b 45fc 5dc3 5548 89e5 .E.BBBB.E.].UH..
代码段中识别上述装配线。
答案 1 :(得分:2)
由于a
隐含auto
(即不是extern
或static
),因此会将其存储在call stack框架中。
实际上,编译器可能会优化:在您的情况下,在优化时,它可能会保留在寄存器中(或者是常量传播和常量折叠):不需要为{{1}分配调用堆栈槽}}
这当然是编译器,目标平台和操作系统相关的。对于GCC编译器,了解Gimple内部表示(通过a
或使用MELT probe)并查看生成的汇编代码(使用-fdump-tree-all
)
另请参阅this answer,其中提供了大量参考资料。
-fverbose-asm -S -O
):
gcc -S -fverbose-asm -O
所以你看到在你的特定情况下没有为 .globl func
.type func, @function
func:
.LFB0:
.cfi_startproc
movl $7, %eax #,
ret
.cfi_endproc
.LFE0:
.size func, .-func
使用额外的空间,它直接存储在7
中,它是寄存器(在ABI约定中定义)来保存其返回的结果。
值%eax
存储在7
机器指令内的机器代码中。执行movl
时,该7将加载到包含返回结果func
的注册表%eax
中。
答案 2 :(得分:0)
根据示例代码,变量“a”进入调用堆栈,放置存储局部变量以及函数调用信息,如程序计数器,返回地址等