Arm assembly study notes (6)-function call stack space and fp register

The rules for function calls on the Arm are defined in detail in the ATPCS part of the ARM System Developer's Guide. Here, the functions of the registers such as fp and sp are mainly explained by the function stack during the function call. For more details about ATPCS, please go to the documentation.


fp is called the frame pointer register, which is the stack frame pointer register; sp is called the stack pointer register, which is the stack pointer register. So what are their specific roles?

First of all, everyone knows that each process has its own independent stack space, there are tens of millions of function calls in the process, these functions share the stack space of the process, then the problem comes, there will be a lot of In the process of stacking and stacking, how can the return address be accurately located when the function returns backtrace? What are the contents of some registers saved by the subfunction? In this way, there is the concept of stack frames, that is, the stack space used by each function is a stack frame, and all stack frames form a complete stack of this process. And fp is the stack base address register, pointing to the bottom of the stack of the current function stack frame, and sp is pointing to the top of the stack of the current function stack frame. The stack frame of the parent function can be restored by the stack frame pointed out by sp and fp, and so on, and the calling sequence of all functions can be backtraced.

What is the specific scope of the stack frame of that function? Where exactly should fp and sp point? Please see the picture below:


figure 1

The above figure describes the stack frame layout of ARM. The main stack frame is the stack frame of the calling function, func1 stack frame is the stack frame of the current function (callee), the bottom of the stack is at a high address, and the stack grows downward. This picture is a picture on the Internet, in theory, it should be in the format of the above picture. The four registers fp, sp, lr and pc are very special registers. They record some important information of the currently running function. When the functions of the start execution, they save the information of the previous function, you need to put them on the stack to save, this is very important! These are not defined in ATPCS. ATPCS stipulates how the parameters are passed when the function is called, and the return value of the function is saved. The above personally feel that it is a tacit agreement, which defines the function of saving and restoring the scene. These tacit agreements, including ATPCS, are artificial constraints. The purpose is to ensure that the program will not go wrong. How to implement it should be different compiler not exactly.

In order to verify the implementation of arm's gcc compiler, I wrote a small experiment program myself:

main.c:



#include <stdio.h>

int func(int i);

int main(void)
{
  int i = 25;
  func(i);
  return 0;
}

func.c

int func(int i)
{
  int a = 2;
  return a * i;
}

The func function is called in main.c, and the func function is implemented in the func.c file. The following is the code disassembled by the execution file compiled with arm-linux-androideabi-gcc:

Disassembly of section .text:

0000822c <func>:
    822c:	e52db004 	push	{fp}		; (str fp, [sp, #-4]!)
    8230:	e28db000 	add	fp, sp, #0
    8234:	e24dd014 	sub	sp, sp, #20
    8238:	e50b0010 	str	r0, [fp, #-16]
    823c:	e3a03002 	mov	r3, #2
    8240:	e50b3008 	str	r3, [fp, #-8]
    8244:	e51b3008 	ldr	r3, [fp, #-8]
    8248:	e51b2010 	ldr	r2, [fp, #-16]
    824c:	e0030392 	mul	r3, r2, r3
    8250:	e1a00003 	mov	r0, r3
    8254:	e24bd000 	sub	sp, fp, #0
    8258:	e49db004 	pop	{fp}		; (ldr fp, [sp], #4)
    825c:	e12fff1e 	bx	lr

00008260 <main>:
    8260:	e92d4800 	push	{fp, lr}
    8264:	e28db004 	add	fp, sp, #4
    8268:	e24dd008 	sub	sp, sp, #8
    826c:	e3a03019 	mov	r3, #25
    8270:	e50b3008 	str	r3, [fp, #-8]
    8274:	e51b0008 	ldr	r0, [fp, #-8]
    8278:	ebffffeb 	bl	822c <func>
    827c:	e3a03000 	mov	r3, #0
    8280:	e1a00003 	mov	r0, r3
    8284:	e24bd004 	sub	sp, fp, #4
    8288:	e8bd8800 	pop	{fp, pc}


As you can see in the above assembly code, I didn't think about what was drawn in the picture above, and put all the fp, sp, lr, pc on the stack, but only the four registers in the stack have been changed. fp is definitely to be saved, it points to the stack base address of each function stack frame, and sp generally does not need to be pushed into the stack, because its value is generally stored in fp, because when you enter a function, the last function After fp is saved on the stack, the stack space of the current function should be empty, and fp should point to the same position as sp, and then subtraction of sp will be made to allocate stack space to save temporary variables. If there is no call to other functions in the current function, the lr register will not be modified, so there is no need to save it.

However, the positions of the fp pointers of the main function and the func function above are not exactly the same. The fp in the main function points to the memory address saved by the last fp, and the fp in the func points to the same position of sp. But as long as there is no error in the recovery, it is said that these provisions of ATPCS are artificial constraints to ensure that the correct content can be restored to the register during backtrace. There is no particular rigidity in how to achieve it. definition.


Another important thing is the order of stacking. In the ARM instruction system, it is the address decrementing stack. The stacking order of the parameters of the stacking operation is from right to left. The stacking order of the parameters is from left to You operate on the right. Including push / pop and LDFMD / STMFD.

For example, the result of the execution of the instruction push {fp, sp, lr, pc} is what the stack in Figure 1 looks like. The pc is first pushed onto the stack and there is a high address, from right to left, and the fp exists on the low address.

These are more detailed and basic things, but also need to be clarified.



Reference link:

1. http://www.linuxidc.com/Linux/2013-03/81247.htm

2. http://www.cnblogs.com/chyl411/p/4579053.html

3. http://www.cnblogs.com/fanzhidongyzby/p/5250116.html

Published 60 original articles · Like 44 · Visits 340,000+

Guess you like

Origin blog.csdn.net/beyond702/article/details/52228683