一步一步寫算法(之函數堆棧顯示)

原貼地址:

【 聲明:版權所有,歡迎轉載,請勿用於商業用途。  聯繫信箱:feixiaoxing @163.com 】


    在繼續圖的討論之前,我們今天開個小差,討論一下函數堆棧的基本原理。有過編程經驗的朋友都知道,堆棧調試是我們在程序開發中經常應用的一個功能。那麼大家有沒有想過,函數堆棧是怎麼開始的啊?其實我們可以自己寫一個函數堆棧輸出函數分析一下。

    因爲一般來說,函數的壓棧過程是這樣的:

              |    參數三  |

              |    參數二  |

              |    參數一  |

              |   address|

              |      ebp     |

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

      那麼堆棧中的內容是怎麼打印的呢?

  1. void stack_print()  
  2. {  
  3.     int var_ebp;  
  4.   
  5.     __asm mov var_ebp, ebp;  
  6.   
  7.     printf("%08x\n", *((int*)(var_ebp) + 1));  
  8. }  
    上面的代碼只是打印當前函數的返回地址,那麼如果是連續的函數打印呢?打印到main函數開始呢。

  1. void stack_print()  
  2. {  
  3.     int var_ebp;  
  4.       
  5.     __asm mov var_ebp, ebp;  
  6.   
  7.     do{  
  8.         printf("%08x\n", *((int*)(var_ebp) + 1));  
  9.         var_ebp = *(int*)(var_ebp);  
  10.   
  11.     }while(var_ebp != 0x0);  
  12. }  
    上面的代碼可看到一對地址,那麼怎麼把這些地址和函數名稱對應起來了,那就只能查表了。函數對應的表在哪裏呢?不着急,看了下面的一個截圖,朋友們就明白怎麼回事了。

                                   

    大家這樣在VC編譯的時候把Generate mapfile選上,就可以生成對應的*.map文件了。文件中包含了當前文件中主要函數的起始地址,而且是按照從低到高依次排序的。所以只要尋找到對應的函數起始,判斷我們的函數返回地址是不是在這個函數中間,那麼就可以找到對應的函數名稱了。


總結:

    (1)今天總結了一下函數堆棧顯示的基本原理;

    (2)知道函數的基本原理之後,方便我們從本質上理解很多問題。即使很多CPU的處理方式和X86不同,我們也可以通過類似的方法快速掌握;

    (3)堆棧原理十分重要,朋友們應該好好了解一下。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章