瞭解函數調用,所涉及棧幀分配,見下圖1:
這個圖也有意思,把函數調用之間的關係展示了出來。
理論分析
假設現在有函數f,固定參數m個,可變參數n(未知)個,假設所有參數都是32位整數,如果不是整數,也可以根據參數類型,推出參數地址,爲了簡單畫圖,在此使用整數。
自右向左(逆變量聲明順序)
那麼調用棧圖
自右向左入棧的調用棧
雖然不知道可變參數n的大小,但是,依然可以根據固定參數的大小m,找到
可變參數的開始位置,然後去訪問就可以了.
自左向右(按變量聲明順序)
那麼調用棧圖
自左向右入棧的調用棧
在只知道ebp的情況下,而不知道可變參數n的大小,不能確定可變參數和參數的分解,怎麼確定參數1,參數m的地址呢?不確定他們怎麼能訪問呢?真相就是這樣子,你無法確定各參數的地址。
如何實現自左向右入棧
使用另外的寄存器指向參數1。那麼就可以訪問固定參數,已經可變參數的區域也就確定了。
自右向左訪問參數超過範圍
以printf爲例:
printf("%d %d\n", 1);
這條語句輸出另個整數,但可變參數只給了一個整數1,那麼訪問第二個整數的時候必然也就“越界”了。
假設1的地址爲ptr,那麼會把(char *)ptr+sizeof(int),這個地址上的數據解析爲一個整數輸出。如果這個區域是它不能訪問的,還會造成非法訪問,如果可以訪問,數據也是錯誤的。