The ATPCS rule embodies the idea of ​​a modular design, the basic content of which is a set of rules invoked by C modules (functions) and assembly modules (functions) (a similar set of rules in C51). I feel more powerful than the online compilation (without having a lot of taboos) and the rules are clearer (a few simple rules).
ATPCS rules content:
1) Usage rules of registers
1. The subroutines pass parameters through registers r0~r3. When the number of parameters is more than 4, use the stack to pass parameters. At this time r0 ~ r3 can be regarded as A1 ~ A4.
2. In the subroutine, use registers r4~r11 to save the local variables. So pay attention to the preservation and restoration of these registers when making subroutine calls. At this time r4 ~ r11 can be recorded as V1 ~ V8.
3. The register r12 is used to save the stack pointer SP. When the subroutine returns, this register is used for stacking and is recorded as IP.
4. Register r13 is used as a stack pointer, denoted as SP. Register r14 is called link register and denoted as LR. This register is used to save the return address of a subroutine.
5. The register r15 is called the program counter and is denoted as PC.
2) Usage rules of the stack
ATPCS specifies that the stack adopts the full descending type (FD, Full Descending), that is, the stack grows downward by decreasing the memory address, and the stack pointer points to the lowest address containing valid data items.
3) Transfer rules of parameters
1. The first four integer parameters are passed using r0~r3, and the other parameters are transferred using the stack. The floating-point parameters use a set of consecutive register transfer parameters that have the smallest number and can satisfy the requirement.
2. When the return value of the subroutine is a 32-bit integer, it is returned through r0; when the result is a 64-bit integer, it is returned through r0 and r1; and so on. When the result is a floating-point number, it is returned by the register F0, D0, or S0 of the floating-point arithmetic unit.
It's more organized, and it's clear that I give two examples:
1. Assembler main program calls C subroutine
The writing of the assembler should follow the ATPCS rules to ensure that the parameters are passed correctly when the program is called. Calling a C program in an assembler is:
1) Use the IMPORT directive in the assembler or extern to declare in advance the C language functions to be called;
2) Call C function by BL instruction.
For example, the following sum function is defined in a C source file:
Int add(int x,int y)
{
Return(x+y);
}
The assembler structure that calls the add() function is as follows:
Area main,code,readonly ;Code segment
Entry; declaration program entry
Code32 ; 32-bit ARM instruction
IMPORT add or extern add; declare the C function to call
Start
......
MOV r0,1
MOV r1,2
BL add ; Call C function add
......
End
When a function call is made, the parameters are passed using r0 and r1, and the result is brought back by r0. At the end of the function call, the value of r0 becomes 3.
2.C main program calls assembly subroutine
When the C program calls the assembler, the writing of the assembler must also follow the ATPCS rules to ensure that the parameters are correctly passed when the program is called. The method of calling assembly subroutines in a C program is:
1) Use the EXPORT directive in the assembler to declare the called subroutine, indicating that the subroutine will be called in other files;
2) Use the extern keyword in a C program to declare that the assembly subroutine to be called is an external function.
For example, the following sum function is defined in an assembler source file:
EXPORT add ; The declaration add subroutine will be called by an external function
......
Add;sum subroutine add
.global add ;Statement
ADD r0,r0,r1
MOV pc,lr
......
The add assembly routine is called in the main() function of a C program:
Extern int add (int x, int y); // declare add as an external function
Void main(){
Int a=1,b=2,c;
c = add (a, b); / / call add subroutine, and implicitly assign r0 and r1
......
}
When the main() function calls the add assembly subroutine, the values ​​of the variables a and b are given to r0 and r1, and the return result is brought back by r0 and assigned to the variable c. At the end of the function call, the value of variable c becomes 3.
3, C program embedded assembly statement
Inline assembly language in C language can achieve some high-level language can not be achieved or not easily implemented. Time-critical functions can also be implemented by inline assembly statements in the C language. The embedded assembler supports most of the ARM and Thumb instructions, but does not support underlying functions such as directly modifying the PC implementation jumps, nor can it directly reference variables in the C language.
Inline assembly: Embedding assembly language in C and C++ languages ​​can achieve features not found in some high-level languages.
grammar
__asm__ (; Note: The front is two "_"
"instruction
...
Instruction"
);//Linux gcc support
__asm{
Instruction
...
Instruction
}; //Support in ADS
Asm("instruction[; instruction]"); //Used in ARM C++
ARM inline assembly syntax
Asm(
Assembly statement template:
Output section:
Input section:
Modified section
);
For example: asm("mov %0, %1, ror #1" :"=r" (result) : "r" (value));
A total of four parts: the assembly statement template, the output part, the input part, the destruction of the description part, each part using ":" grid open, assembly statement template is essential, the other three parts are optional, if the use of the back part, and front Parts are empty, but also need to be opened with ":". The corresponding part is empty. E.g:
__asm__ __volatile__ (
"CLI":
:"memory"
);
Example: /* main.c */
Void __main(void)
{
Int var=0xAA;
__asm ​​//Inline assembly identifier
{
MOV R1,var
CMP R1, #0xAA
}
While(1);
}
Dongguan SOLEPIN Electronics Co., Ltd , https://www.wentae.com