For demonstration purposes only. C and assembly can call each other, assembly sub-function format Reference assembly: Common function call assembly code parsing http://www.cnblogs.com/mylinux/p/4139972.html
;//CALL_ASM.SPRESERVE8 Area| C $ $code |, CODE, READONLY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Import cfunc_called_by_asm Import c_add import c_sub export AsmCaller1 export ASMCALLER2 export Asmcall Er3 EXPORT slib_readcpustatus AsmCaller1; , execute the Sub-function TestFunc6 (1,2) Sub R13, R13, #4; sp-=4str R14, [R13]; SP--->lr BL c_add; The parameters in the Bl:r0,r1 are passed to the sub-function Ldr R14, [R13]; LR--->sp Add R13, R13, #4; sp+=4BX R14;GotoSP ASMCALLER2 mov ip, SP stmfd sp!, {FP, IP, LR, PC} sub fp, IP, #4bl c_sub ldmfd sp, {fp, SP, PC};;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; AsmCaller3 Sub R13, R13, #4; SP-=4str R14, [R13]; SP--->lr BL cfunc_called_by_asm; Ldr R14, [R13]; LR--->sp Add R13, R13, #4; SP + =4BX R14;GotoSP slib_readcpustatus mov ip, SP stmfd sp!, {FP, IP, LR, PC} sub fp, IP, #4Mrs R0,cpsr Ldmfd SP, {fp, SP, PC} END
//ASM_C.C/*according to the "Arm-thumb Procedure Call standard": R0-R3 is used as an incoming function parameter, and the outgoing function returns a value. The R0-R3 can be used for any purpose between subroutine calls. The called function does not have to recover R0-R3 before returning. If the calling function needs to use R0-R3 's content again, it must retain the content. R4-r11 is used to store local variables of a function. If the called function uses these registers, it must restore the values of these registers before returning. R12 is an internal call to a temporary register IP. It is used for this role in the process link glue code (for example, interactively manipulating the glue code). Between procedure calls, it can be used for any purpose. The called function does not have to recover R12 before returning. R13 is the stack pointer sp. It cannot be used for any other purpose. The value stored in the SP must be the same as the value entered when exiting the called function. R14 is the link register LR. If you save the return address, you can use R14 between calls for other purposes, and when the program returns, the R15 is the program counter PC. It cannot be used for any other purpose. Note: In the interrupt program, all registers must be protected and the compiler will automatically protect the R4~r11*/intC_add (intAintb) { returnA +b;}intC_sub (intAintb) { returnA-b;} unsignedintASM_C_CTL_CP15 (void) {unsignedinti =0; uart_printf ("asm_c_ctl_cp15\n"); __asm {MRC P15,0, R0,C1,C0,0MOV I,r0}returni;} unsignedintASM_C_READCPSR (void) {unsignedinti =0; __asm {Mrs R0,cpsr MOV i,r0}returni;}voidcfunc_called_by_asm () {uart_printf ("This is cfunc_called_by_asm\n");} voidAsm_demo (void){ intI, 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. //function arguments from left to right are put to r0-r3,[enough to push stack]//The push stack is STMFD ldmfd, and the parameters on the right are first in the stack//STMFD&&LDMFDhttp://www.cnblogs.com/mylinux/p/4139972.htmluart_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
Arm:c language and assembly mixed programming