在以下代码段中:
int func()
{
int a=7;
return a;
}
值 7 是否存储在可执行文件中的代码段?还是在数据段还是在代码段?答案取决于操作系统还是编译器?
在以下代码段中:
int func()
{
int a=7;
return a;
}
值 7 是否存储在可执行文件中的代码段?还是在数据段还是在代码段?答案取决于操作系统还是编译器?
每个可执行格式都有一些部分。其中之一是text
,包含汇编 - 二进制代码。其中之一是heap
找到malloc
-ed 数据的位置,而 on 是stack
存储局部变量的位置。还有其他几个,但现在不重要了。以上三者随处可见。
现在,像您这样的本地数据a
驻留在堆栈上。在可执行文件中,值存储在text
节中。
我已经main
在您的代码中添加了一个(返回 0),-g
然后编译objdump -CDgS a.out
并搜索0x424242
(我已经用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..
您可以在代码段中识别上述装配线xxd
。
由于a
is 隐式auto
(即 is not extern
or static
)它存储在调用堆栈帧中。
实际上,编译器可能会优化:在您的情况下,优化时,它可能会保留在寄存器中(或不断传播和不断折叠):无需为您分配调用堆栈槽a
这当然取决于编译器、目标平台和操作系统。对于GCC编译器,了解 Gimple 内部表示(通过-fdump-tree-all
,或使用MELT 探针)并查看生成的汇编代码(使用-fverbose-asm -S -O
)
另请参阅this answer,它提供了很多参考资料。
Linux/x86-64 上的 GCC 4.8 将您的函数编译(使用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
,它直接存储在%eax
寄存器(在 ABI 约定中定义)用于保存其返回结果的位置。
该值7
存储在movl
机器指令中的机器代码中。当func
被执行时,那个 7 被加载到%eax
包含返回结果的寄存器中func
。
根据示例代码,变量“a”进入调用堆栈,用于存储局部变量以及函数调用信息,如程序计数器、返回地址等