标题:
C程序和汇编程序相互调用
[打印本页]
作者:
51黑tt
时间:
2016-3-6 13:06
标题:
C程序和汇编程序相互调用
为了使单独编译的C语言程序和汇编程序之间能够相互调用,必须为子程序间的调用规定一定的规则。ATPCS(ARM/Thumb Procedure Call Standard) ,是ARM程序和Thumb程序中子程序调用的基本规则,它规定了一些子程序间调用的基本规则,如想了解更多的规则,可以查看上一篇中关于ATPCS的介绍。
高级语言函数与汇编语言函数的混合调用也要遵循ATPCS规则,保证程序调用时参数的正确传递。
当在C语言程序中调用汇编程序时,在汇编程序中使用EXPORT伪指令声明本子程序,使其它程序可以调用此子程序;而在C语言程序中使用extern关键字声明外部函数(声明要调用的汇编子程序),即可调用此汇编子程序。
当在汇编程序中调用C语言程序时,在C程序中不需要使用任何关键字来声明将被汇编语言调用的C程序,但是在汇编程序调用该C程序之前需要在汇编语言程序中使用IMPORT伪操作来声明该C程序。在汇编程序中通过BL指令来调用子程序。
下面给出两个例子来介绍函数相互调用。
// C程序
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//定义LED端口寄存器
#define rGPFCON (*(volatile unsigned *)0x56000050) //Port F control
#define rGPFDAT (*(volatile unsigned *)0x56000054) //Port F data
#define rGPFUP (*(volatile unsigned *)0x56000058) //Pull-up control F
extern void delay(int times); //声明要调用的汇编子程序
extern void strcpydiy(char *dest, const char *src); //声明要调用的汇编子程序
extern int callsum(void ); //声明要调用的汇编子程序
int sumdiy(int a, int b, int c, int d, int e)
{
return(a+b+c+d+e);
}
void xmain(void)
{
int temp;
const char *strsrc = "First string source";
char strdest[] = "Scend string source";
printf("Before copying ...:\n");
printf("%s...%s...\n",strdest,strsrc);
strcpydiy(strdest, strsrc);
printf("After copying ...\n");
printf("%s...%s...\n",strdest,strsrc);
temp = callsum();
#if 0
if (temp == 15)
{
printf("the sum is :%d\n",temp);
rGPFCON=(rGPFCON|0xFF00)&0x55FF; //GPF4--GPF7设置为output
rGPFUP|=0xF0; //disable GPF pull up
rGPFDAT=(rGPFDAT&0x0F)|0x70;//GPF7 output 0
while(1);
}
#endif
#if 0
if(strcmp(strdest,strsrc) == 0)
{
rGPFCON=(rGPFCON|0xFF00)&0x55FF;//GPF4--GPF7设置为output
rGPFUP|=0xF0; //disable GPF pull up
rGPFDAT=(rGPFDAT&0x0F)|0x70; //GPF7 output 0
while(1);
}
#endif
...
}
;汇编指令延时程序
EXPORT delay ;声明本子程序,别的程序可以调用
EXPORT strcpydiy ;声明本子程序,别的程序可以调用
EXPORT callsum ;声明本子程序,别的程序可以调用
IMPORT sumdiy ;声明本程序可以使用C程序中的sumdiy本程序
AREA DELAY,CODE,READONLY ;该伪指令定义了一个代码段,段名为Delay,属性只读
;下面是延迟子程序
delay
sub r0,r0,#1 ;r0=r0-1 r0是入口参数
cmp r0,#0x0 ;将r0的值与0相比较
bne delay ;比较的结果不为0(r0不为0),继续调用delay,否则执行下一条语句
mov pc,lr ;返回
strcpydiy
;r0为目标字符串地址
;r1为源字符串地址
ldrb r2,[r1],#1
strb r2,[r0],#1
cmp r2,#0
bne strcpydiy
mov pc,lr
callsum
stmfd sp!,{lr} ;返回地址压栈
mov r0,#0 ;清零,对应sumdiy中的a
mov r1,#0 ;对应sumdiy中的b
mov r2,#0 ;对应sumdiy中的c
mov r3,#0 ;对应sumdiy中的d
mov r4,#0 ;对应sumdiy中的e
add r0,r0,#1 ;附初值
add r1,r1,#2
add r2,r2,#3
add r3,r3,#4
add r4,r4,#5
str r4,[sp,#-4]! ;r4需要用数据栈来传送
bl sumdiy ;调用C函数
add sp,sp,#4 ;到这里,r0存储了sumdiy的返回值为15
ldmfd sp!,{pc}
END ;程序结束符
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1