本汇编代码中的"2 + 2"在哪里(由C中的gcc翻译)

Mor*_*lde 4 c assembly gcc

我写了这个简单的C代码

int main()
{
    int calc = 2+2;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我希望看到它在汇编中看起来如何,所以我使用它编译它 gcc

$ gcc -S -o asm.s test.c
Run Code Online (Sandbox Code Playgroud)

结果是大约65行(Mac OS X 10.8.3),我发现这些是相关的:

在此输入图像描述

2+2在这个代码中在哪里寻找我的?

编辑:

One part of the question hasn't been addressed.

If %rbp, %rsp, %eax are variables, what values do they attain in this case?

zwo*_*wol 11

你得到的几乎所有代码都是无用的堆栈操作.通过优化on(gcc -S -O2 test.c),你会得到类似的东西

main:
.LFB0:
    .cfi_startproc
    xorl    %eax, %eax
    ret
    .cfi_endproc
.LFE0:
Run Code Online (Sandbox Code Playgroud)

忽略以点开头或以冒号结尾的每一行:只有两个汇编指令:

    xorl %eax, %eax
    ret
Run Code Online (Sandbox Code Playgroud)

他们编码return 0;.(对一个寄存器进行异或操作会将其设置为全位 - 零.函数返回值%eax按照x86 ABI 进行寄存器.)与您的所有操作int calc = 2+2;都被丢弃为未使用.

如果您将代码更改为

int main(void) { return 2+2; }
Run Code Online (Sandbox Code Playgroud)

你宁愿得到

    movl $4, %eax
    ret
Run Code Online (Sandbox Code Playgroud)

4来自编译器进行加法本身而不是让生成的程序执行它(这称为常量折叠).

也许更有趣的是,如果您将代码更改为

int main(int argc, char **argv) { return argc + 2; }
Run Code Online (Sandbox Code Playgroud)

然后你得到

    leal    2(%rdi), %eax
    ret
Run Code Online (Sandbox Code Playgroud)

这是在运行时做一些真正的工作!在这种情况下%rdi,argc在64位ELF ABI中,保存函数的第一个参数. leal 2(%rdi), %eax是用于" %eax = %edi + 2"的x86汇编语言,并且这样做主要是因为更熟悉的add指令只接受两个参数,所以你不能用它来添加2 %rdi并将结果%eax放在一个指令中.(忽略现在%rdi和之间的区别%edi.)


She*_*tJS 10

编译器确定2+2 = 4并内联它.常量存储在第10行(the $4)中.要验证这一点,请将数学更改为2+3,您将看到$5

编辑:至于寄存器本身,%rsp是堆栈指针,%rbp是帧指针,%eax是一个通用寄存器