在使用 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

解释

  1. 初始化:MOVS r1, #0 将寄存器 r1(用于变量 i)初始化为0。
  2. 条件判断:CMP r1, #10 将 r1 与10进行比较,BGE loop_end 如果 r1 大于或等于10,则跳转到 loop_end 结束循环。
  3. 循环体:在条件成立的情况下执行循环体代码(这里省略了具体的操作)。
  4. 增量:ADDS r1, r1, #1 增加 r1 的值,然后 B loop_start 跳回条件判断部分。
  5. 返回:POP {pc} 恢复链接寄存器并返回。

关于寄存器和指令

  • MOVS: 将一个立即数加载到寄存器,并设置条件代码。
  • CMP: 比较两个寄存器的值,并设置条件代码。
  • BGE: 条件分支指令,当比较结果为大于或等于时跳转。
  • ADDS: 将两个寄存器的值相加,并将结果存储到第一个寄存器,同时更新条件代码。
  • PUSH 和 POP: 用于保存和恢复寄存器的值,特别是链接寄存器 lr。

注意事项
实际生成的汇编代码可能会根据具体的编译器优化选项和编写的 C 代码有所不同。
使用 Keil 编译器时,可以通过查看生成的 .asm 文件来查看编译后的汇编代码。(关于如何配置keil生成asm汇编文件,详见配置keil生成asm汇编文件)

同时可以看下这篇文章汇编 for循环

06-13 15:24