Mixed programming of C language and assembly language in STM32 under Keil

Keywords: C stm32

1, Introduction

C language is intuitive, easy to use, widely applicable, efficient assembly language and less memory. The combination of the two is the best choice

2, Example Title Requirements

  • Refer to the attachment to complete the C language call assembly function
  • Modify the reference code and require the original assembly language Init_1 change the type of the function to int Init_1(init), this function is modified to pass in an integer number x, and the function returns the integer number x+100 after running. Please program, track and debug through simulation;
  • If you want to call a function written in C language in assembly function, how do you modify the assembly code?

Reference codes are as follows:
C language part:

#include<stdio.h>

extern void Init_1(void);

int main()
{
	Init_1();
	
	return 0;
}

Assembly language:

	
	AREA	My_Function,CODE,READONLY ;This line is necessary except My_Function You can name yourself. All the others are templates
	EXPORT 	Init_1  ; With in c Defined in the file Init_1 Function Association

	; The declaration and use of variables in high-level languages are actually the use of board registers, so we only need to use registers directly

Init_1

	MOV R1,#0 Set R1 register to i
	MOV R2,#0 	  ;  Set R2 register to j
	
LOOP	; Written on the far left is the segment name of the program segment, which is used when executing the jump program
	CMP R1,#ten 	  ;  Compare the sizes of R1 and 10
	BHS LOOP_END  	  ; If R1 Greater than or equal to 10, jump to LOOP_END On the contrary, ignore the statement and directly execute the following statement
	ADD R2,#1	  ; j++
	ADD R1,#1     ; i++
	B LOOP		  ; loop
	
LOOP_END
	NOP	
	
	END  ; You must write after a space END,Otherwise, it will be regarded as the segment name, indicating the end of the program

3, Example part I

1. Preparation

  • First, you should create a new project in keil and create two files to store the code

If you are not familiar with how to build a new project in keil, please refer to my previous blog: Creating STM32 assembly language project and hex file analysis based on Keil5

  • Note: when creating two files, one should select the C File (. c) file and the other should select the Asm File (. s) file, as shown below:

2. Code part

  • Store the two parts of the reference code in their respective files, as shown in the figure. I store the assembly language in the funds. S file and the C language in the main.c file

3. Environment configuration and commissioning

(1) Environment configuration

  • Click to open the magic wand, select Use Simulator under Debug, change the content of Dialog DLL in the lower left to DARMSTM.DLL, and change the content of Parameter to - pSTM32F103C8

  • Click Rebuild to compile and display 0 error, indicating that the code is correct

(2) Debug

  • After the compilation is correct, click Start Debug Session to start debugging

  • Add breakpoint in main.c

  • Click Step for single Step debugging

  • As shown in the figure, registers R1 and R2 become 0, indicating that the program has been called from C language to assembly language

  • As shown in the figure, the registers R1 and R2 are gradually increased by 1, indicating that the function can execute its function, indicating that the C language calls the assembler successfully!

4, Example part 2 (modify function)

The original assembly language Init_1 change the type of the function to int Init_1(init), this function is modified to pass in an integer number x, and the function returns the integer number x+100 after running

1. Code part

In Keil, the parameter value transfer of the sub function is stored in R0, R1, R2 and R3 in order, and more than four parameter values are transferred and placed in the stack frame. So Init_1(10) the incoming 10 is put into R0, and the MOV PC and LR return 110

main.c code:

#include<stdio.h>

extern int Init_1(int x);

int main(){
	
	int y = Init_1(10);
	printf("%d", y);
	
	return 0;
}

func.s Code:

	AREA	MY_Function,CODE,READONLY
	EXPORT 	Init_1  ; With in c Defined in the file Init_1 Function Association


; The declaration and use of variables in high-level languages are actually the use of board registers, so we only need to use registers directly

Init_1
	ADD R0,#100     ;  Add the passed in value + 100
	MOV PC,LR		; return R0
	
	
LOOP	; Written on the far left is the segment name of the program segment, which is used when executing the jump program
	CMP R1,#ten 	  ;  Compare the sizes of R1 and 10
	BHS LOOP_END  	  ; If R1 Greater than or equal to 10, jump to LOOP_END On the contrary, ignore the statement and directly execute the following statement
	ADD R2,#1	  ; j++
	ADD R1,#1     ; i++
	B LOOP		  ; loop
	
LOOP_END
	NOP	
	
	
	END  ; You must write after a space END,Otherwise, it will be regarded as the segment name, indicating the end of the program

2. Commissioning

  • Set breakpoints, as shown in the figure

  • Click ctrl+F5 to enter debugging, and debug according to the debugging steps of example 1


    As shown in the figure, the value of R0 register is 6E. Convert hexadecimal to hexadecimal, and the value of R0 register is 110. Init is called in the main function_ 1 function, the given parameter 10. When the function is executed, the value becomes 10 + 100, also 110, which is the same as the value of register R0. The call is successful!

5, The third part of the example (assembly calls C language functions)

When you call the C language function XXX in the assembly, add IMPORT XXX, note that the Keil tool does not allow the assembly statement to be written on the top, otherwise it will report wrong.

1. Code part

Funds. S Code:

	AREA	My_Function,CODE,READONLY
	EXPORT 	Init_1  ; With in c Defined in the file Init_1 Function Association
	IMPORT  get8    ; statement get8 Is an external reference

; The declaration and use of variables in high-level languages are actually the use of board registers, so we only need to use registers directly

Init_1

	MOV R1,#0 Set R1 register to i
	MOV R2,#0 	  ;  Set R2 register to j
	
LOOP	; Written on the far left is the segment name of the program segment, which is used when executing the jump program
	CMP R1,#ten 	  ;  Compare the sizes of R1 and 10
	BHS LOOP_END  	  ; If R1 Greater than or equal to 10, jump to LOOP_END On the contrary, ignore the statement and directly execute the following statement
	ADD R2,#1	  ; j++
	ADD R1,#1     ; i++
	BL get8  	  ; call get8,The returned value is passed in R0
	B LOOP		  ; loop
	
LOOP_END
	NOP	

	END  ; You must write after a space END,Otherwise, it will be regarded as the segment name, indicating the end of the program

main.c code:

# include<stdio.h>

extern void	Init_1(void);

int get8(void)
{
     return 8;
}
int main()
{
	Init_1();
	
	return 0;
}

2. Commissioning

  • Set breakpoints, as shown in the figure:

  • After compilation, ctrl+F5 enters debugging
  • After debugging according to part of the example, the results are as follows:

    The value of register R0 changes to 8, indicating that the C language function call is successful!

6, Summary

Through the study of this blog, readers can understand the mixed use of C language and assembly language through three specific examples. The mixed use of C language and assembly language can not only save storage space, but also intuitively read out the content of the program. Readers can use this mixed method more. Through many practical operations, they can really master the mixed use method of C language and assembly. The article is for reference only. If there are any mistakes, you are welcome to discuss and correct them together.

7, References

Posted by *Lynette on Wed, 13 Oct 2021 16:04:01 -0700