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.