1

在以下代码段中:

int func()
{
    int a=7;
    return a;
}

值 7 是否存储在可执行文件中的代码段?还是在数据段还是在代码段?答案取决于操作系统还是编译器?

4

3 回答 3

3

每个可执行格式都有一些部分。其中之一是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

于 2013-05-16T05:10:47.580 回答
2

由于ais 隐式auto(即 is not externor 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

于 2013-05-16T05:09:29.450 回答
0

根据示例代码,变量“a”进入调用堆栈,用于存储局部变量以及函数调用信息,如程序计数器、返回地址等

于 2013-05-16T05:30:51.220 回答