Cortex-M7——函数及中断异常调用过程

Cortex-M7——函数及中断异常调用过程

小狼@http://blog.csdn.net/xiaolangyangyang


一、函数调用过程

ARMv8架构下,函数参数是通过R0~R4寄存器传递的,如果参数超过4个,就要借助于栈进行参数传递。

int func(int a1, int a2, int a3, int a4, int a5, int a6)
{
	return a1 + a2 + a3 + a4 + a5 + a6;
}
 
void main(void)
{
	func(1, 2, 3, 4, 5, 6);
}

main()函数的汇编如下:

movs    r2, #0x6            ; 参数赋值,用于压栈
movs    r3, #0x5            ; 参数赋值,用于压栈
sub     sp, sp, #0x0C       ; 预留栈空间给参数
str     r2, [sp, #0x4]      ; 参数保存到栈
str     r3, [sp]            ; 参数保存到栈
movs    r2, #0x3            ; 参数赋值给r3
movs    r3, #0x4            ; 参数赋值给r2
movs    r1, #0x2            ; 参数赋值给r1
movs    r0, #0x1            ; 参数赋值给r0
bl      0x80A278            ; 调用func

func()函数的汇编如下:

push    {r4-r5, lr}         ; 函数用到r4/r5,将原值压栈,lr压栈
ldr     r4, [sp, #0x8]      ; 将栈保存的参数赋给r4
ldr     r5, [sp, #0x0C]     ; 将栈保存的参数赋给r5
add     r4, r5              ; r4=r4+r5
add     r3, r4              ; r3=r3+r4
add     r2, r3              ; r2=r2+r3
add     r1, r2              ; r1=r1+r2
add     r0, r1              ; r0=r0+r1
pop     {r4-r5, pc}         ; 恢复r4/r5,lr赋值给pc

以上函数对应点的栈结构图如下: 

综上所述,ARMv8体系结构下,函数调用流程如下:

1、func调用前:将参数写入R0~R3,大于4个以后的参数压栈;

2、func调用后:将LR、R4/R5压栈,将上个栈帧保存的参数复制到R4/R5进行使用;

3、func返回前:将返回值放入R0,恢复R4/R5,POP LR到PC(即函数返回);

4、func返回后:main函数读取R0中的返回值。


函数调用时硬件不会压栈,进行软件压栈:

1、进入函数后,首先将LR压栈(如果没有调用子函数,则LR不压栈);
2、参数大于4个时,调用函数将多余的参数压入本函数栈帧供被调用函数使用;
3、局部变量较少时,R寄存器处理,不开辟栈空间,变量较多时,调整SP指针预留空间;
4、函数退出时出栈,如果局部变量较多使用了栈,先调整SP释放变量预留空间;
5、函数退出时将栈中的LR值出栈到PC(如果没有调用子函数,直接将LR赋值给PC)。

二、中断异常调用过程

中断异常时硬件自动压栈:

1、中断和异常会进行硬件自动压栈,压栈顺序:xPSR、PC、LR、R12、R0~R3;
2、硬件压栈是在进入中断函数前进行,所以硬件压栈的LR寄存器是原LR,并非进入异常后的LR值(进异常后LR=EXC_RETURN,EXC_RETURN的值包括如下,其他值为非法值);
        0xFFFFFFF1:中断返回时从MSP恢复寄存器值,返回后进入Handler模式,使用MSP(中断返回到另一个中断);
        0xFFFFFFF9:中断返回时从MSP恢复寄存器值,返回后进入线程模式,使用MSP(不使用PSP只使用MSP堆栈的情况);
        0xFFFFFFFD:中断返回时从PSP恢复寄存器值,返回后进入线程模式,使用PSP(OS处理完中断后返回用户程序)。
3、中断函数退出时,执行# bx R14(LR)指令,该指令将LR赋值给PC,PC根据LR判断出栈到MSP还是PSP,恢复CPU模式,出栈内容与压栈内容相同(即将进入中断函数前硬件自动压栈内容出栈,其中包括LR和PC)。

  • 5
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
这段命令是 Keil uVision5 软件的 armclang 编译器的链接命令,用于将目标文件链接成可执行文件。这个命令包含了以下参数: - `--cpu Cortex-M7.fp.dp`:指定链接器使用的目标处理器。 - `*.o`:指定链接器需要链接的目标文件,`*.o` 表示链接当前目录下所有的 `.o` 目标文件。 - `--library_type=microlib`:指定链接器使用的库类型为 `microlib`。 - `--strict`:启用严格模式。 - `--scatter "STM32H747I_DISCO_CM7\Exe\STM32H747I_DISCO_CM7.sct"`:指定链接器使用的链接脚本文件。 - `--summary_stderr`:将链接器的摘要信息输出到标准错误流。 - `--info summarysizes`:输出链接器的摘要信息。 - `--map`:生成链接器映射文件。 - `--load_addr_map_info`:生成可加载地址映射信息。 - `--xref`:生成交叉引用表。 - `--callgraph`:生成函数调用图。 - `--symbols`:生成符号表。 - `--info sizes`:输出每个目标文件的大小信息。 - `--info totals`:输出总大小信息。 - `--info unused`:输出未使用的符号信息。 - `--info veneers`:输出使用的 Veneer 信息。 - `--list "STM32H747I_DISCO_CM7.map"`:将链接器的详细信息输出到指定的文件中。 - `-o STM32H747I_DISCO_CM7\Exe\STM32H747I_DISCO_CM7.axf`:指定链接器生成的可执行文件的名称和路径。 你可以根据需要进行调整,例如,修改链接器使用的目标处理器、库类型、链接脚本文件等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值