“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 function
  • extern: 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