在繼續(xù)圖的討論之前,我們今天開個(gè)小差,討論一下函數(shù)堆棧的基本原理。有過編程經(jīng)驗(yàn)的朋友都知道,堆棧調(diào)試是我們在程序開發(fā)中經(jīng)常應(yīng)用的一個(gè)功能。那么大家有沒有想過,函數(shù)堆棧是怎么開始的?。科鋵?shí)我們可以自己寫一個(gè)函數(shù)堆棧輸出函數(shù)分析一下。
因?yàn)橐话銇碚f,函數(shù)的壓棧過程是這樣的:
| 參數(shù)三 |
| 參數(shù)二 |
| 參數(shù)一 |
| address|
| ebp |
| variable | <--------------------------------- ebp
那么堆棧中的內(nèi)容是怎么打印的呢?
void stack_print()
{
int var_ebp;
__asm mov var_ebp, ebp;
printf("%08xn", *((int*)(var_ebp) + 1));
}
上面的代碼只是打印當(dāng)前函數(shù)的返回地址,那么如果是連續(xù)的函數(shù)打印呢?打印到main函數(shù)開始呢。
void stack_print()
{
int var_ebp;
__asm mov var_ebp, ebp;
do{
printf("%08xn", *((int*)(var_ebp) + 1));
var_ebp = *(int*)(var_ebp);
}while(var_ebp != 0x0);
}
上面的代碼可看到一對地址,那么怎么把這些地址和函數(shù)名稱對應(yīng)起來了,那就只能查表了。函數(shù)對應(yīng)的表在哪里呢?不著急,看了下面的一個(gè)截圖,朋友們就明白怎么回事了。
http://wiki.jikexueyuan.com/project/step-by-step-learning-algorithm/images/1.gif" alt="" />
大家這樣在VC編譯的時(shí)候把Generate mapfile選上,就可以生成對應(yīng)的*.map文件了。文件中包含了當(dāng)前文件中主要函數(shù)的起始地址,而且是按照從低到高依次排序的。所以只要尋找到對應(yīng)的函數(shù)起始,判斷我們的函數(shù)返回地址是不是在這個(gè)函數(shù)中間,那么就可以找到對應(yīng)的函數(shù)名稱了。
總結(jié):
(1)今天總結(jié)了一下函數(shù)堆棧顯示的基本原理;
(2)知道函數(shù)的基本原理之后,方便我們從本質(zhì)上理解很多問題。即使很多CPU的處理方式和X86不同,我們也可以通過類似的方法快速掌握;
(3)堆棧原理十分重要,朋友們應(yīng)該好好了解一下。