How do function calls work in x86 32-bit assembly on Linux?

a 夏天 提交于 2019-12-11 05:52:22

问题


I am learning GNU assembly from Jonathan Bartlett's "Programming from ground up" book.

While going through the topic of a function call and stack, I'm unable to understand its working.

Below is what's written in the book:

Before executing a function, a program pushes all of the parameters for the function onto the stack in the reverse order that they are documented. Then the program issues a call instruction indicating which function it wishes to start. The call instruction does two things. First it pushes the address of the next instruction, which is the return address, onto the stack. Then it modifies the instruction pointer (%eip) to point to the start of the function. So, at the time the function starts, the stack looks like this (the "top" of the stack is at the bottom on this example):

Parameter #N
...
Parameter 2
Parameter 1
Return Address <--- (%esp)

Each of the parameters of the function have been pushed onto the stack, and finally the return address is there. Now the function itself has some work to do.

The first thing it does is save the current base pointer register, %ebp, by doing pushl %ebp. The base pointer is a special register used for accessing function parameters and local variables. Next,it copies the stack pointer to %ebp by doing movl %esp, %ebp. This allows you to be able to access the function parameters as fixed indexes from the base pointer. You may think that you can use the stack pointer for this. However, during your program you may do other things with the stack such as pushing arguments to other functions. Copying the stack pointer into the base pointer at the beginning of a function allows you to always know where your parameters are (and as we will see, local variables too), even while you may be pushing things on and off the stack. %ebp will always be where the stack pointer was at the beginning of the function, so it is more or less a constant reference to the stack frame (the stack frame consists of all of the stack variables used within a function, including parameters, local variables, and the return address).

At this point, the stack looks like this:

Parameter #N <--- N*4+4(%ebp)
...
Parameter 2 <--- 12(%ebp)
Parameter 1 <--- 8(%ebp)
Return Address <--- 4(%ebp)
Old %ebp <--- (%esp) and (%ebp)

As you can see, each parameter can be accessed using base pointer addressing mode using the %ebp register.

Can I get a concise intro on what the author wants to tell after the second paragraph. I am clearly confusing among the %esp, %ebp registers and %ebp's working here. Any help is highly appreciated.


回答1:


In the second diagram, there is this "Old %ebp <--- (%esp) and (%ebp)". What does it mean ?

It means the saved %ebp value (the caller's value that your function saves/restores) is pointed to by both %esp and your new %ebp at that point.

You just ran push %ebp, which did esp -= 4 and stored %ebp to (%esp). This saves your caller's %ebp so you can restore it later.

Then you ran mov %esp, %ebp to set up %ebp as a frame pointer. So %ebp = %esp, and they're both pointing at the last thing you pushed.



来源:https://stackoverflow.com/questions/47448283/how-do-function-calls-work-in-x86-32-bit-assembly-on-linux

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!