全局变量非常量初始化执行时机及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
相关产品推荐
相关产品推荐

