zoukankan      html  css  js  c++  java
  • arm:c语言和汇编混合编程

    仅作演示。

    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
    ");
        
        __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
    ");
    }
     
    void asm_demo(void)
    {
        int i, j,a ;
    Uart_Printf("asm_demo ");

    asm_c_ctl_cp15();//在c中使用汇编语言操作协处理器cp15
    Uart_Printf("4+5 = %d " , 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=0x30006160 ,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 " , AsmCallerSub(9, 5) );//汇编调用c语言函数
    Uart_Printf(
    "slib_ReadCPSR :%x " , asm_c_ReadCPSR() ); //在c语言中混合汇编,读取Cpsr寄存器 AsmCallerPrint();//汇编调用c语言函数
    switch(0x1f & slib_ReadCpuStatus()){//c语言调用汇编编写的函数 case 0x13: Uart_Printf("in svc " , a); } } // asm_demo // asm_c_ctl_cp15 // 4+5 = 9 // 9-5 = 4 // slib_ReadCPSR :60000013 //mode[4-0] 10011 svc模式。 // this is cfunc_print,called_by_asm。 // in svc
  • 相关阅读:
    JAVA设计模式之单例模式
    JAVA设计模式之建造模式
    JAVA设计模式之原型模式
    JAVA设计模式之适配器模式
    JAVA设计模式之合成模式
    JAVA设计模式之享元模式
    JAVA设计模式之门面模式
    JAVA设计模式之桥梁模式
    JAVA设计模式之不变模式
    JAVA设计模式之模版方法模式
  • 原文地址:https://www.cnblogs.com/mylinux/p/4153766.html
Copyright © 2011-2022 走看看