Code
compilation
The previous assembly code is as follows
//These are just assembly syntax, nothing to remember
.text
.global _start
_start:
/*Set memory: sp (stack pointer) stack*/
ldr sp, = 4096 //nand
// ldr sp, = 0x40000000 + 4096/*nor start*/
/*Call main function*/
bl main /*jump to execute main and save the return address*/
halt:
b stop
The process is as follows
1. Set up the stack
2. Call main and save the return address in lr
main.c
int main()
{
unsigned int *pGPFCON = (unsigned int *)0x56000050;
unsigned int *pGPFDAT = (unsigned int *)0x56000054;
/*Configure GPF4 as output pin*/
*pGPFCON = 0x100;
/*Configure GPF4 output 0*/
*pGPFDAT = 0;
return 0;
}
The process is as follows
Define two local variables
Setting variables
return 0
doubt
Why do we need to set up the stack before calling the main function?
——C function needs to use
How to use the stack?
——Save local variables, save lr and other registers
In the assembly, the return value of bl main is stored in the lr register.
Assuming that the main function calls other functions, it should also return to the main function to continue execution after the call.
Obviously, when calling a sub-function, the return address should also be saved in lr. Then the address of the main function in lr will not be overwritten by the return address of the sub-function? ——So lr and other registers will be saved
How does the caller pass parameters to the callee (sub-function)?
How does the callee return the return value to the caller?
These two questions need to be understood. The ATPCS rules followed by assembly calling C functions
ARM-THUMB prodcedure call standard
These four registers are parameter result registers
The caller passes parameters to the callee through these registers
The callee returns the result to the caller through these registers
How to restore those registers from the stack?
In the function, r4~r11 may be used
So, save them at the entry of the function and save them at the exit of the function
Of course, your function may be very simple, so just save whoever you need.
Analyzing disassembled code
Assume we are using nand boot
For the program started by NAND, the hardware will completely copy the first 4k of Nand Flash to the 4
kMemory
That is to say, the machine codes in the second column will be completely saved in the front of the 4k memory.
The state in memory is as follows:
The last address is e89da800
It can be seen that the common segment is not saved in the memory
The common section is the comment section of the program, and these comments do not need to be included in the bin file
process
Upon power-up, execution starts at address 0 and the stack is set at address 4096
Then bl saves the return address at 0x8 and jumps to 0x0c to start executing the main function
Initially, ip = sp = 4096
The second statement saves the values of the four registers in the brackets into the memory corresponding to sp.
stmdb, decrement first and then store, store according to the register number. fp, ip, lr, pc correspond to r11, r12, r14, r15 respectively. High numbers are placed at high addresses. So we store the address of pc first, pc = the address of the current instruction + 8, which is 0x18.
Next, store lr, lr = 0x8
ip = sp = 4096
fp is an undefined value
The above are the values of these four registers. The addresses stored are 4 minus 4 from 4096.
So the final sp' = 4096 - 4*4 = 4080
The third directive
fp = ip - 4 = 4092
Article 4
sp = sp - 8 = 4080 - 8 = 4072
Fifth Sixth Seventh
r3 = 0x56000050
The value of r3 is stored in [fp-16] = [4076-16] = 4060
This is the pGPFCON local variable. Local variables are stored on the stack.
Article 10
Store the value of r3, 0x56000054, into [fp - 20] = 4072
This is the local variable
Article 11
r2 = [fp - 16] = [4076] = 0x56000050 = pGPFCON
Article 12
Store r3—0x100 into the location pointed to by r2-----0x56000050
The corresponding C language is
Article 13
r2 = [fp - 20] = 4072 = 0x56000054
14
Store r3 in the location pointed to by r2, which is 0x56000054
The corresponding C code is here↑
The last two
Assign 0 to r3
Assign r3 to r0
The compiler is not very smart, in fact, it can directly assign 0 to r0
The callee returns the return value to the caller through r0~r3. There is only one return value here, so r0 is enough.
The second to last
Recovery Stack
sp = fp - 12 = 4092 - 12 = 4080
The last one
Restore registers from the stack
fp, sp, pc are labeled r11, r13, r15 respectively
fp = [4080] = originally saved fp
sp = [4084] = 4096
pc = [4088] = 8—jump back to address 0x8
Return here↑
Summarize
From the above analysis, we can see that the stack is the memory pointed to by the sp register, which can be read and written
The previous part is used to save registers, and the registers will be restored before the function returns.
Here are the local variables
It can also be seen here that 8 bytes is the space for local variables
Setting the stack to 4096 is perfectly fine.
The stack is transferred from high address to low address. The program is very small and the stack will not destroy the main function below.
In this program, we only involve the callee returning the return value to the caller, so how does the caller pass parameters to the callee?
Next blog post Writing program tests
Previous article:S3C2440c language assembly parameter transfer light
Next article:S3C2440 uses bin file machine code to light up
- Popular Resources
- Popular amplifiers
- Learn ARM development(16)
- Learn ARM development(17)
- Learn ARM development(18)
- Embedded system debugging simulation tool
- A small question that has been bothering me recently has finally been solved~~
- Learn ARM development (1)
- Learn ARM development (2)
- Learn ARM development (4)
- Learn ARM development (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- CGD and Qorvo to jointly revolutionize motor control solutions
- CGD and Qorvo to jointly revolutionize motor control solutions
- Keysight Technologies FieldFox handheld analyzer with VDI spread spectrum module to achieve millimeter wave analysis function
- Infineon's PASCO2V15 XENSIV PAS CO2 5V Sensor Now Available at Mouser for Accurate CO2 Level Measurement
- Advanced gameplay, Harting takes your PCB board connection to a new level!
- Advanced gameplay, Harting takes your PCB board connection to a new level!
- A new chapter in Great Wall Motors R&D: solid-state battery technology leads the future
- Naxin Micro provides full-scenario GaN driver IC solutions
- Interpreting Huawei’s new solid-state battery patent, will it challenge CATL in 2030?
- Are pure electric/plug-in hybrid vehicles going crazy? A Chinese company has launched the world's first -40℃ dischargeable hybrid battery that is not afraid of cold
- I would like to know the functions of these two components, about switching power supply.
- Molex's compact Type-C connector saves valuable space in your design! Download and get a gift! Event starts now
- Knowledge about power amplifiers in RF chips
- Playing with Zynq Part 7 - Ubuntu and Windos file transfer tool WinSCP
- Altium Designer 3D View Problem
- [National Technology N32G457 Review] RT_Thread Studio failed to mount spi1 after configuring SPI
- RT-Thread operating system μC/OS-III compatibility layer
- LSM6DSL power consumption problem
- [Rawpixel RVB2601 development board trial experience] TCP_SEVER communication
- A naked scheme, is this true?