使用的C代码如下:
GPIO_TypeDef *gGpio = GPIOA;
GPIO_TypeDef *const gcGpio = GPIOA;
int main(void)
{
GPIO_TypeDef *gpio = GPIOA;
gpio->BRR = 4;
gGpio->BRR = 6;
gcGpio->BRR = 5;
GPIOA->BRR = 7;
while(1);
}
编译后生成的主要汇编代码如下:
-----------------------------------1------------------------
102: GPIO_TypeDef *gpio = GPIOA;
0x08000612 4807 LDR r0,[pc,#28] ; @0x08000630
103: gpio->BRR = 4;
0x08000614 2104 MOVS r1,#0x04
0x08000616 6141 STR r1,[r0,#0x14]
-----------------------------------1------------------------
-----------------------------------2------------------------
104: gGpio->BRR = 6;
0x08000618 2106 MOVS r1,#0x06
0x0800061A 4A06 LDR r2,[pc,#24] ; @0x08000634
0x0800061C 6812 LDR r2,[r2,#0x00]
0x0800061E 6151 STR r1,[r2,#0x14]
-----------------------------------2------------------------
-----------------------------------3------------------------
105: gcGpio->BRR = 5;
0x08000620 2105 MOVS r1,#0x05
0x08000622 4A03 LDR r2,[pc,#12] ; @0x08000630
0x08000624 3214 ADDS r2,r2,#0x14
0x08000626 6011 STR r1,[r2,#0x00]
-----------------------------------3------------------------
-----------------------------------4------------------------
106: GPIOA->BRR = 7;
0x08000628 2107 MOVS r1,#0x07
0x0800062A 6011 STR r1,[r2,#0x00]
-----------------------------------4------------------------
107: while(1);
0x0800062C BF00 NOP
0x0800062E E7FE B 0x0800062E
对于局部变量gpio:从生成的汇编代码块1,可看出包括自身初始化共生成3句汇编代码。
对于全局变量gGpio:从生成的汇编代码块2,可看出不包括自身初始化共生成4句汇编代码。
对于全局const变量gcGpio:从生成的汇编代码块3,可看出不包括自身初始化代码共生成4句汇编代码。
对于宏定义GPIOA:从生成的汇编代码块4,可看出只生成2句汇编代码。
从以上结果,看上去宏定义最快,但实际可能并非如此。以下为分析:
生成的汇编代码块4中所使用的寄存器r2,初值来自汇编代码块3 。所以我们无法确定各自到底会生成多少代码,我们修改下C文件重新生成下汇编代码。
修改后的C源码:
GPIO_TypeDef *gGpio = GPIOA;
GPIO_TypeDef *const gcGpio = GPIOB;
int main(void)
{
GPIO_TypeDef *gpio = GPIOC;
gpio->BRR = 4;
gGpio->BRR = 6;
gcGpio->BRR = 5;
GPIOD->BRR = 7;
while(1);
}
我们分别使用不同的宏来初始化不同的变量。得到的汇编如下:
----------------------------------1-------------------------------------
102: GPIO_TypeDef *gpio = GPIOC;
0x08000612 4807 LDR r0,[pc,#28] ; @0x08000630
103: gpio->BRR = 4;
0x08000614 2104 MOVS r1,#0x04
0x08000616 6141 STR r1,[r0,#0x14]
----------------------------------1-------------------------------------
----------------------------------2-------------------------------------
104: gGpio->BRR = 6;
0x08000618 2106 MOVS r1,#0x06
0x0800061A 4A06 LDR r2,[pc,#24] ; @0x08000634
0x0800061C 6812 LDR r2,[r2,#0x00]
0x0800061E 6151 STR r1,[r2,#0x14]
----------------------------------2-------------------------------------
----------------------------------3-------------------------------------
105: gcGpio->BRR = 5;
0x08000620 2105 MOVS r1,#0x05
0x08000622 4A05 LDR r2,[pc,#20] ; @0x08000638
0x08000624 6011 STR r1,[r2,#0x00]
----------------------------------3-------------------------------------
----------------------------------4-------------------------------------
106: GPIOD->BRR = 7;
0x08000626 2107 MOVS r1,#0x07
0x08000628 4A04 LDR r2,[pc,#16] ; @0x0800063C
0x0800062A 6011 STR r1,[r2,#0x00]
----------------------------------4-------------------------------------
从当前数据可得出结论:define = gcGpio <= gpio < gGpio 。
即:宏定义和const变量较快,其次是局部变量,全局变量最慢。且全局变量使用两次LDR指令,第一次同其他三种一样都是从Load Area取得当前所需要的值(变量地址)。第二次则变为从RAM中获取值(变量值)。
另,经验证,再不开启优化的情况下。使用base + offset = *(base + offset)的格式,生成的汇编代码比较精简。若使用结构体的指针格式,生成的汇编代码可能会多次进行基址记载和索引操作,比较臃肿。