僅做演示。html
1.C和彙編可相互調用,彙編子函數格式參考 彙編:普通的函數調用的彙編代碼解析 http://www.cnblogs.com/mylinux/p/4139972.htmllinux
本文演示了 : 彙編嵌入到c語言;函數
彙編調用c語言,c語言調用匯編。post
2.C函數參數從左到右是放到r0-r3,[不夠再push stack];push stack用stmfd ldmfd,右邊的參數會先入棧。this
;//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=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" , 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 :60000013 //mode[4-0] 10011 svc模式。 // this is cfunc_print,called_by_asm。 // in svc