在使用 Keil 编译基于 STM32F103 的 C 语言程序时,生成的汇编代码会有一些不同。STM32F103 是基于 ARM Cortex-M3 内核的微控制器,因为汇编语言是 ARM 汇编,而不是 x86 汇编。
示例 C 代码
假设我们有如下的简单 C 语言 for 循环代码:
void loop_example(void) {
for (int i = 0; i < 10; i++) {
// loop body
}
}
Keil 编译生成的 ARM 汇编代码
使用 Keil 编译器(如 ARMCC 或 ARMCLANG)编译上述代码,生成的汇编代码可能类似于以下内容。
loop_example PROC
; Setup the stack frame (if required)
PUSH {lr} ; Save the link register
; Initialize i = 0
MOVS r1, #0 ; r1 = i = 0
loop_start
; Compare i with 10
CMP r1, #10 ; Compare i with 10
BGE loop_end ; If i >= 10, jump to loop_end
; Loop body
; (Insert loop body code here)
; Increment i
ADDS r1, r1, #1 ; i++
; Jump back to start of loop
B loop_start
loop_end
; Clean up and return
POP {pc} ; Restore the link register and return
ENDP
解释
- 初始化:MOVS r1, #0 将寄存器 r1(用于变量 i)初始化为0。
- 条件判断:CMP r1, #10 将 r1 与10进行比较,BGE loop_end 如果 r1 大于或等于10,则跳转到 loop_end 结束循环。
- 循环体:在条件成立的情况下执行循环体代码(这里省略了具体的操作)。
- 增量:ADDS r1, r1, #1 增加 r1 的值,然后 B loop_start 跳回条件判断部分。
- 返回:POP {pc} 恢复链接寄存器并返回。
关于寄存器和指令
- MOVS: 将一个立即数加载到寄存器,并设置条件代码。
- CMP: 比较两个寄存器的值,并设置条件代码。
- BGE: 条件分支指令,当比较结果为大于或等于时跳转。
- ADDS: 将两个寄存器的值相加,并将结果存储到第一个寄存器,同时更新条件代码。
- PUSH 和 POP: 用于保存和恢复寄存器的值,特别是链接寄存器 lr。
注意事项
实际生成的汇编代码可能会根据具体的编译器优化选项和编写的 C 代码有所不同。
使用 Keil 编译器时,可以通过查看生成的 .asm 文件来查看编译后的汇编代码。(关于如何配置keil生成asm汇编文件,详见配置keil生成asm汇编文件)
同时可以看下这篇文章汇编 for循环