×
单片机 > 单片机程序设计 > 详情

arm:c语言和汇编混合编程

发布时间:2020-06-20 发布时间:
|
仅作演示。

1.C和汇编可相互调用,汇编子函数格式参考 汇编:普通的函数调用的汇编代码解析 http://www.cnblogs.com/mylinux/p/4139972.html

  本文演示了 : 汇编嵌入到c语言;

            汇编调用c语言,c语言调用汇编。

2.C函数参数从左到右是放到r0-r3,[不够再push stack];push stack用stmfd ldmfd,右边的参数会先入栈。

;//call_asm.s
    PRESERVE8
    AREA C$$code, CODE, READONLY
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    IMPORT cfunc_print
    IMPORT c_add
    IMPORT c_sub
    
    EXPORT AsmCallerAdd
    EXPORT AsmCallerSub
    EXPORT AsmCallerPrint
    EXPORT slib_ReadCpuStatus
    
AsmCallerAdd              ; ,执行子函数TestFunc6(1,2)
    sub r13, r13, #4    ;sp-=4 
    str r14, [r13]      ;sp>lr
    bl c_add            ;BL : r0,r1中的参数传到子函数
    ldr r14, [r13]      ;lr>sp  
    add r13, r13, #4    ;sp+=4 
    bx r14              ;goto sp
    
AsmCallerSub 
    mov     ip, sp
    stmfd   sp!, {fp, ip, lr, pc}
    sub     fp, ip, #4
    bl      c_sub
    ldmfd   sp, {fp, sp, pc}  
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
AsmCallerPrint 
    sub r13, r13, #4    ;sp -= 4 
    str r14, [r13]      ;sp > lr
    bl cfunc_print      ; 
    ldr r14, [r13]      ;lr > sp  
    add r13, r13, #4    ;sp += 4 
    bx r14              ;goto sp
    
    
slib_ReadCpuStatus
    mov     ip, sp
    stmfd   sp!, {fp, ip, lr, pc}
    sub     fp, ip, #4
    mrs     r0,cpsr
    ldmfd   sp, {fp, sp, pc}
    
 
    
    END

 

//asm_c.c

/*
根据“ARM-thumb 过程调用标准”:
r0-r3    用作传入函数参数,传出函数返回值。在子程序调用之间,可以将 r0-r3 用于任何用途。
         被调用函数在返回之前不必恢复 r0-r3。如果调用函数需要再次使用 r0-r3 的内容,则它必须保留这些内容。
r4-r11   被用来存放函数的局部变量。如果被调用函数使用了这些寄存器,它在返回之前必须恢复这些寄存器的值。
r12      是内部调用暂时寄存器 ip。它在过程链接胶合代码(例如,交互操作胶合代码)中用于此角色。
         在过程调用之间,可以将它用于任何用途。被调用函数在返回之前不必恢复 r12。
r13      是栈指针 sp。它不能用于任何其它用途。sp 中存放的值在退出被调用函数时必须与进入时的值相同。
r14      是链接寄存器 lr。如果您保存了返回地址,则可以在调用之间将 r14 用于其它用途,程序返回时要恢复
r15      是程序计数器 PC。它不能用于任何其它用途。
         注意:在中断程序中,所有的寄存器都必须保护,编译器会自动保护R4~R11
*/

int c_add(int a ,int b)
{
    return a+b;
}
int c_sub(int a ,int b)
{
    return a-b;
}

unsigned int asm_c_ctl_cp15(void)
{
    unsigned int i = 0;
    Uart_Printf("asm_c_ctl_cp15\n");
    
    __asm 
    {
        mrc p15,0,r0,c1,c0,0 
        MOV i,r0
    }
    return i;
}

unsigned int asm_c_ReadCPSR(void)
{
    unsigned int i = 0;
    __asm 
    {
        mrs     r0,cpsr
        MOV i,r0
    }
    return i;
}

void cfunc_print()
{
    Uart_Printf("this is cfunc_print,called_by_asm\n");
}
 
void asm_demo(void)
{
    int i, j,a ;
    Uart_Printf("asm_demo\n");

    asm_c_ctl_cp15();//在c中使用汇编语言操作协处理器cp15

    Uart_Printf("4+5 = %d \n" ,  AsmCallerAdd(4, 5) ); //汇编调用c语言函数
    //mdk_jlink:
    //get into AsmCallerAdd(4, 5) :  r0=4 ,r1=5 
    //get into c_add    : r0=4 ,r1=5 
    //return from c_add : r0=9
    //return from AsmCallerAdd: r0=0x36160 ,r1=9 .
    //函数参数从左到右是放到r0-r3,[不够再push stack]
    //push stack用stmfd ldmfd,右边的参数会先入栈
    //STMFD&&LDMFD  http://www.cnblogs.com/mylinux/p/4139972.html
 
    Uart_Printf("9-5 = %d \n" ,  AsmCallerSub(9, 5) );//汇编调用c语言函数

    Uart_Printf("slib_ReadCPSR :%x \n" , asm_c_ReadCPSR() ); //在c语言中混合汇编,读取Cpsr寄存器
    
    AsmCallerPrint();//汇编调用c语言函数

    switch(0x1f & slib_ReadCpuStatus()){//c语言调用汇编编写的函数
        case 0x13:
            Uart_Printf("in svc\n" , a);
    } 
    
}
// asm_demo
// asm_c_ctl_cp15
// 4+5 = 9 
// 9-5 = 4 
// slib_ReadCPSR :60013    //mode[4-0] 10011 svc模式。
// this is cfunc_print,called_by_asm。
// in svc

 

关键字:arm  c语言  汇编  混合编程

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
ARM中断源之定时器中断