这是一个简单的C代码
#include <stdio.h>
int a = 5;
static int b = 20;
int main(){
int c = 30;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译为无需优化的组合:
.section __TEXT,__text,regular,pure_instructions
.macosx_version_min 10, 13
.globl _main ## -- Begin function main
.p2align 4, 0x90
_main: ## @main
.cfi_startproc
## %bb.0:
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
xorl %eax, %eax
movl $0, -4(%rbp)
movl $30, -8(%rbp)
popq %rbp
retq
.cfi_endproc
## -- End function
.section __DATA,__data
.globl _a ## @a
.p2align 2
_a:
.long 5 ## 0x5
Run Code Online (Sandbox Code Playgroud)
我的问题是static int b = 20;上面的装配在哪里?我知道他们应该在内存的全局部分,但我在编译版本中找不到它.
您的代码不使用b,并且它是文件范围的,因此其他文件中的任何内容都无法使用它.GCC不打算为它发出定义.
回答标题问题:带有非零初始值设定项的
非const静态/全局变量(即静态存储类)变量将进入.section .data,而不是.bss(零初始化可变),或.rdata(Windows)/ .rodata(Linux)非 - 零只读数据.
gcc没有完全的脑卒中模式,可以天真地音译. 请参阅在GCC中禁用所有优化选项 - GCC始终必须通过其内部表示进行转换.
GCC总是这样,留下了未使用的东西,甚至在一通-O0.有可能是禁用,不像一些其他的转换GCC甚至在做的一种方式-O0.
gcc和铿锵-O0编译每个语句ASM的一个单独的块存储/重新加载一切(为一致调试),但块GCC内仍然适用的标准转化,就像(x+y) < x成为y<0了签署x和y 与gcc8和更新,或者x / 10到乘法+高位移位.(为什么GCC在实现整数除法时使用乘以一个奇数?).
并且内部代码if(false)被gcc删除-O0,因此你不能jump在GDB中使用它.
有些人关心调试版本的运行时性能,尤其是游戏或操作系统等实时软件的开发人员,如果运行速度太慢,则无法正常测试.(游戏中的人机交互,或操作系统中的设备驱动程序.)
其他一些编译器更多的是脑力-O0,所以你经常看到asm看起来更像是源表达式.我想我已经看到没有优化的MSVC发出指令,这些指令mov在一个寄存器中进行了修改,然后cmp reg,imm,即在运行时只做依赖于立即的分支,因此可以在编译时在该表达式内进行计算.
当然还有真正的非优化编译器,其整个目标只是用固定模式进行音译.例如,我认为Tiny C编译器几乎是一次通过,并且随着它的发展而发出asm(或机器代码).请参阅Tiny C编译器生成的代码会发出额外的(不必要的?)NOP和JMP显示它是多么简单:它总是发出一个sub esp, imm32函数序列,只有在它知道了多少函数的结尾时才返回填充函数的末尾堆叠功能需求.即使答案为零,也无法将其删除并收紧代码.
无论如何,查看优化的asm通常更有趣.编写带有args并返回值的函数,这样你就可以看到asm的有趣部分而没有很多样板和存储/重载噪声. 如何从GCC /铿锵声组件输出中消除"噪音"?
| 归档时间: |
|
| 查看次数: |
359 次 |
| 最近记录: |