嵌入式开发交流网论坛
标题:
Cortex-M3寄存器组&汇编与C的接口
[打印本页]
作者:
若七年
时间:
2018-12-31 07:08
标题:
Cortex-M3寄存器组&汇编与C的接口
[attach]22148[/attach]
学uCOS的任务切换时涉及到汇编代码。为了能理解汇编代码,我在网上了解了Cortex-M3寄存器组、C与汇编的接口的知识,在这里分享给大家。
先来介绍Cortex-M3寄存器:
[attach]22149[/attach]
Cortex-M3拥有16个通用寄存器R0-R15。
R0-R12都是32位通用寄存器,用于数据操作。
R13是堆栈指针。在CM3处理器内核中共有两个堆栈指针,于是也就支持两个堆栈。当引用R13(SP)时,你引用到的是当前正在使用的那一个,另一个必须用特殊的指令来访问。两个堆栈分别是:
1、主堆栈指针(MSP):这是缺省的堆栈指针,它由OS内核、异常服务程序及需要特权访问的应用程序代码来使用。
2、进程堆栈指针(PSP):用于常规的应用程序代码。
R14是连接寄存器(LR)。在函数调用时存储返回的地址。
R15是程序计数器(PC)。指向当前程序的地址,如果修改它的值,就会改变程序的执行顺序(很多高级操作都在这)。
接下来介绍汇编与C的接口:
让C程序与汇编程序互相交互时,我们必须知道参数是如何传递的,以及值是如何返回的,这样才能在主调函数与子程序之间协调工作。这些交互机制在ARM中有明确的规定,由文档《ARM Architecture Procedure Call Standard(AAPCS,Ref5)》(我没有看过)给出。虽然没看官方的文档,我还是在百度上看了一下C与汇编混合编程,并做以下总结:1、发生函数调用时,入口参数依次通过R0-R3寄存器传递,其中R0传递第一个,R1传递第2个……,当超过4个参数时,其他参数通过栈传递。函数的返回值通过R0寄存器返回。在函数被调用前,R0-R3中的值会自动入栈。2、R4-R11为普通的通用寄存器,发生函数调用时,其中的数据不会自动入栈,如果被调函数需要使用这些寄存器,则需要由被调函数先将这些寄存器中数据入栈保存再使用这些寄存器。被调函数返回前,需要先将数据出栈回复R4-R11的值,然后再返回主调函数。3、R12(IP)可以记录对子程序的调用。R13-R15的作用在前一部分介绍过了,不再啰嗦
最后,我用C和汇编写了一个流水灯的程序,以此演示C语言调用汇编函数,其中LED亮灭的切换由汇编代码实现。以下附上部分代码:
/******************led.h*******************/
#ifndef __LED_H
#define __LED_H
#include "stm32f10x.h"
void
LED_Init
(
void
);
//GPIO
初始化
void
LED_Change
(
unsigned
char
index
);
//
汇编函数在
C
语言头文件中的声明
#endif
/*******
********
***main.c******
*************
/
#include "delay.h"
#include "led.h"
int
main
(
void
)
{
unsigned
char
index
=
1
;
delay_init
();
LED_Init
();
while
(
1
)
{
LED_Change
(
index
);
//
调用汇编函数,传递一个参数
index
=!
index
;
delay_ms
(
300
);
}
}
/******************led.s*******************/
;
全局函数
EXPORT
LED_Change
;
该文件定义的函数
;
常量
GPIOB_BASE
EQU
0x40010C00
;GPIOB
的基地址
GPIOB_BRR
EQU
GPIOB_BASE
+
0x14
;GPIOB_BRR
寄存器的地址
GPIOB_BSRR
EQU
GPIOB_BASE
+
0x10
;GPIOB_BSRR
寄存器的地址
GPIOE_BASE
EQU
0x40011800
;GPIOE
的基地址
GPIOE_BRR
EQU
GPIOE_BASE
+
0x14
;GPIOE_BRR
寄存器的地址
GPIOE_BSRR
EQU
GPIOE_BASE
+
0x10
;GPIOE_BSRR
寄存器的地址
LED_LIGHT
EQU
0x0020
;
代码产生指令
PRESERVE8
THUMB
AREA
CODE
,
CODE
,
READONLY
;LED
切换函数
LED_Change
CBZ
R0
,
LED1_Light
;
一个参数由
R0
传递,判断
R0
,如果值为
0
就跳转到
LED1_Light
LED2_Light
;
点亮
LED2
LDR
R1
,
=
GPIOE_BRR
;R1=GPIOE_BRR;//R1
中存
GPIOE_BRR
寄存器的地址
LDR
R2
,
=
LED_LIGHT
;R2=0x0020;
STR
R2
,
[
R1
]
;*R1=R2;
;
熄灭
LED1
LDR
R1
,
=
GPIOB_BSRR
LDR
R2
,
=
LED_LIGHT
STR
R2
,
[
R1
]
BX
LR
;
函数返回
LED1_Light
;
点亮
LED1
LDR
R1
,
=
GPIOB_BRR
LDR
R2
,
=
LED_LIGHT
STR
R2
,
[
R1
]
;
熄灭
LED2
LDR
R1
,
=
GPIOE_BSRR
LDR
R2
,
=
LED_LIGHT
STR
R2
,
[
R1
]
BX
LR
;
函数返回
NOP
END
;
汇编文件结束
效果如下:
[attach]22150[/attach]
欢迎光临 嵌入式开发交流网论坛 (http://www.dianzixuexi.com/bbs/)
Powered by Discuz! X3.2