自己试试看
起点:so.c
#define THIS_INTEGER 100
int newVariable = THIS_INTEGER;
void fun0 ( void )
{
static int hello;
hello = 100;
}
int fun1 ( void )
{
int hello;
hello = 100;
return(hello);
}
预处理器对定义进行搜索和替换
arm-none-eabi-gcc -save-temps -O2 -c so.c -o so.o
所以.i
# 1 "so.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "so.c"
int newVariable = 100;
void fun0 ( void )
{
static int hello;
hello = 100;
}
int fun1 ( void )
{
int hello;
hello = 100;
return(hello);
}
您可以看到 THIS_INTEGER 不再存在,它只是一个宏/定义它的目的是在这种情况下保持一个常量,以便如果您想更改它,您可以更改它的所有相关实例。但是编译器需要它可以实际编译的东西。
然后将预处理器输出 so.i 馈送到实际的编译器并生成汇编:so.s
.cpu arm7tdmi
.eabi_attribute 20, 1
.eabi_attribute 21, 1
.eabi_attribute 23, 3
.eabi_attribute 24, 1
.eabi_attribute 25, 1
.eabi_attribute 26, 1
.eabi_attribute 30, 2
.eabi_attribute 34, 0
.eabi_attribute 18, 4
.file "so.c"
.text
.align 2
.global fun0
.arch armv4t
.syntax unified
.arm
.fpu softvfp
.type fun0, %function
fun0:
@ Function supports interworking.
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 0, uses_anonymous_args = 0
@ link register save eliminated.
bx lr
.size fun0, .-fun0
.align 2
.global fun1
.syntax unified
.arm
.fpu softvfp
.type fun1, %function
fun1:
@ Function supports interworking.
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 0, uses_anonymous_args = 0
@ link register save eliminated.
mov r0, #100
bx lr
.size fun1, .-fun1
.global newVariable
.data
.align 2
.type newVariable, %object
.size newVariable, 4
newVariable:
.word 100
.ident "GCC: (GNU) 9.2.0"
它被输入到汇编器中,然后如果你反汇编,你会得到:
Disassembly of section .text:
00000000 <fun0>:
0: e12fff1e bx lr
00000004 <fun1>:
4: e3a00064 mov r0, #100 ; 0x64
8: e12fff1e bx lr
Disassembly of section .data:
00000000 <newVariable>:
0: 00000064
嗯,我曾希望静电能把它留在那里。对于正在初始化的全局变量,如果它不是.data,它将是.bss。然后在 .data 你
可以看到 100 (0x64)。但它与宏无关/定义宏/定义只是将实际值100放在实际编译的代码中。
对于另一种情况,在这里进行优化,堆栈上没有变量或任何类似的值被放置在返回寄存器中,所以在这种情况下它短暂地存在于寄存器中。
静态是否按预期工作,事后看来,它没有起作用。我希望我称之为本地全球。它是一个局部变量,但添加静态将其放入 .bss 或 .data 而不是堆栈,然后希望看到生成的代码然后将 100 放入变量中,然后将其放入 .data/.bss 区域,该区域当然未优化但更难阅读:
Disassembly of section .text:
00000000 <fun0>:
0: e52db004 push {r11} ; (str r11, [sp, #-4]!)
4: e28db000 add r11, sp, #0
8: e59f3018 ldr r3, [pc, #24] ; 28 <fun0+0x28>
c: e3a02064 mov r2, #100 ; 0x64
10: e5832000 str r2, [r3]
14: e1a00000 nop ; (mov r0, r0)
18: e1a00003 mov r0, r3
1c: e28bd000 add sp, r11, #0
20: e49db004 pop {r11} ; (ldr r11, [sp], #4)
24: e12fff1e bx lr
28: 00000000 andeq r0, r0, r0
0000002c <fun1>:
2c: e52db004 push {r11} ; (str r11, [sp, #-4]!)
30: e28db000 add r11, sp, #0
34: e24dd00c sub sp, sp, #12
38: e3a03064 mov r3, #100 ; 0x64
3c: e50b3008 str r3, [r11, #-8]
40: e51b3008 ldr r3, [r11, #-8]
44: e1a00003 mov r0, r3
48: e28bd000 add sp, r11, #0
4c: e49db004 pop {r11} ; (ldr r11, [sp], #4)
50: e12fff1e bx lr
Disassembly of section .data:
00000000 <newVariable>:
0: 00000064 andeq r0, r0, r4, rrx
Disassembly of section .bss:
00000000 <hello.4142>:
0: 00000000 andeq r0, r0, r0
具体来说:
c: e3a02064 mov r2, #100 ; 0x64
10: e5832000 str r2, [r3]
100 被放入一个寄存器,然后该寄存器值被写入内存中,来自 fun0 的本地全局 hello 位于 .bss 中。
宏/定义只是搜索和替换,预处理器将根据需要对宏的各个级别/层进行多次迭代,直到它们全部被替换,它们都不存在于预处理代码中。然后将其发送到编译器。
在这种情况下,VALUE 100 在最终输出中可见,但这取决于您如何使用它,以及它的表示方式或存储位置。