Question

I am following a course in computer architecture and assembly programming in Uni. Some time ago we learned how to write functions in ASM and call them from C. There is one thing I don't understand though -- at the start of every ASM function, the lecturer always makes two instructions;

pushl   %ebp
movl    %esp, %ebp

I do not understand why he does that, and what effect it has on the function when called. On my Intel Mac, when writing assembly for IA32, it seems to make no difference at all whether I include those instructions or simply skip it.

Can someone tell me what's actually going on when calling on those instructions, and why they are always called at the beginning of an ASM function? Preferably in GNU ASM, although Intel ASM is also okay.

Was it helpful?

Solution

This is part of the convention necessary for proper stack unwinding. The %ebp base pointer points to the stack frame of the caller. The calling convention is to save the caller's base pointer by pushing it on the stack. See Chapter 9 Exception handling and stack unwinding in Agner Fog's comprehensive Calling Conventions document

http://www.agner.org/optimize/calling_conventions.pdf.

If you want to use a debugger, such as gdb to debug your program, and you want it to show you a backtrace, then you need to follow that calling convention.

http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_node/gdb_42.html

A backtrace is a summary of how your program got where it is. It shows one line per frame, for many frames, starting with the currently executing frame (frame zero), followed by its caller (frame one), and on up the stack.

OTHER TIPS

Depending on the compiler, frame pointers are optional (you can omit frame pointers with Microsoft compilers). In this case, local variables and parameters are accessed as offsets from ESP instead of EBP, and EBP is freed up to be used as a generic register (although using EBP as part of an address defaults to using ss instead of ds segment register).

The reason is simple:

The mentioned function prolog saves the previous frame pointer, and sets up a new one, for the new frame. Frameless code is quite popular on 16bit/32bit x86 though...

You could look at what enter and leave do.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top