标题: 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