“This is the 30th day of my participation in the November Gwen Challenge. See details: The Last Gwen Challenge 2021”.
Assembly language and C language interaction
- Inline assembly
- Outside the chain assembly
1. Introduce other source file functions
Use import or extern directives
; AREA code, code import fun1; Import the function END named fun1 from other source files; Use the extern pseudodirective AREA code, code extern fun1 ENDCopy the code
Differences between the two:
import
: This label is added to the symbol table of the current file, which is a static reference, regardless of whether the current file uses the introduced functionextern
: This label is added to the symbol table only if it is used by the current file. This is a dynamic reference
2. Export functions in the current source file for other files to access
Use export or global directives
; AREA code, code export fun; Export fun for other source files to use fun mov R0,#4 bx lr ENDCopy the code
3. External chain assembly of C language assembly function
The first step is to expose the function to external calls in the assembly file, using export or global directives:
AREA code, CODE export arm_strcpy ; Or use global arm_strcpy loop LDRB R4,[R0],#1; If LDR is used then change the offset to 4 CMP R4,#0 beq over STRB R4,[R1],#1 b loop over ENDCopy the code
Second, reference the assembly function in a C file, where only extern directives can be used:
extern arm_strcpy(char *src,char*des);
int main2(){
char *a="hello pangshu";
char b[64];
arm_strcpy(a,b);
}
Copy the code
4. Outside chain assembly assembly tuning C language functions
The first step is to write the function in a C file
int c_sum(int a,int b){
return a+b;
}
Copy the code
The second step is to introduce functions in the assembler, using import or extern directives
AREA code, CODE import c_sum mov R0,#1 ; The first parameter mov R1,#2; The second argument ENDCopy the code
Third, call the function with the BL instruction
AREA code, CODE import c_sum mov R0,#1 ; The first parameter mov R1,#2; The second argument is BL c_sum ENDCopy the code
In ARM, function parameters are transferred using four registers R0~R3. At most, 4 parameters are transferred. If more than 4 parameters are processed by stack, the return value of function is transferred through R0
Due to the particularity of keil software, we can conduct intermodulation testing in the following ways
Code in C file:
#include<stdio.h>
extern arm_strcpy(char *src,char*des);
int main2(a){
char *a="hello pangshu" ;
char b[64];
arm_strcpy(a,b); // call the assembly function
return 0;
}
int c_sum(int a,int b){
return a+b;
}
Copy the code
Compile the code in the file:
AREA code, CODE import c_sum export arm_strcpy arm_strcpy mov R0,#1 ; The first parameter mov R1,#2; The second argument BL c_sum; The result is stored in R0 ENDCopy the code
5. Inline assembly
Embed assembly code in C language in the following format:
int main2(a){
int a=4;
int b=4;
int c=4;
__asm__{ // use __asm or __asm__
mov R5,#0x00000005 // Just write the assembly code inside the braces
mov R6,#0x00000005
}
return 0;
}
Copy the code
Notes for embedded assembly:
- It is not possible to assign a value to the PC register directly. If you want to change the PC value, you need to use the transfer instruction
- Since R0 ~ R3 is used to store function parameters and return values,R12 ~ R15 has a special purpose, so the only registers we can manipulate are R4~R11. And because the compiler will give preference to the register allocation to the function of the local variable, so we usually cannot accurately embedded assembly environment changes a register values, such as I would like to modify the R5 register values, because the function has a variable occupies R5 this register, then the compiler will automatically change the R5 you wrote to R6 or other, so, In inline assembly, we need to treat registers as variables, and local variables as registers, which is easy to understand
void c_strcopy(char *src,char *des){ char ch __asm__{ loop: STRB ch,[des],#1 CMP,ch,#0 bne loop}}Copy the code