|
為了使單獨(dú)編譯的C語(yǔ)言程序和匯編程序之間能夠相互調(diào)用,必須為子程序間的調(diào)用規(guī)定一定的規(guī)則。ATPCS(ARM/Thumb Procedure Call Standard) ,是ARM程序和Thumb程序中子程序調(diào)用的基本規(guī)則,它規(guī)定了一些子程序間調(diào)用的基本規(guī)則,如想了解更多的規(guī)則,可以查看上一篇中關(guān)于ATPCS的介紹。
高級(jí)語(yǔ)言函數(shù)與匯編語(yǔ)言函數(shù)的混合調(diào)用也要遵循ATPCS規(guī)則,保證程序調(diào)用時(shí)參數(shù)的正確傳遞。
當(dāng)在C語(yǔ)言程序中調(diào)用匯編程序時(shí),在匯編程序中使用EXPORT偽指令聲明本子程序,使其它程序可以調(diào)用此子程序;而在C語(yǔ)言程序中使用extern關(guān)鍵字聲明外部函數(shù)(聲明要調(diào)用的匯編子程序),即可調(diào)用此匯編子程序。
當(dāng)在匯編程序中調(diào)用C語(yǔ)言程序時(shí),在C程序中不需要使用任何關(guān)鍵字來(lái)聲明將被匯編語(yǔ)言調(diào)用的C程序,但是在匯編程序調(diào)用該C程序之前需要在匯編語(yǔ)言程序中使用IMPORT偽操作來(lái)聲明該C程序。在匯編程序中通過(guò)BL指令來(lái)調(diào)用子程序。
下面給出兩個(gè)例子來(lái)介紹函數(shù)相互調(diào)用。
// 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); //聲明要調(diào)用的匯編子程序
extern void strcpydiy(char *dest, const char *src); //聲明要調(diào)用的匯編子程序
extern int callsum(void ); //聲明要調(diào)用的匯編子程序
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設(shè)置為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設(shè)置為output
rGPFUP|=0xF0; //disable GPF pull up
rGPFDAT=(rGPFDAT&0x0F)|0x70; //GPF7 output 0
while(1);
}
#endif
...
}
;匯編指令延時(shí)程序
EXPORT delay ;聲明本子程序,別的程序可以調(diào)用
EXPORT strcpydiy ;聲明本子程序,別的程序可以調(diào)用
EXPORT callsum ;聲明本子程序,別的程序可以調(diào)用
IMPORT sumdiy ;聲明本程序可以使用C程序中的sumdiy本程序
AREA DELAY,CODE,READONLY ;該偽指令定義了一個(gè)代碼段,段名為Delay,屬性只讀
;下面是延遲子程序
delay
sub r0,r0,#1 ;r0=r0-1 r0是入口參數(shù)
cmp r0,#0x0 ;將r0的值與0相比較
bne delay ;比較的結(jié)果不為0(r0不為0),繼續(xù)調(diào)用delay,否則執(zhí)行下一條語(yǔ)句
mov pc,lr ;返回
strcpydiy
;r0為目標(biāo)字符串地址
;r1為源字符串地址
ldrb r2,[r1],#1
strb r2,[r0],#1
cmp r2,#0
bne strcpydiy
mov pc,lr
callsum
stmfd sp!,{lr} ;返回地址壓棧
mov r0,#0 ;清零,對(duì)應(yīng)sumdiy中的a
mov r1,#0 ;對(duì)應(yīng)sumdiy中的b
mov r2,#0 ;對(duì)應(yīng)sumdiy中的c
mov r3,#0 ;對(duì)應(yīng)sumdiy中的d
mov r4,#0 ;對(duì)應(yīng)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需要用數(shù)據(jù)棧來(lái)傳送
bl sumdiy ;調(diào)用C函數(shù)
add sp,sp,#4 ;到這里,r0存儲(chǔ)了sumdiy的返回值為15
ldmfd sp!,{pc}
END ;程序結(jié)束符
|
|