Examples of C and assembly languages or programming in ARM, and explanations of arm instances
1. inline assembly
Notes for Embedded Assembly in C language:
You cannot assign values directly to the PC register. B or BL commands must be used for program redirection. Do not use overly complex C expressions when using physical registers, avoid physical register conflicts. R12 and R13 may be used by the compiler to store intermediate compilation results. When calculating expression values, R0 to R3, R12, and R14 may be used for subroutine calls, therefore, to avoid using these physical registers directly, do not directly specify the physical registers, but let the compiler allocate them.
Example program:
#include
void my_strcpy(const char *src, char *dest)
{
char ch;
__asm
{
loop:
ldrb ch, [src], #1
strb ch, [dest], #1
cmp ch, #0
bne loop
}
}
int main()
{
char *a = "forget it and move on!";
char b[64];
my_strcpy(a, b);
printf("original: %s", a);
printf("copyed: %s", b);
return 0;
}
Use global variables defined in C language in assembly language
It is very convenient to compile and compile assembly files without using inline assembly, but there are many restrictions on using inline assembly, when there are many assembly files, you need to use a special assembly file to compile the assembly program. The simplest form of data transmission in C and assembly languages is to use global variables.
#include
int gVar_1 = 12;
extern asmDouble(void);
int main()
{
printf("original value of gVar_1 is: %d", gVar_1);
asmDouble();
printf(" modified value of gVar_1 is: %d", gVar_1);
return 0;
}
Corresponding assembly language file
;called by main(in C),to double an integer, a global var defined in C is used.
AREA asmfile, CODE, READONLY
EXPORT asmDouble
IMPORT gVar_1
asmDouble
ldr r0, =gVar_1
ldr r1, [r0]
mov r2, #2
mul r3, r1, r2
str r3, [r0]
mov pc, lr
END
Call assembly language functions in C
There are two main tasks to call functions in C: declare the function prototype in C and add the extern keyword, the second is to use EXPORT to EXPORT the function in the assembly language, use the function name as the flag of the Assembly segment, and finally use mov pc and lr to return the function, then you can call the function in C. From the perspective of C, you do not know whether the function is implemented in C or assembly, because the function name in C language also marks the starting address of the function, which is the same as that in assembly.
/* cfile.c
* in C,call an asm function, asm_strcpy
* Sep 9, 2004
*/
#include
extern void asm_strcpy(const char *src, char *dest);
int main()
{
const char *s = "seasons in the sun";
char d[32];
asm_strcpy(s, d);
printf("source: %s", s);
printf(" destination: %s",d);
return 0;
}
;asm function implementation
AREA asmfile, CODE, READONLY
EXPORT asm_strcpy
asm_strcpy
loop
ldrb r4, [r0], #1 ;address increment after read
cmp r4, #0
beq over
strb r4, [r1], #1
b loop
over
mov pc, lr
END
Here, the parameter transfer between C and assembly is implemented according to the ATPCS (ARM Thumb Procedure Call Standard. Simply put, if the function has no more than four parameters, corresponding to the use of R0-R3 to pass, more than four with stack, the return value of the function is returned through R0.
Call C Functions in assembly language
To call a C function in an assembly language, you must IMPORT the corresponding C language function name in the assembly language.
;the details of parameters transfer comes from ATPCS
;if there are more than 4 args, stack will be used
EXPORT asmfile
AREA asmfile, CODE, READONLY
IMPORT cFun
ENTRY
mov r0, #11
mov r1, #22
mov r2, #33
BL cFun
END
/*C file, called by asmfile */
int cFun(int a, int b, int c)
{
return a + b + c;
}