You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

全局变量非常量初始化执行时机及ARM汇编代码解析

全局变量非常量初始化的执行时机与ARM裸机汇编解析

问题核心

全局变量的非常量初始化代码何时、如何执行?以如下代码为例,变量c的计算是在main执行前完成,还是当main中执行到ldr r0, [r3]时才触发初始化?

C++代码示例

#include <cstdio>

int a = 2;
int b = 5;
int c = a * b;

int main() {    
    return c;
}

对应ARM裸机汇编代码

main:
  ldr r3, .L3
  ldr r0, [r3]
  bx lr
.L3:
  .word .LANCHOR0
_GLOBAL__sub_I_a:
  ldr r2, .L6
  ldr r3, [r2]
  ldr r2, [r2, #4]
  mul r3, r2, r3
  ldr r1, .L6+4
  str r3, [r1]
  bx lr
.L6:
  .word .LANCHOR1
  .word .LANCHOR0
a:
  .word 2
b:
  .word 5
c:

汇编代码解析与执行时机说明

1. 关键符号与函数作用

  • a:、b::全局变量的存储位置,分别预存常量值2和5;c:是预留的内存位置,初始无值。
  • _GLOBAL__sub_I_a:编译器自动生成的全局初始化函数,负责计算a*b并赋值给c:
    • .L6存储了两个地址:.LANCHOR1对应a的起始地址,.LANCHOR0对应c的起始地址。
    • 函数内先加载a的值,再通过a的地址+4(ARM中int占4字节)读取b的值,相乘后将结果写入c的内存位置。

2. 执行时机

在ARM裸机环境中,这类全局初始化函数会被编译器放入专门的初始化段(如.init_array)。程序启动时,进入main函数之前,系统启动代码(如crt0.s)会遍历该段中的所有函数指针,依次调用这些初始化函数。也就是说,_GLOBAL__sub_I_a会在main执行前就完成c的计算与赋值。

main函数中的逻辑只是直接读取c的内存值返回,并不会触发初始化函数的调用:

  • .L3中存储的是c的地址,ldr r3, .L3加载c的地址到r3寄存器;
  • ldr r0, [r3]直接从c的内存位置读取已经计算好的值,最后返回该值。

3. 汇编阅读要点

  • 锚点符号(.LANCHOR0、.LANCHOR1)是编译器用来标记变量地址的辅助符号,对应全局变量的内存起始位置;
  • .word伪指令用于在内存中存储地址或常量值;
  • ldr指令用于从内存加载数据到寄存器,str指令用于将寄存器数据写入内存;
  • bx lr是ARM中返回调用者的指令,lr寄存器存储了函数调用的返回地址。

结论

变量c的计算是在main函数执行前就完成的,main中的代码仅读取已初始化好的c值,不会触发初始化逻辑。

内容的提问来源于stack exchange,提问作者DEKKER

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 05:06:42