C push & pop test - c

Could someone please help me understand what the push_test() and pop_test() methods are attempting to test? These methods are attempting to test something and I can't figure out what that is.
The following code is written in c:
int push_test() {
int ret_val;
/* movl %esp, %eax ;; save stack pointer
pushl %esp ;; push stack pointer onto stack
popl %edx ;; pop the stack into %edx
subl %edx, %eax ;; subtract the two values
movl %eax, ret_val ;; set up the return value
*/
asm("movl %%esp, %%eax; pushl %%esp; popl %%edx; subl %%edx, %%eax; movl %%eax, %0"
: "=r" (ret_val)
: /* no input */
: "%edx", "%eax");
return ret_val;
}
int pop_test() {
int ret_val = 0xffffffff; /* -1 in decimal */
/* pushl ret_val ;; save ret_val on the stack
movl %esp, %edx ;; save the stack pointer
popl %esp ;; pop stack into the stack pointer
movl %esp, ret_val ;; set the popped value as the return value
movl %edx, %esp ;; restore original stack pointer
*/
asm("pushl %1; movl %%esp, %%edx; popl %%esp; movl %%esp, %0; movl %%edx, %%esp"
: "=r" (ret_val)
: "r" (ret_val)
: "%edx");
return ret_val;
}
int main() {
printf("push test: %d\n", push_test());
printf("pop test: %d\n", pop_test());
}
/* Output:
push test: 0
pop test: -1
*/

Your push_test() and pop_test() is saving the stack state, destroying the stack frame,
and then doing an operation based on values on the stack.
Let's go through each instruction of pop_test() and figure out what it does (push_test() is very similar in operation).
pushl ret_val pushes -1 onto the stack, incrementing the stack pointer (%esp), so right now your stack looks like: {-1}.
movl %esp, %edx copies your stack pointer into %edx, so %edx contains the memory address of position 1 on the stack, so right now your stack looks like : {-1}, %esp: stack[1], %edx : stack[1]
popl %esp pops -1 and stores it into %esp, so the stack looks like: {}, %esp: -1, %edx:stack[1]
movl %esp, ret_val takes the value of %esp, currently -1, and moves it into ret_val, so ret_val becomes -1.
finally movl %edx, %esp puts the value of %edx back in %esp and returns -1.
This method always returns -1. The idea is to push a value onto the stack, pop it back off, and see if the value stays the same. It also destroys and reforms the stack (by temporarily destroying and then restoring %esp). I would guess this is probably some learning assembly kind of deal and not an actual testing method.

Related

counting the '0's in a string in assembly

