C与汇编深入分析 - 指南

1、汇编怎么调用C语言

1.1、直接调用

bl main

1.2、想传参数怎么办?

(1)在arm中有个ATPCS规则:ARM-THUMB procedure call standard(ARM-Thumb过程调用标准)。 约定r0-r15寄存器的用途:

  • r0-r3:调用者和被调用者之间传参数。
  • r4-r11:函数可能被使用,所以在函数的入口保存它们,在函数的出口恢复它们。

(2)示例代码:

int delay(unsigned int d)
{
	while (d--);
    return 0;
}

在汇编里调用delay:

ldr  r0, =1000000   /* 给delay函数传参数,保存在r0里 */
bl delay
cmp r0, #0          /* 返回值保存在r0中,比较返回值是否为0 */

1.3、寄存器与栈

(1)栈的作用:函数调用时,保存现场;函数返回时,恢复现场。

(2)函数传参和返回值会用到如上寄存器和栈。

2、程序下载到Flash中

2.1、反汇编示例

2.2、烧写在Flash上的内容

地址Flash内容
0x0800000000000000
0x0800000408000009
0x08000008f8dfd004
0x0800000cf000f80c
0x0800001020010000
0x08000014bf00b501
0x080000181e419800
…………

3.3、启动流程

上电后:

  • 设置栈:CPU会从0x08000000读取值,用来设置SP(我们的程序里再次设置了SP)
  • 跳转:CPU从0x08000004得到地址值,根据它的BIT0切换为ARM状态或Thumb状态,然后跳转
    • 对于cortex M3/M4,它只支持Thumb状态,所以0x08000004上的值bit0必定是1
    • 0x08000004上的值 = Reset_Handler + 1
  • 从Reset_Handler继续执行

3、汇编启动代码分析

(1)PRESERVE8

  • 解释:告诉汇编器当前文件保持 8 字节对齐,符合 ARM 的 AAPCS(ARM 架构过程调用标准)要求。
  • 作用:确保函数调用时栈是 8 字节对齐的,避免某些指令出错。

(2)THUMB

  • 解释:告诉汇编器接下来的代码是 THUMB 指令集(16 位压缩指令集),而不是 ARM 指令集(32 位)。
  • 作用:Cortex-M 系列只支持 THUMB 指令集,所以必须加这一句。

(3)AREA    RESET, DATA, READONLY

  • 解释:定义一个名为 RESET 的数据段,属性是只读(READONLY)。
  • 作用:这个段通常用来存放中断向量表(Vector Table),它会被链接器放到 Flash 的起始地址(0x00000000)。

(4)EXPORT  __Vectors

  • 解释:把 __Vectors 这个符号导出,让链接器或其他文件可以引用它。
  • 作用:链接器需要知道这个向量表的位置,以便正确放置到 Flash 开头。

(5)DCD     0

  • 解释:在向量表中定义第一个条目:初始主堆栈指针(MSP)的值。
  • 作用:芯片上电后,CPU 会自动把这里的值加载到 MSP 寄存器(R13寄存器)。实际使用中应该改成 RAM 顶地址,否则程序会崩溃。

(6)DCD     Reset_Handler              ; Reset Handler

  • 解释:定义向量表的第二个条目:复位中断向量。
  • 作用:芯片复位后,CPU 会跳转到 Reset_Handler 这个函数执行。

(7)AREA |.text|, CODE, READONLY

  • 解释:定义一个名为 .text 的代码段,属性是只读。
  • 作用:接下来的代码会被放到 Flash 中,作为程序指令。

(8)Reset_Handler   PROC

  • 解释:定义一个名为 Reset_Handler 的函数(过程)。
  • 作用:这是芯片复位后执行的第一个函数,负责初始化系统并跳转到 main()
  • PORC:告诉汇编器“一个函数从这里开始,与ENDP相对应

(9)EXPORT  Reset_Handler             [WEAK]

  • 解释:把 Reset_Handler 导出为弱符号(weak symbol)。
  • 作用:允许用户在其它文件中重新定义 Reset_Handler,覆盖这个默认版本。

(10)IMPORT  main

  • 解释:告诉汇编器 main 是一个外部符号(在 C 文件中定义)。
  • 作用:以便后面用 BL main 跳转到 C 程序的入口。

(11)LDR SP, =(0x20000000+0x30000)

  • 解释:设置主堆栈指针(MSP)为 0x20030000
  • 作用:0x20000000 是 SRAM 起始地址,+0x30000 表示栈顶地址为 192KB 偏移(具体取决于芯片 SRAM 大小)。
  • 注意: 如果芯片没有这么多 SRAM,这个值会出错。

(12)BL main

  • 解释:调用 C 语言的 main() 函数。
  • 作用:进入用户程序入口,开始执行应用逻辑。

(13)ENDP:告诉汇编器:这个函数到这里结束 。

(14)END:告诉汇编器:文件结束。

                PRESERVE8
                THUMB
; Vector Table Mapped to Address 0 at Reset
                AREA    RESET, DATA, READONLY
				EXPORT  __Vectors
__Vectors       DCD     0
                DCD     Reset_Handler              ; Reset Handler
				AREA    |.text|, CODE, READONLY
; Reset handler
Reset_Handler   PROC
				EXPORT  Reset_Handler             [WEAK]
                IMPORT  main
				LDR SP, =(0x20000000+0x30000)
				BL main
                ENDP
                 END

参考资料:

posted @ 2026-02-01 15:31  yangykaifa  阅读(2)  评论(0)    收藏  举报