c - 静态值存储在程序集中的什么位置

标签 c assembly

这是一个简单的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/

相关文章:

c - 使用 unix shell 测试系统的字节顺序

c - 通过 mmap 配置焊盘

c - 初始化 - C 中的多维数组

C: "invalid use of undefined type ‘struct X’ & 取消引用指向不完整类型的指针”错误

assembly - 关于汇编CF(进位)和OF(溢出)标志

c - ARM 检测中断何时占用过多 CPU 时间

c - 格式化带有多个百分号的字符串

assembly - 机器指令和汇编指令有什么区别?

c - 具有 64 位立即值的长模式(64 位)相对调用

c - 你如何解读这个集会?