Ere*_*evi 1 c++ assembly x86-64 llvm clang
我创建了一个最小的C++程序:
int main() {
return 1234;
}
Run Code Online (Sandbox Code Playgroud)
并使用clang ++ 5.0编译它并禁用优化(默认值-O0).生成的汇编代码是:
pushq %rbp
movq %rsp, %rbp
movl $1234, %eax # imm = 0x4D2
movl $0, -4(%rbp)
popq %rbp
retq
Run Code Online (Sandbox Code Playgroud)
我理解大多数行,但我不明白"movl $ 0,-4(%rbp)".似乎程序将一些局部变量初始化为0.为什么?
什么编译器内部细节导致此存储不对应源中的任何内容?
TL; DR:在未经优化的代码中,您的CLANG ++为返回值留出4个字节,main并根据C++(包括C++ 11)标准将其设置为零.它生成了main不需要它的函数的代码.这是未被优化的副作用.通常,未经优化的编译器将生成它可能需要的代码,然后最终不需要它,并且没有做任何事情来清理它.
因为您正在编译,-O0所以对代码进行了极少的优化(-O0可能会删除死代码等).试图理解未经优化的代码中的工件通常是浪费的练习.未经优化的代码的结果是额外的加载和存储以及原始代码生成的其他工件.
在这种情况下main是特殊的,因为在C99/C11和C++中,标准有效地说当到达外部块时main,默认返回值为0. C11标准说:
5.1.2.2.3程序终止
1如果main函数的返回类型是与int兼容的类型,则从初始调用到main函数的返回等效于调用exit函数,其中main函数返回的值作为其参数; 11)到达}终止main函数返回值0.如果返回类型与int不兼容,则未指定返回到主机环境的终止状态.
在C++ 11标准说:
3.6.1主要功能
5)main中的return语句具有离开main函数(销毁具有自动存储持续时间的任何对象)并以返回值作为参数调用std :: exit的效果.如果控制到达main的末尾而没有遇到return语句,则效果就是执行
Run Code Online (Sandbox Code Playgroud)return 0;
在CLANG ++版本中,您使用未优化的64位代码,默认情况下返回值为0 dword ptr [rbp-4].
问题是你的测试代码有点太微不足道了,看看这个默认的返回值是如何发挥作用的.这是一个应该是更好演示的示例:
int main() {
int a = 3;
if (a > 3) return 5678;
else if (a == 3) return 42;
}
Run Code Online (Sandbox Code Playgroud)
此代码有两个退出显式退出点return 5678,return 42;但return在函数末尾没有最后一个.如果}达到,则默认为返回0.如果我们检查godbolt输出,我们会看到:
main: # @main
push rbp
mov rbp, rsp
mov dword ptr [rbp - 4], 0 # Default return value of 0
mov dword ptr [rbp - 8], 3
cmp dword ptr [rbp - 8], 3 # Is a > 3
jle .LBB0_2
mov dword ptr [rbp - 4], 5678 # Set return value to 5678
jmp .LBB0_5 # Go to common exit point .LBB0_5
.LBB0_2:
cmp dword ptr [rbp - 8], 3 # Is a == 3?
jne .LBB0_4
mov dword ptr [rbp - 4], 42 # Set return value to 42
jmp .LBB0_5 # Go to common exit point .LBB0_5
.LBB0_4:
jmp .LBB0_5 # Extraneous unoptimized jump artifact
# This is common exit point of all the returns from `main`
.LBB0_5:
mov eax, dword ptr [rbp - 4] # Use return value from memory
pop rbp
ret
Run Code Online (Sandbox Code Playgroud)
可以看出,编译器已生成一个公共出口点,用于设置堆栈地址的返回值(EAX)dword ptr [rbp-4].在代码的开头dword ptr [rbp-4]显式设置为0.在更简单的情况下,未优化的代码仍然生成该指令但未使用.
如果使用该选项构建代码,则-ffreestanding应该看到默认返回值main不再设置为0.这是因为默认返回值0的要求main适用于托管环境而不是独立环境.
| 归档时间: |
|
| 查看次数: |
185 次 |
| 最近记录: |