开发者

What is the use of "push %ebp; movl %esp, %ebp" generated by GCC for x86?

开发者 https://www.devze.com 2022-12-24 07:20 出处:网络
What effect these tw开发者_开发百科o instructions cause in the assembly code generated by gcc for x86 machines:

What effect these tw开发者_开发百科o instructions cause in the assembly code generated by gcc for x86 machines:

push %ebp
movl %esp, %ebp


unwind's explanation is the literal truth (one minor directional error notwithstanding), but doesn't explain why.

%ebp is the "base pointer" for your stack frame. It's the pointer used by the C runtime to access local variables and parameters on the stack. Here's some typical function prologue code generated by GCC (g++ to be precise) First the C++ source.

// junk.c++
int addtwo(int a)
{
    int x = 2;

    return a + x;
}

This generates the following assembler.

.file   "junk.c++"
    .text
.globl _Z6addtwoi
    .type   _Z6addtwoi, @function
_Z6addtwoi:
.LFB2:
    pushl   %ebp
.LCFI0:
    movl    %esp, %ebp
.LCFI1:
    subl    $16, %esp
.LCFI2:
    movl    $2, -4(%ebp)
    movl    -4(%ebp), %edx
    movl    8(%ebp), %eax
    addl    %edx, %eax
    leave
    ret
.LFE2:
    .size   _Z6addtwoi, .-_Z6addtwoi
    .ident  "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
    .section    .note.GNU-stack,"",@progbits

Now to explain that prologue code (all the stuff before .LCFI2:), first:

  1. pushl %ebp stores the stack frame of the calling function on the stack.
  2. movl %esp, %ebp takes the current stack pointer and uses it as the frame for the called function.
  3. subl $16, %esp leaves room for local variables.

Now your function is ready for business. Any references with a negative offset from the %ebp% register are your local variables (x in this example). Any references with a positive offset from the %ebp% register are your parameters passed in.

The final point of interest is the leave instruction which is an x86 assembler instruction which does the work of restoring the calling function's stack frame. This is usually optimized away in to the faster move %ebp %esp and pop %ebp% sequence in C code. For illustrative purposes, however, I didn't compile with any optimizations on at all.


It's typical code that you see at the beginning of a function.

It saves the contents of the EBP register on the stack, and then stores the content of the current stack pointer in EBP.

The stack is used during a function call to store local arguments. But in the function, the stack pointer may change because values are stored on the stack.

If you save the original value of the stack, you can refer to the stored arguments via the EBP register, while you can still use (add values to) the stack.

At the end of the function you will probably see the command

pop %ebp   ; restore original value 
ret        ; return 


push %ebp

This will push the 32 bit (extended) base pointer register on the stack, i.e. the stack pointer (%esp) is subtracted by four, then the value of %ebp is copied to the location that the stack pointer points to.

movl %esp, %ebp

This copies the stack pointer register to the base pointer register.

The purpose of copying the stack pointer to the base pointer is to create a stack frame, i.e. an area on the stack where a subroutine can store local data. The code in the subroutine would use the base pointer to reference the data.


It's part of what is known as the function prolog.

It saves the current base pointer that is going to be retrieved when the function ends and sets the new ebp to the beginning of the new frame.


I also think that it is important to note that often after push %ebp and movl %esp, %ebp the assembly will have push %ebx or push %edx. These are caller saves of the registers %ebx and %edx. At the end of the routine call the registers will be restored with their original values.

Also - %ebx, %esi, %edi are all callee save registers. So if you want to overwrite them you need to save them first, then restore them.


The piece of code sets up the stack for your program.

In x86 stack information is held by two registers.


    Base pointer (bp): Holds starting address of the stack
    Stack pointer (sp): Holds the address in which next value will be stored

These registers have different names in different modes:


                            Base pointer           Stack pointer
    16 bit real mode:       bp                     sp
    32 bit protected mode:  ebp(%ebp)              esp(%esp)
    64 bit mode:            rbp                    rsp

When you set up a stack, stack pointer and base pointer gets the same address at the beginning.

Now to explain your code,


    push %ebp

This code pushes the current stack address into the stack so that the function can "exit" or "return" properly.


    movl %esp, %ebp

This code sets up the stack for your function.

For more info, refer to this question.

Hope this help!

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号