这是一个简单的C代码
#include <stdio.h>
int a = 5;
static int b = 20;
int main(){
int c = 30;
return 0;
}
编译成assebly,没有优化:
.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
我的问题是 static int b = 20;
在上面的程序集中在哪里?
我知道它们应该位于内存的全局部分,但我在编译版本中找不到它。
最佳答案
您的代码不使用 b
,并且它是文件范围的,因此其他文件中的任何内容都不能使用它。 GCC 不会为它发布定义。
回答标题问题:
非const
具有非零初始值设定项的静态/全局变量(即静态存储类)变量将进入 .section .data
,而不是 .bss
(零初始化可变),或 .rdata
( window )/.rodata
(Linux) 用于非零只读数据。
gcc 没有天真地音译为 asm 的完全 braindead 模式。参见 Disable all optimization options in GCC - GCC 始终必须通过其内部表示进行转换。
即使在 -O0
处,GCC 总是会遗漏未使用的内容.与 gcc 甚至在 -O0
时所做的一些其他转换不同,可能 可以禁用它.
gcc 和 clang -O0
将每个语句编译为单独的 asm block ,存储/重新加载所有内容(for consistent debugging),但在该 block 内 gcc 仍然应用其标准转换,如 (x+y) < x
成为y<0
对于有符号的 x 和 y with gcc8 and newer , 或 x / 10
变成高半部分的乘法+移位。 (Why does GCC use multiplication by a strange number in implementing integer division?)。
里面的代码if(false)
即使在 -O0
也被 gcc 删除, 所以你不能 jump
到 GDB 中。
有些人关心调试版本的运行时性能,尤其是游戏或操作系统等实时软件的开发人员,如果运行速度太慢则无法正确测试。 (游戏中的人机交互,或者操作系统中的设备驱动程序。)
其他一些编译器在 -O0
处比较脑残,因此您经常会看到看起来更像源表达式的 asm。我想我已经看到没有优化的 MSVC 发出执行 mov
的指令-立即进入寄存器,然后cmp reg,imm
,即在运行时执行一个仅依赖于立即数的分支,因此可以在编译时在该表达式中简单地计算出来。
当然也有真正非优化的编译器,它们的全部目标只是用固定模式进行音译。例如,Tiny C Compiler我认为几乎是一次通过,并在进行时发出 asm(或机器代码)。参见 Tiny C Compiler's generated code emits extra (unnecessary?) NOPs and JMPs显示它是多么简单:它总是发出一个 sub esp, imm32
在函数序言中,只有在知道函数需要多少堆栈后才会回来填充函数末尾的立即数。即使答案为零,也无法将其删除并收紧代码。
无论如何,查看优化的 asm 通常更有趣。编写接受 args 并返回值的函数,这样您就可以看到 asm 的有趣部分,而无需大量样板和存储/重新加载噪音。 How to remove "noise" from GCC/clang assembly output?
关于c - 静态值存储在程序集中的什么位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54642429/