I have a little program written with c and assembly. the principle is simple: "count the '0's in a a string given by main.c
so for test0 str0ing 0 it should return 3 because there's 3 '0's in the string
the function itself is made in x86 asm with AT&T syntax, i am given a pointer to the string via C. both main.c and the asm is linked via header file.
this is my code so far and the problem is that it always returns 0. it never reaches conditional jump to increment %eax(to be returned)
// C
#include "asm.h"
char string[] = "2a0 a0 ";
char *ptr1 = string;
int main(){
printf("\nthere are : %d %s in :%s", zero_count(), "0s", string);
printf("\nstring address is: %p\n", ptr1);
return 0;
}
// x86asm
.global ptr1
.section .text
.global zero_count #func()
zero_count:
# prologue
pushl %ebp # save these previous stack frame pointer
movl %esp, %ebp # the stack frame pointer for function
# save registers
#pushl $ebx # needs to be pushed out of stack when used
#pushl %esi # needs to be pushed out of stack when used
#pushl %edi # needs to be pushed out of stack when used
# function body
movl ptr1, %ecx # moves the value of ptr1 to ecx
movl $0, %eax # cleans eax with 0
# loop start
loop_beginning:
cmp $0, (%ecx)
je end
# compare to 'o'
cmp $48, %ecx # 48 is "0" in the asci table
je if_0
increment_pointer:
addl $1, %ecx
jmp loop_beginning
if_0:
addl $1, %eax
jmp increment_pointer
end:
#popl %edi # needs to be popped when used
#popl %esi # needs to be popped when useds
#popl %ebx # needs to be popped when used
# epilogue
movl %ebp, %esp # restore the previous stack pointer("cleaner" the stack)
popl %ebp # restore the previous stack frame pointer
ret #w returns
i apolagize for using global variables in advance, i know it's not good but I'm still learning to use the stack
by switching the cmp to cmpb worked in this string. but i still don't know why. would this operation also worked if this was an int[]?
.global ptr1
.section .text
.global zero_count #func()
zero_count:
# prologue
pushl %ebp # save these previous stack frame pointer
movl %esp, %ebp # the stack frame pointer for function
# save registers
#pushl $ebx # needs to be pushed out of stack when used
#pushl %esi # needs to be pushed out of stack when used
#pushl %edi # needs to be pushed out of stack when used
# function body
mov ptr1, %ecx # moves the value of ptr1 to ecx
movl $0, %eax # cleans eax with 0
# loop start
loop_beginning:
cmpb $0, (%ecx)
je end
# compare to 'o'
cmpb $48, (%ecx) # 48 is "0" in the asci table
je if_0
increment_pointer:
addl $1, %ecx
jmp loop_beginning
if_0:
addl $1, %eax
jmp increment_pointer
# movl (%ecx), %eax
end:
#popl %edi # needs to be popped when used
#popl %esi # needs to be popped when useds
#popl %ebx # needs to be popped when used
# epilogue
movl %ebp, %esp # restore the previous stack pointer("cleaner" the stack)
popl %ebp # restore the previous stack frame pointer
ret #w returns

Calling C function from the x86 assembler

I am trying to write a function that converts decimal numbers into binary in assembler. Since printing is so troublesome in there, I have decided to make a separate function in C that just prints the numbers. But when I run the code, it always prints '0110101110110100'
Heres the C function (both print and conversion):
void printBin(int x) {
printf("%d", x);
}
void DecToBin(int n)
{
// Size of an integer is assumed to be 16 bits
for (int i = 15; i >= 0; i--) {
int k = n >> i;
printBin(k & 1);
}
heres the code in asm:
.globl _DecToBin
.extern _printBin
_DecToBin:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp),%eax
movl $15, %ebx
cmpl $0, %ebx
jl end
start:
movl %ebx, %ecx
movl %eax, %edx
shrl %cl, %eax
andl $1, %eax
pushl %eax
call _printBin
movl %edx, %eax
dec %ebx
cmpl $0, %ebx
jge start
end:
movl %ebp, %esp
popl %ebp
ret
Cant figure out where the mistake is. Any help would be appreciated
disassembled code using online program
Your principle problem is that it is very unlikely that %edx is preserved across the function call to printBin.
Also:
%ebx is not a volatile register in most (any?) C calling convention rules. You need to check your compilers documentation and conform to it.
If you are going to use ebx, you need to save and restore it.
The stack pointer needs to be kept aligned to 16 bytes. On my machine (macos), it SEGVs under printBin if you don’t.

