I am trying to draw a stack as it would appear just before the “return count” line in the secondCall function. I am trying to draw it so that it would show all three frames (or activation records) for the three active functions, main, firstCall and secondCall.
Will someone help me complete the stack diagram?
I am trying to draw the positions of the base (ebp) and stack (esp) pointers as they were in each stack frame before the call to the next function.
The C code is as follows:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int secondCall(int a, int b) {
int count;
count = write(STDOUT_FILENO, &"hello\n", 6);
count += write(STDOUT_FILENO, &"jbnd007\n", 8);
count += a + b;
return count;
}
int firstCall(void) {
int local;
local = secondCall(4, 2);
return local;
}
int main(int argc, char** argv) {
int result;
result = firstCall();
return (EXIT_SUCCESS);
}
The Assembly code is as follows:
.file "A3Program2.c"
.section .rodata
.LC0:
.string "hello\n"
.LC1:
.string "jbnd007\n"
.text
.globl secondCall
.type secondCall, @function
secondCall:
pushl %ebp
movl %esp, %ebp
subl $40, %esp
movl $6, 8(%esp)
movl $.LC0, 4(%esp)
movl $1, (%esp)
call write
movl %eax, -12(%ebp)
movl $8, 8(%esp)
movl $.LC1, 4(%esp)
movl $1, (%esp)
call write
addl %eax, -12(%ebp)
movl 12(%ebp), %eax
movl 8(%ebp), %edx
leal (%edx,%eax), %eax
addl %eax, -12(%ebp)
movl -12(%ebp), %eax
leave
ret
.size secondCall, .-secondCall
.globl firstCall
.type firstCall, @function
firstCall:
pushl %ebp
movl %esp, %ebp
subl $40, %esp
movl $2, 4(%esp)
movl $4, (%esp)
call secondCall
movl %eax, -12(%ebp)
movl -12(%ebp), %eax
leave
ret
.size firstCall, .-firstCall
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
andl $-16, %esp
subl $16, %esp
call firstCall
movl %eax, 12(%esp)
movl $0, %eax
leave
ret
.size main, .-main
.ident "GCC: (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5"
.section .note.GNU-stack,"",@progbits
The stack drawing right now I have is :
+------------------------------+ high address
| original position of stack pointer
+------------------------------+
| saved value of ebp <- ebp (base pointer when in main)
+------------------------------+
| alignment spacing (don’t really know how big until runtime)
+------------------------------+
|
+------------------------------+
|
+------------------------------+
|
+------------------------------+
...
Each line represents 4 bytes (from lowest address (left) to highest address (right)).
I’m not going to do the whole thing for you, but here’s a detailed explanation of how to follow through what happens.
On entry to
mainthe stack looks like this:Standard prologue code:
This aligns the stack down to a 16-byte boundary by zeroing the bottom 4 bits
of
%esp:…which is where you got to. Continuing:
This subtracts 16 bytes from the stack pointer, which creates 16 bytes of reserved space for
mainto use:Now
maincallsfirstCall; thecallinstruction pushes the return address, so at the point just afterfirstCallhas been entered, the stack will look like this:The return address will be popped off again when returning to
maindue to theretinstruction at the end offirstCall.…and so on. Just keep tracing through the code in the same way, following what
%espis doing.The other thing that perhaps needs explanation is the
leavewhich appears in theepilogue code of the various routines. So here’s how that works for
main:Just before
leavenear the end ofmain, the stack looks like this (we’ve returned fromfirstCalland stored a value in the reserved space):
leaveis equivalent tomovl %ebp, %espfollowed bypopl %ebp. So:And finally the
retpops the return address and execution continues insidewhatever called
main.