函数调用的过程stack动态分析(一)

2014-11-24 08:09:02 · 作者: · 浏览: 2
一段代码的stack调用分析:
下面分析的代码:
[cpp]
/*
* =====================================================================================
*
* Filename: stack.c
*
* Description: gdb 栈的使用,对栈的分析过程
*
* Version: 1.0
* Created: 2013年02月10日 13时48分02秒
* Revision: none
* Compiler: gcc
*
* Author: LeoK,
* Organization:
*
* =====================================================================================
*/
#include
#include
#include
#include
#define MAX (1UL<<20)
typedef unsigned long long u64;
typedef unsigned int u32;
u32 max_addend = MAX;
u64 sum_till_MAX(u32 n)
{
u64 sum;
n++;
sum = n;
if (n < max_addend)
{
sum += sum_till_MAX(n);
}
return sum;
}
int main(int argc, char** argv)
{
u64 sum = 0;
if (argc == 2 && isdigit(*(argv[1])))
max_addend = strtoul(argv[1], NULL, 0);
if (max_addend >= MAX || max_addend == 0)
{
fprintf(stderr, "Invalid number is specidied\n");
return 1;
} www.2cto.com
sum = sum_till_MAX(0);
printf("sum(0..%lu) = %llu\n", max_addend, sum);
return 0;
}
图1 main函数的汇编代码
其中main调用了sum_till_MAX
步骤1:图1 movl $0x0, (%esp),这个汇编代码就是main 调用sum_till_MAX的准备工作.
主要完成的就是stack.c:51行,把0函数参数传进来(代码是图2).
图2
执行完步骤1此时的栈如下,因为程序执行的时候都是逻辑地址,所以栈地址就假设开始为0x8fff0000开始
Address Content Expain
0x8fff0000 0x0 $esp指向这里
0x8ffefffc 内容random
0x8ffefff8 内容random
0x8ffefff4 内容random
0x8ffefff0 内容random
0x8ffeffec 内容random
0x8ffeffe8 内容random
0x8ffeffe4 内容random
0x8ffeffe0 内容random
图3 步骤1完成之后栈的内容
注意:如果函数是多参数的,那么参数的入栈顺序是从右向左入栈,such as
int sum(int a, int b, int c)
这个函数的入栈顺序是push c =>push b=> push a这个做的原因可能是函数执行可变参数的原因吧
步骤2 main函数调用call sum_till_MAX这个函数首先把eip压栈,eip就是程序的执行的下一个地址,此时的stack如图4
Address Content Expain
0x8fff0000 0x0 push 0
0x8ffefffc 0x0804858d 寄存器eip esp指向这里
0x8ffefff8 内容random
0x8ffefff4 内容random
0x8ffefff0 内容random
0x8ffeffec 内容random
0x8ffeffe8 内容random
0x8ffeffe4 内容random
0x8ffeffe0 内容random
图4步骤2完毕stack情况
下面进入到sum_till_MAX函数
sum_till_MAX的反汇编代码如下:
图5sum_till_MAX函数汇编代码
步骤1 push %ebp把调用sum_till_MAX函数的ebp进行压栈,恢复上一层栈帧的时候使用,此时栈如下:
Address Content Expain
0x8fff0000 0x0 push 0
0x8ffefffc 0x0804858d 寄存器eip
0x8ffefff8 $ebp 上一个栈帧的栈基址 $esp指向这里
0x8ffefff4 内容 random
0x8ffefff0 内容random
0x8ffeffec 内容random
0x8ffeffe8 内容random
0x8ffeffe4 内容random
0x8ffeffe0 内容random
步骤2 mov %esp , %ebp这段代码表示把ebp指向esp也是就是地址0x8ffefff4地址。
步骤3 sub $0x28 , %esp表示把esp指针指向0x8ffefff4-0x28=0x8FFEFFCC,也就是为函数内部开辟新的占空间,是2*16+8=40个字节。
此时栈如下:
Address Content Expain
0x8fff0000 0x0 push 0
0x8ffefffc 0x0804858d 寄存器eip
0x8ffefff8 $ebp 上一个栈帧的栈基址
0x8ffefff4 $ebp指向这里
0x8ffefff0 内容random
0x8ffeffec 内容random
0x8ffeffcc esp指向这里
步骤4 addl $0x1, 0x8