C to Assembly code - what does it mean [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I'm trying to figure out exactly what is going on with the following assembly code. Can someone go down line by line and explain what is happening? I input what I think is happening (see comments) but need clarification.
.file "testcalc.c"
.section .rodata.str1.1,"aMS",#progbits,1
.LC0:
.string "x=%d, y=%d, z=%d, result=%d\n"
.text
.globl main
.type main, #function
main:
leal 4(%esp), %ecx // establish stack frame
andl $-16, %esp // decrement %esp by 16, align stack
pushl -4(%ecx) // push original stack pointer
pushl %ebp // save base pointer
movl %esp, %ebp // establish stack frame
pushl %ecx // save to ecx
subl $36, %esp // alloc 36 bytes for local vars
movl $11, 8(%esp) // store 11 in z
movl $6, 4(%esp) // store 6 in y
movl $2, (%esp) // store 2 in x
call calc // function call to calc
movl %eax, 20(%esp) // %esp + 20 into %eax
movl $11, 16(%esp) // WHAT
movl $6, 12(%esp) // WHAT
movl $2, 8(%esp) // WHAT
movl $.LC0, 4(%esp) // WHAT?!?!
movl $1, (%esp) // move result into address of %esp
call __printf_chk // call printf function
addl $36, %esp // WHAT?
popl %ecx
popl %ebp
leal -4(%ecx), %esp
ret
.size main, .-main
.ident "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
.section .note.GNU-stack,"",#progbits
Original code:
#include <stdio.h>
int calc(int x, int y, int z);
int main()
{
int x = 2;
int y = 6;
int z = 11;
int result;
result = calc(x,y,z);
printf("x=%d, y=%d, z=%d, result=%d\n",x,y,z,result);
}
You didn't show the compilation command, that could be useful, but it seems that you have optimizations enabled, so there are actually no space for local variables, they are optimized out:
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
All this code above set the stack frame. Since it is the main it is a bit different from a standard stack frame: it ensures the alignment of the stack with andl $-16, %esp, just in case.
pushl %ecx
It saves the original value of esp before the alignment correction, to restore it at the end.
subl $36, %esp
It allocates 36 bytes of stack space, not for local variables but for calling parameters.
movl $11, 8(%esp)
movl $6, 4(%esp)
movl $2, (%esp)
It sets the arguments for calling calc from right to left, that is, the constants, (2, 6, 11).
call calc // function call to calc
It calls function calc with the arguments pointed to by esp.
movl %eax, 20(%esp)
movl $11, 16(%esp)
movl $6, 12(%esp)
movl $2, 8(%esp)
movl $.LC0, 4(%esp)
movl $1, (%esp)
These are the arguments for calling __printf_chk, from right to left: (1, .LC0, 2, 6, 11, %eax), where %eax is the return value of calc() (remember, no local variables!) and .LC0 is the address of the literal string, look at these lines at the top of the assembly:
.LC0:
.string "x=%d, y=%d, z=%d, result=%d\n"
But what about that mysterious 1?. Well, in Ubuntu the standard compilation options (-D_FORTIFY_SOURCE) will make printf an inline function that forwards to __printf_chk(1, ...) or something like that, that does extra checks to the arguments.
call __printf_chk
This is the call to the printf substitute function.
addl $36, %esp
This removes the 36 bytes added to the stack with subl $36, %esp.
popl %ecx
This restores the possibly unaligned stack pointer into ecx.
popl %ebp
leal -4(%ecx), %esp
This restores the previous stack frame.
ret
And this returns without a value, because you didn't write a return for main.

previous stack variables

I have this problem, I am recursively calling a function in C and C is lexically scoped, so I can only access the current stack frame. I want to extract the arguments and the local variables from the previous stack frame which was created under the previous function call while im on the current stack frame
I know that the values from the previous recursive call are still on the stack, but I cant access access these values because they're "buried" under the active stack frame?
I want to extract the arguments and local variables from the previous stack and copy them to copy_of_buried_arg and copy_of_buried_loc;
It is a requirement to use inline assembly using GAS to extract the variables, this is what I have so far, and I tried all day, I cant seem to figure it out, I drew the stack on paper and did the calculations but nothing is working, I also tried deleting calls to printf so the stack will be cleaner but I cant figure out the right arithmetic. Here is the code so far, my function halts on the second iteration
#include <stdio.h>
char glo = 97; // just for fun 97 is ascii lowercase 'a'
int copy_of_buried_arg;
char copy_of_buried_loc;
void rec(int arg) {
char loc;
loc = glo + arg * 2; // just for fun, some char arithmetic
printf("inside rec() arg=%d loc='%c'\n", arg, loc);
if (arg != 0) {
// after this assembly code runs, the copy_of_buried_arg and
// copy_of_buried_loc variables will have arg, loc values from
// the frame of the previous call to rec().
__asm__("\n\
movl 28(%esp), %eax #moving stack pointer to old ebp (pointing it to old ebp)\n\
addl $8, %eax #now eax points to the first argument for the old ebp \n\
movl (%eax), %ecx #copy the value inside eax to ecx\n\
movl %ecx, copy_of_buried_arg # copies the old argument\n\
\n\
");
printf("copy_of_buried_arg=%u copy_of_buried_loc='%c'\n",
copy_of_buried_arg, copy_of_buried_loc);
} else {
printf("there is no buried stack frame\n");// runs if argument = 0 so only the first time
}
if (arg < 10) {
rec(arg + 1);
}
}
int main (int argc, char **argv) {
rec(0);
return 0;
}
I can try to help, but don't have Linux or assembly in GAS. But the calculations should be similar:
Here's the stack after a couple of calls. A typical stack frame setup creates a linked list of stack frames, where EBP is the current stack frame and points to its old value for the previous stack frame.
+-------+
ESP-> |loc='c'| <- ESP currently points here.
+-------+
EBP-> |oldEBP |--+ <- rec(0)'s call frame
+-------+ |
|retaddr| | <- return value of rec(1)
+-------+ |
|arg=1 | | <- pushed argument of rec(1)
+-------+ |
|loc='a'| | <- local variable of rec(0)
+-------+ |
+--|oldEBP |<-+ <- main's call frame
| +-------+
| |retaddr| <- return value of rec(0)
| +-------+
| |arg=0 | <- pushed argument of rec(0)
| +-------+
\|/
to main's call frame
This is created by the following sequence:
Push arguments last arg first.
Call the function, pushing a return address.
Push soon-to-be old EBP, preserving previous stack frame.
Move ESP (top of stack, containing oldEBP) into EBP, creating new stack frame.
Subtract space for local variables.
This has the effect on a 32-bit stack that EBP+8 will always be the first parameter of the call, EBP+12 the 2nd parameter, etc. EBP-n is always an offset to a local variable.
The code to get the previous loc and arg is then (in MASM):
mov ecx,[ebp] // get previous stack frame
mov edx,[ecx]+8 // get first argument
mov copy_of_buried_arg,edx // save it
mov dl,[ecx]-1 // get first char-sized local variable.
mov copy_of_buried_loc,dl // save it
or my best guess in GAS (I don't know it but know it is backwards to MASM):
movl (%ebp),ecx
movl 8(%ecx),edx
movl edx,copy_of_buried_arg
movb -1(%ecx),dl
movb dl,copy_of_buried_loc
Output of your code with my MASM using VS2010 on Windows:
inside rec() arg=0 loc='a'
there is no buried stack frame
inside rec() arg=1 loc='c'
copy_of_buried_arg=0 copy_of_buried_loc='a'
inside rec() arg=2 loc='e'
copy_of_buried_arg=1 copy_of_buried_loc='c'
inside rec() arg=3 loc='g'
copy_of_buried_arg=2 copy_of_buried_loc='e'
inside rec() arg=4 loc='i'
copy_of_buried_arg=3 copy_of_buried_loc='g'
inside rec() arg=5 loc='k'
copy_of_buried_arg=4 copy_of_buried_loc='i'
inside rec() arg=6 loc='m'
copy_of_buried_arg=5 copy_of_buried_loc='k'
inside rec() arg=7 loc='o'
copy_of_buried_arg=6 copy_of_buried_loc='m'
inside rec() arg=8 loc='q'
copy_of_buried_arg=7 copy_of_buried_loc='o'
inside rec() arg=9 loc='s'
copy_of_buried_arg=8 copy_of_buried_loc='q'
inside rec() arg=10 loc='u'
copy_of_buried_arg=9 copy_of_buried_loc='s'
With my compiler (gcc 3.3.4) I ended up with this:
#include <stdio.h>
char glo = 97; // just for fun 97 is ascii lowercase 'a'
int copy_of_buried_arg;
char copy_of_buried_loc;
void rec(int arg) {
char loc;
loc = glo + arg * 2; // just for fun, some char arithmetic
printf("inside rec() arg=%d loc='%c'\n", arg, loc);
if (arg != 0) {
// after this assembly code runs, the copy_of_buried_arg and
// copy_of_buried_loc variables will have arg, loc values from
// the frame of the previous call to rec().
__asm__ __volatile__ (
"movl 40(%%ebp), %%eax #\n"
"movl %%eax, %0 #\n"
"movb 31(%%ebp), %%al #\n"
"movb %%al, %1 #\n"
: "=m" (copy_of_buried_arg), "=m" (copy_of_buried_loc)
:
: "eax"
);
printf("copy_of_buried_arg=%u copy_of_buried_loc='%c'\n",
copy_of_buried_arg, copy_of_buried_loc);
} else {
printf("there is no buried stack frame\n");// runs if argument = 0 so only the first time
}
if (arg < 10) {
rec(arg + 1);
}
}
int main (int argc, char **argv) {
rec(0);
return 0;
}
Here's the disassembly of the relevant part (get it with gcc file.c -S -o file.s):
_rec:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
movl 8(%ebp), %eax
addl %eax, %eax
addb _glo, %al
movb %al, -1(%ebp)
subl $4, %esp
movsbl -1(%ebp),%eax
pushl %eax
pushl 8(%ebp)
pushl $LC0
call _printf
addl $16, %esp
cmpl $0, 8(%ebp)
je L2
/APP
movl 40(%ebp), %eax #
movl %eax, _copy_of_buried_arg #
movb 31(%ebp), %al #
movb %al, _copy_of_buried_loc #
/NO_APP
subl $4, %esp
movsbl _copy_of_buried_loc,%eax
pushl %eax
pushl _copy_of_buried_arg
pushl $LC1
call _printf
addl $16, %esp
jmp L3
L2:
subl $12, %esp
pushl $LC2
call _printf
addl $16, %esp
L3:
cmpl $9, 8(%ebp)
jg L1
subl $12, %esp
movl 8(%ebp), %eax
incl %eax
pushl %eax
call _rec
addl $16, %esp
L1:
leave
ret
Those offsets from ebp (40 and 31) initially were set to an arbitrary guess value (e.g. 0) and then refined through observation of the disassembly and some simple calculations.
Note that the function uses extra 12+4=16 bytes of stack for the alignment and the parameter when it calls itself recursively:
subl $12, %esp
movl 8(%ebp), %eax
incl %eax
pushl %eax
call _rec
addl $16, %esp
There are also 4 bytes of the return address.
And then the function uses 4+8=12 bytes for the old ebp and its local variables:
_rec:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
So, in total the stack grows by 16+4+12=32 bytes with each recursive call.
Now, we know how to get our local arg and loc through ebp:
movl 8(%ebp), %eax ; <- arg
addl %eax, %eax
addb _glo, %al
movb %al, -1(%ebp) ; <- loc
So, we just add 32 to those offsets 8 and -1 and arrive at 40 and 31.
Do the same and you'll get your "buried" variables.

why is the call stack set up like this?

I was just playing with the call stack, trying to change the return address of a function etc, and wound up writing this program in C:
#include<stdio.h>
void trace(int);
void func3(int);
void func2(int);
void func1(int);
int main(){
int a = 0xAAAA1111;
func1(0xFCFCFC01);
return 0;
}
void func1(int a){
int loc = 0xBBBB1111;
func2(0xFCFCFC02);
}
void func2(int a){
int loc1 = 0xCCCC1111;
int loc2 = 0xCCCC2222;
func3(0xFCFCFC03);
}
void func3(int a){
int loc1 = 0xDDDD1111;
int loc2 = 0xDDDD2222;
int loc3 = 0xDDDD3333;
trace(0xFCFCFC04);
}
void trace(int a){
int loc = 0xEEEE1111;
int *ptr = &loc;
do {
printf("0x%08X : %08X\n", ptr, *ptr, *ptr);
} while(*(ptr++) != 0xAAAA1111);
}
(sorry for the length)
This produced the following output (with comments that I added):
0xBF8144D4 : EEEE1111 //local int in trace
0xBF8144D8 : BF8144F8 //beginning of trace stack frame
0xBF8144DC : 0804845A //return address for trace to func3
0xBF8144E0 : FCFCFC04 //int passed to trace
0xBF8144E4 : 08048230 //(possibly) uninitialized padding
0xBF8144E8 : 00000000 //padding
0xBF8144EC : DDDD3333 //local int in func3
0xBF8144F0 : DDDD2222 //local int in func3
0xBF8144F4 : DDDD1111 //local int in func3
0xBF8144F8 : BF814518 //beginning of func3 stack frame
0xBF8144FC : 08048431 //return address for func3 to func2
0xBF814500 : FCFCFC03 //parameter passed to func3
0xBF814504 : 00000000 //padding
0xBF814508 : 00000000 //padding
0xBF81450C : 00000000 //padding
0xBF814510 : CCCC2222 //local int in func2
0xBF814514 : CCCC1111 //local int in func2
0xBF814518 : BF814538 //beginning of func2 stack frame
0xBF81451C : 0804840F //return address for func2 to func1
0xBF814520 : FCFCFC02 //parameter passed to func2
0xBF814524 : 00000000 //padding
0xBF814528 : BF816728 //uninitialized padding
0xBF81452C : B7DF3F4E //uninitialized padding
0xBF814530 : B7EA61D9 //uninitialized padding
0xBF814534 : BBBB1111 //local int in func1
0xBF814538 : BF814558 //beginning of func1 stack frame
0xBF81453C : 080483E8 //return address for func1 to main
0xBF814540 : FCFCFC01 //parameter passed to func1
0xBF814544 : 08049FF4 //(maybe) padding
0xBF814548 : BF814568 //(maybe) padding
0xBF81454C : 080484D9 //(maybe) padding
0xBF814550 : AAAA1111 //local int in main
I was wondering if anybody could fill me in on the blank spots here... I'm running Ubuntu linux compiling with gcc 4.3.3 (on an x86 -- AMD Turion 64)
What are the 0804... numbers? What's the third address up from the bottom? Is that the return address for main? If so, why is it out of order compared to the rest of the stack?
The 0x0804 numbers are return addresses, or pointers to code/data or something, while the 0xBF814 numbers are stack pointers
What's this:
0xBF814524 : 00000000 //padding?
0xBF814528 : BF816728 //I have no idea
0xBF81452C : B7DF3F4E //????
0xBF814530 : B7EA61D9 //????
seen just after the local int in func1?
Okay I have my stack dump almost completely filled in.
It looks like the the compiler wants to have the parameters pushed onto the stack starting at a 0x.......0 address, and everything between the local variables from the function before and the first parameter of the function being called seems to be padding (whether 0x00000000 or some uninitialized value). Some of them I'm unsure about because they look like code/data segment pointers, but I can't see them being used in the code: they're just there when the stack pointer gets reduced.
and I know it's a HUGE nono to touch the call stack in any kind of project, but that's okay. It's fun, right?
also
Greg wants to see the assembly,
here it is
.file "stack.c"
.text
.globl main
.type main, #function
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
subl $20, %esp
movl $-1431695087, -8(%ebp)
movl $-50529279, (%esp)
call func1
movl $0, %eax
addl $20, %esp
popl %ecx
popl %ebp
leal -4(%ecx), %esp
ret
.size main, .-main
.globl func1
.type func1, #function
func1:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
movl $-1145368303, -4(%ebp)
movl $-50529278, (%esp)
call func2
leave
ret
.size func1, .-func1
.globl func2
.type func2, #function
func2:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
movl $-859041519, -4(%ebp)
movl $-859037150, -8(%ebp)
movl $-50529277, (%esp)
call func3
leave
ret
.size func2, .-func2
.globl func3
.type func3, #function
func3:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
movl $-572714735, -4(%ebp)
movl $-572710366, -8(%ebp)
movl $-572705997, -12(%ebp)
movl $-50529276, (%esp)
call trace
leave
ret
.size func3, .-func3
.section .rodata
.LC0:
.string "0x%08X : %08X\n"
.text
.globl trace
.type trace, #function
trace:
pushl %ebp
movl %esp, %ebp
subl $40, %esp
movl $-286387951, -4(%ebp)
leal -4(%ebp), %eax
movl %eax, -8(%ebp)
.L10:
movl -8(%ebp), %eax
movl (%eax), %edx
movl -8(%ebp), %eax
movl (%eax), %eax
movl %edx, 12(%esp)
movl %eax, 8(%esp)
movl -8(%ebp), %eax
movl %eax, 4(%esp)
movl $.LC0, (%esp)
call printf
movl -8(%ebp), %eax
movl (%eax), %eax
cmpl $-1431695087, %eax
setne %al
addl $4, -8(%ebp)
testb %al, %al
jne .L10
leave
ret
.size trace, .-trace
.ident "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
.section .note.GNU-stack,"",#progbits
Inspecting the stack like this seems like one step too far away. I might suggest loading your program in a debugger, switching to the assembly language view, and single stepping through every machine instruction. Understanding of the CPU stack necessarily requires an understanding of the machine instructions operating on it, and this will be a more direct way to see what's going on.
As others mentioned, the structure of the stack is also highly dependent on the processor architecture you're working with.
Most likely those are stack canaries. Your compiler adds code to push additional data to the stack and read it back afterwards to detect stack overflows.
I'm guessing those values starting with 0x0804 are addresses in your program's code segement (like return addresses for function calls). The ones starting with 0xBF814 that you've labeled as return addresses are addresses on the stack -- data, not code. I'm guessing they're probably frame pointers.
As already pointed out, the 0xBF... are frame pointers and 0x08... return addresses.
The padding is due to alignment issues. Other unrecognized values are also padding as the stack is not initalized to zero or any other value. Uninitialized variables and unused padding space will contain whatever bytes are in those memory locations.
The 0xBF... addresses will be links to the previous stack frame:
0xBF8144D8 : BF8144F8 //return address for trace
0xBF8144DC : 0804845A //
0xBF8144F8 : BF814518 //return address for func3
0xBF8144FC : 08048431 //????
0xBF814518 : BF814538 //return address for func2?
0xBF81451C : 0804840F //????
0xBF814538 : BF814558 //return address for func1
0xBF81453C : 080483E8 //????
The 0x08... addresses will be the addresses of the code to return to in each case.
I can't speak for the other stuff on the stack; you would have to step through the assembly language and see exactly what it is doing. I guess that it is aligning the start of each frame to a specific alignment so that __attribute__((align)) (or whatever it's called these days...) works.
The compiler uses EBP to store the frame's base address. It's been a while so I looked at this, so I may get the details a bit wrong, but the idea is like this.
You have three steps when calling a function:
The caller pushes the function's parameters onto the stack.
The caller uses the call instruction, which pushes the return address onto the stack, and jumps to the new function.
The called function pushes EBP onto the stack, and copies ESP into EBP:
(Note: well behaved functions will also push all the GPRs onto the stack with PUSHAD)
push EBP
mov EBP, ESP
When the function returns it:
pops EBP
executes the ret instruction, which pops off the return address and jumps there.
pop EBP
ret
The question is, why is EBP pushed, and why does ESP get copied into it?
When you enter the function ESP points to the lowest point on the stack for this function. Any variables you declare on the stack can be accessed as [ESP + offset_to_variable]. This is easy! But note that ESP must always point to the top of the stack, so when you declare a new variable on the stack, ESP changes. Now [ESP + offset_to_variable] isn't so great, because you have to remember what ESP was at the time the variable was allocated.
Instead of doing that, the first thing the function needs to do is to copy ESP into EBP. EBP won't change during the life of the function, so you can access all variables using `[EBP + offset_to_variable]. But now you have another problem, because if the called functions calls another function, EBP will be overwritten. That's why before copying EBP it needs to be saved onto the stack, so that it can be restored before the returning to the calling function.
Is this a debug or release build? I'd expect some padding with the debug builds for detecting Stack Overflows.

Resources