`
hulianwang2014
  • 浏览: 681164 次
文章分类
社区版块
存档分类
最新评论
  • bcworld: 排版成这样,一点看的欲望都没有了
    jfinal

函数调用的过程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到程序计数寄存器中,将控制权返回给调用者.


分享到:
评论

相关推荐

    传智播客扫地僧视频讲义源码

    20_课堂答疑_函数调用流程入栈出栈过程 21_指针也是一种数据类型_基础 22_指针也是一种数据类型_强化_传智扫地僧 源码及文档 01_课程回顾 02_作业题强化和野指针 03_向null地址copy数据和不断改变指针指向强化 04_...

    Visual C++ 数据库系统开发完全手册.part2

    2.5.1 函数的定义与调用 2.5.2 默认参数 2.5.3 函数重载概述 2.6 编译预处理指令 2.6.1 #include文件包含指令 2.6.2 #define宏定义指令 2.6.3 条件编译指令 第3章 面向对象的程序设计 3.1 概述 3.1.1 面向对象程序...

    Visual C++ 数据库系统开发完全手册.part1

    2.5.1 函数的定义与调用 2.5.2 默认参数 2.5.3 函数重载概述 2.6 编译预处理指令 2.6.1 #include文件包含指令 2.6.2 #define宏定义指令 2.6.3 条件编译指令 第3章 面向对象的程序设计 3.1 概述 3.1.1 面向对象程序...

    McGraw C++程序调试实用手册

    2.2.14 函数调用之间允许使用别名 2.2.15 全局优化 2.2.16 产生内部函数的内联 2.2.17 优化math.h 2.3 Microsoft C++的优化开关 2.4 使用 Microsoft Visual Studio设置编译器选项 2.4.1 Project ...

    OllyDbg 1.0.10.0 32位程序分析调试软件

     动态跟踪时,与指令相关的各寄存器的值、API函数调用提示、跳转提示等信息显示。 3.数据窗口  以十六进制或内存方式显示文件在内容中的数据,类似于softICE的数据窗口。要显示数据可单击右键"转到→表达式(Go to...

    keil中文手册

    10. 调用线窗口(Call-Stack Window)... 33 11. 代码覆盖窗口... 33 12. 外围设备窗口(peripherals) 33 第二节 dScope for Windows基本操作... 33 1. 指定初始化文件... 33 2. 观察变量... 33 3. 显示RAM的值... ...

    超级有影响力霸气的Java面试题大全文档

    21、heap和stack有什么区别。  栈是一种线形集合,其添加和删除元素的操作应在同一段完成。栈按照后进先出的方式进行处理。 堆是栈的一个组成元素 22、forward 和redirect的区别  forward是服务器请求资源,...

    java 面试题 总结

    18、heap和stack有什么区别。 栈是一种线形集合,其添加和删除元素的操作应在同一段完成。栈按照后进先出的方式进行处理。 堆是栈的一个组成元素 19、forward 和redirect的区别 forward是服务器请求资源,服务器直接...

    Think in Java(中文版)chm格式

    1.12 分析和设计 1.12.1 不要迷失 1.12.2 阶段0:拟出一个计划 1.12.3 阶段1:要制作什么? 1.12.4 阶段2:开始构建? 1.12.5 阶段3:正式创建 1.12.6 阶段4:校订 1.12.7 计划的回报 1.13 Java还是C++? ...

    Java初学者入门教学

    1.12 分析和设计 1.12.1 不要迷失 1.12.2 阶段0:拟出一个计划 1.12.3 阶段1:要制作什么? 1.12.4 阶段2:开始构建? 1.12.5 阶段3:正式创建 1.12.6 阶段4:校订 1.12.7 计划的回报 1.13 Java还是C++? 第2章 ...

    JAVA_Thinking in Java

    1.12 分析和设计 1.12.1 不要迷失 1.12.2 阶段0:拟出一个计划 1.12.3 阶段1:要制作什么? 1.12.4 阶段2:开始构建? 1.12.5 阶段3:正式创建 1.12.6 阶段4:校订 1.12.7 计划的回报 1.13 Java还是C++? 第2章 ...

    ThinkInJava

    1.12 分析和设计 1.12.1 不要迷失 1.12.2 阶段0:拟出一个计划 1.12.3 阶段1:要制作什么? 1.12.4 阶段2:开始构建? 1.12.5 阶段3:正式创建 1.12.6 阶段4:校订 1.12.7 计划的回报 1.13 Java还是C++? 第2章 ...

    java 编程入门思考

    1.12 分析和设计 1.12.1 不要迷失 1.12.2 阶段0:拟出一个计划 1.12.3 阶段1:要制作什么? 1.12.4 阶段2:开始构建? 1.12.5 阶段3:正式创建 1.12.6 阶段4:校订 1.12.7 计划的回报 1.13 Java还是C++? 第2章 ...

    thinkinjava

    1.12 分析和设计 1.12.1 不要迷失 1.12.2 阶段0:拟出一个计划 1.12.3 阶段1:要制作什么? 1.12.4 阶段2:开始构建? 1.12.5 阶段3:正式创建 1.12.6 阶段4:校订 1.12.7 计划的回报 1.13 Java还是C++? 第2章 ...

    Thinking in Java简体中文(全)

    1.12 分析和设计 1.12.1 不要迷失 1.12.2 阶段0:拟出一个计划 1.12.3 阶段1:要制作什么? 1.12.4 阶段2:开始构建? 1.12.5 阶段3:正式创建 1.12.6 阶段4:校订 1.12.7 计划的回报 1.13 Java还是C++? 第2章 ...

    java联想(中文)

    1.12 分析和设计 1.12.1 不要迷失 1.12.2 阶段0:拟出一个计划 1.12.3 阶段1:要制作什么? 1.12.4 阶段2:开始构建? 1.12.5 阶段3:正式创建 1.12.6 阶段4:校订 1.12.7 计划的回报 1.13 Java还是C++? 第2章 ...

Global site tag (gtag.js) - Google Analytics