一步一步写算法(之函数堆栈显示)

原文:一步一步写算法(之函数堆栈显示)

【 声明:版权所有,欢迎转载,请勿用于商业用途。  联系信箱:feixiaoxing @163.com 】

    在继续图的讨论之前,我们今天开个小差,讨论一下函数堆栈的基本原理。有过编程经验的朋友都知道,堆栈调试是我们在程序开发中经常应用的一个功能。那么大家有没有想过,函数堆栈是怎么开始的啊?其实我们可以自己写一个函数堆栈输出函数分析一下。

    因为一般来说,函数的压栈过程是这样的:

              |    参数三  |

              |    参数二  |

              |    参数一  |

              |   address|

              |      ebp     |

              |   variable |     <--------------------------------- ebp

      那么堆栈中的内容是怎么打印的呢?

void stack_print()
{
	int var_ebp;

	__asm mov var_ebp, ebp;

	printf("%08x\n", *((int*)(var_ebp) + 1));
}

    上面的代码只是打印当前函数的返回地址,那么如果是连续的函数打印呢?打印到main函数开始呢。

void stack_print()
{
	int var_ebp;

	__asm mov var_ebp, ebp;

	do{
        printf("%08x\n", *((int*)(var_ebp) + 1));
        var_ebp = *(int*)(var_ebp);

	}while(var_ebp != 0x0);
}

    上面的代码可看到一对地址,那么怎么把这些地址和函数名称对应起来了,那就只能查表了。函数对应的表在哪里呢?不着急,看了下面的一个截图,朋友们就明白怎么回事了。

                                   

    大家这样在VC编译的时候把Generate mapfile选上,就可以生成对应的*.map文件了。文件中包含了当前文件中主要函数的起始地址,而且是按照从低到高依次排序的。所以只要寻找到对应的函数起始,判断我们的函数返回地址是不是在这个函数中间,那么就可以找到对应的函数名称了。

总结:

    (1)今天总结了一下函数堆栈显示的基本原理;

    (2)知道函数的基本原理之后,方便我们从本质上理解很多问题。即使很多CPU的处理方式和X86不同,我们也可以通过类似的方法快速掌握;

    (3)堆栈原理十分重要,朋友们应该好好了解一下。

时间: 2024-09-22 12:40:52

一步一步写算法(之函数堆栈显示)的相关文章

一步一步写算法(之克鲁斯卡尔算法 下)

原文:一步一步写算法(之克鲁斯卡尔算法 下) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com]     前面在讨论克鲁斯卡尔的算法的时候,我们分析了算法的基本过程.基本数据结构和算法中需要解决的三个问题(排序.判断.合并).今天,我们继续完成剩下部分的内容.合并函数中,我们调用了两个基本函数,find_tree_by_index和delete_mini_tree_from_group,下面给出详细的计算过程. MINI_GENERATE_T

一步一步写算法(之线性结构的处理)

原文:一步一步写算法(之线性结构的处理) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com]     我们知道,在内存中的空间都是连续的.也就是说,0x00000001下面的地址必然是0x00000002.所以,空间上是不会出现地址的突变的.那什么数据结构类型是连续内部空间呢,其实就是数组,当然也可以是堆.数组有很多优势,它可以在一段连续空间内保存相同类型的数据,并且对这些数据进行管理.所以从这个意义上说,掌握了数组才能说明你数据结构入门了.

一步一步写算法(之字符串查找 中篇)

原文:一步一步写算法(之字符串查找 中篇) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com]     昨天我们编写了简单的字符查找函数.虽然比较简单,但是也算能用.然而,经过我们仔细分析研究一下,这么一个简单的函数还是有改进的空间的.在什么地方改进呢?大家可以慢慢往下看.     下面的代码是优化前的代码,现在再贴一次,这样分析起来也方便些: char* strstr(const char* str, char* data) { int i

一步一步写算法(之非递归排序)

原文:一步一步写算法(之非递归排序) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com]        在上面一篇博客当中,我们发现普通查找和排序查找的性能差别很大.作为一个100万的数据,如果使用普通的查找方法,那么每一个数据查找平均下来就要几十万次,那么二分法的查找呢,20多次就可以搞定.这中间的差别是非常明显的.既然排序有这么好的效果,那么这篇博客中,我们就对排序算做一个总结.     按照我个人的理解,排序可以分为两种:一种是非递归排

一步一步写算法(之寻找丢失的数)

原文:一步一步写算法(之寻找丢失的数) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com]     假设我们有一个1亿个数据,其中数据的范围是0~1亿,也就是100M的数据.但是这个数组中丢了一些数据,比如说少了5啊,少了10啊,那么有什么办法可以把这些丢失的数据找回来呢?这个题目不难,但是它可以帮助我们拓展思路,不断提高算法的运行效率.     对于这个问题,我们一个最简单的思路就是对各个数据进行flag判断,然后依次输出数据. void

一步一步写算法(之排序二叉树删除-1)

原文:一步一步写算法(之排序二叉树删除-1) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com]     相比较节点的添加,平衡二叉树的删除要复杂一些.因为在删除的过程中,你要考虑到不同的情况,针对每一种不同的情况,你要有针对性的反应和调整.所以在代码编写的过程中,我们可以一边写代码,一边写测试用例.编写测试用例不光可以验证我们编写的代码是否正确,还能不断提高我们开发代码的自信心.这样,即使我们在开发过程对代码进行修改或者优化也不会担心害怕.

一步一步写算法(之字符串查找 上篇)

原文:一步一步写算法(之字符串查找 上篇) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com]     字符串运算是我们开发软件的基本功,其中比较常用的功能有字符串长度的求解.字符串的比较.字符串的拷贝.字符串的upper等等.另外一个经常使用但是却被我们忽视的功能就是字符串的查找.word里面有字符串查找.notepad里面有字符串查找.winxp里面也有系统自带的字符串的查找,所以编写属于自己的字符串查找一方面可以提高自己的自信心,另外一

一步一步写算法(之循环单向链表)

原文:一步一步写算法(之循环单向链表) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com]     前面的博客中,我们曾经有一篇专门讲到单向链表的内容.那么今天讨论的链表和上次讨论的链表有什么不同呢?重点就在这个"循环"上面.有了循环,意味着我们可以从任何一个链表节点开始工作,可以把root定在任何链表节点上面,可以从任意一个链表节点访问数据,这就是循环的优势.     那么在实现过程中,循环单向链表有什么不同?     1)打印链

一步一步写算法(之克鲁斯卡尔算法 中)

原文:一步一步写算法(之克鲁斯卡尔算法 中) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com]     前面说到,克鲁斯卡尔的算法是按照各个line的权重依次进行添加的,那么这就涉及到一个权重的排序问题.怎么排序呢?可以采用最简单的冒泡排序算法.可是这里排序的是数据结构,怎么办呢?那就只好采用通用排序算法了. void bubble_sort(void* array[], int length, int (*compare)(void*,