arm:c语言和汇编混合编程
仅作演示。c和汇编可相互调用,汇编子函数格式参考 汇编:普通的函数调用的汇编代码解析 http://www.cnblogs.com/mylinux/p/4139972.html
;//call_asm.s PRESERVE8 AREA |C$$code|, CODE, READONLY ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; IMPORT cfunc_called_by_asm IMPORT c_add IMPORT c_sub EXPORT AsmCaller1 EXPORT AsmCaller2 EXPORT AsmCaller3 EXPORT slib_ReadCpuStatus AsmCaller1 ; ,执行子函数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 AsmCaller2 mov ip, sp stmfd sp!, {fp, ip, lr, pc} sub fp, ip, #4 bl c_sub ldmfd sp, {fp, sp, pc} ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; AsmCaller3 sub r13, r13, #4 ;sp -= 4 str r14, [r13] ;sp ---> lr bl cfunc_called_by_asm ; 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_called_by_asm() { Uart_Printf("this is cfunc_called_by_asm\n"); } void asm_demo(void) { int i, j,a ; asm_c_ctl_cp15(); Uart_Printf("asm_demo\n"); Uart_Printf("4+5 = %d \n" , AsmCaller1(4, 5) ); //mdk_jlink: //get into AsmCaller1(4, 5) : r0=4 ,r1=5 //get into c_add : r0=4 ,r1=5 //return from c_add : r0=9 //return from AsmCaller1: 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 \n" , AsmCaller2(9, 5) ); Uart_Printf("slib_ReadCPSR :%x \n" , asm_c_ReadCPSR() ); AsmCaller3(); switch(0x1f & slib_ReadCpuStatus()){ case 0x13: Uart_Printf("in svc\n" , a); } } // asm_demo // asm_c_ctl_cp15 // 4+5 = 9 // 9-5 = 4 // slib_ReadCPSR :60000013 // this is cfunc_called_by_asm // in svc
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。