开发环境:Keil5
工程目录:
一、汇编调用C——多数相加
使用汇编调用C,需要注意的是参数的传递。不同于X86的传参规则,在ARM体系中,如果形参的个数不超过4个,使用特殊寄存去R0~R3传递;而如果参数大于4个,就要将多出来的那部分参数使用堆栈传递。
压栈的之后移动位置指针,压栈顺序别忘了是最后一个参数先入栈->倒数第二个参数->,,,,
下面的代码实现了五个参数求和,首先使R0=0,R1=1,R2=2,R3=3,第五个参数使用栈传递,并移动堆栈指针。
(1)startup.s
Stack_Size EQU 0x100 ;初始化栈的大小为256B AREA STACK, NOINIT, READWRITE, ALIGN = 3 Stack_Mem SPACE Stack_Size __initial_sp PRESERVE8 THUMB AREA RESET, DATA, READONLY;中断向量表 DCD __initial_sp DCD Reset_Handler AREA RESET, DATA, READWRITE AREA Sum, CODE, READONLY ;声明一个叫Sum的代码段,可读 Reset_Handler PROC; ;复位函数,从这里开始执行 IMPORT main ;main函数不在此文件中,所以需要引入 IMPORT sum5 ;sum5函数不在此文件中,所以需要引入 CALLSUM5 MOV R0,#0 MOV R1,#1 MOV R2,#2 MOV R3,#3 MOV R4,#4 ;前4个参数使用R0~R3传递, STR R4,[SP, #-4]! ;第5个使用栈传递 BL sum5 ;调用c程序 LDR R0, = main BX R0 ;回到C的main函数 ENDP END
(2)main.c
int sum5(int a, int b, int c, int d, int e) { return (a+b+c+d+e); } int main(void) { return 0; }
二、C调用汇编——strcopy
逻辑上比较好理解,首先在汇编文件中定义C要调用的函数,然后在.c文件extern这个函数,调用即可。
(1)startup.s
AREA |.text|, CODE, READONLY ;声明一个叫|.text|的代码段,可读 Reset_Handler PROC IMPORT main ;main函数不在此文件中,所以需要引入 EXPORT Reset_Handler ;声明外部函数 LDR R0, =main BX R0 ALIGN ENDP AREA SCopy, CODE, READONLY EXPORT strcopy ;想要被外部调用,必须声明函数 strcopy LDRB R2,[R1],#1 ;B 代表一个字节,#1 代表 R1 的地址 1 STRB R2,[R0],#1 CMP R2,#0 ;0 是字符串额结束标志,比较R2和0就可以看到字符串是否结束 BNE strcopy ;跳转指令,不相等的时候跳转到上面,形成了循环 BX LR ;返回现场 END
(2)main.c
extern void strcopy(char *d, const char *s); int main(void) { const char srcstr[] = "ABCDEFGH";//0x41-0x48 char dststr[] = "abcdefgh";//0x61-0x68 strcopy(dststr, srcstr); return 0; }