MyException - 我的异常网
当前位置:我的异常网» 综合 » 函数调用的进程stack动态分析

函数调用的进程stack动态分析

www.MyException.Cn  网友分享于:2013-02-20  浏览:11次
函数调用的过程stack动态分析

一段代码的stack调用分析:

下面分析的代码:

/*
 * =====================================================================================
 *
 *       Filename:  stack.c
 *
 *    Description:  gdb 栈的使用,对栈的分析过程
 *
 *        Version:  1.0
 *        Created:  2013年02月10日 13时48分02秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  LeoK, 
 *   Organization:  
 *
 * =====================================================================================
 */
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#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;
	}
	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(%ebp)这段代码是把0拿出来(%ebp+0x8),进行++

步骤5 mov 0x8(%ebp), %eax 把变量n放到eax寄存器中

步骤6 mov 0x0 , %edx 把寄存器edx清零

步骤7 mov %eax , -0x10(%ebp)这个是sum =n 把n赋值给sum

步骤21 leave指令为删除栈帧的执行,它执行与1和2相反的处理,以释放以前的栈。

步骤22 ret 为子程序返回指令,将栈中保存的返回地址POP到程序计数寄存器中,将控制权返回给调用者.


文章评论

软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有