欧美一区二区三区,国内熟女精品熟女A片视频小说,日本av网,小鲜肉男男GAY做受XXX网站

如果一個函數需要傳遞大量的參數,顯然寄存器是不夠用的,應該如何解決?

林雅南2年前12瀏覽0評論

我們無論學習什么語言,都離不開函數、參數、參數傳遞、函數調用、返回值等這幾個步驟。

我們在編寫一個匯編函數時,用寄存器傳參的方式,要提前約定好參與函數功能的寄存器,將參數存入函數約定好的寄存器中,在進行運算。

那么問題來了,我們知道的寄存器也就那么幾十個,如果一個函數需要傳遞大量的參數,顯然寄存器是不夠用的,就需要用到堆棧傳參的方式去解決。

【堆棧傳參的方式】

堆棧傳參看到這幾個字肯定能想到將參數保存在堆棧中。那我們該怎么用哪?同樣用例題介紹堆棧傳參的方式。

例:編寫一個函數,實現任意五個整數相加。

分析:需要將5個參數保存到堆棧中,用CALL指令調用函數。

第一步:在DTDebug.exe軟件中打開飛鴿軟件,如圖2-13-1所示。

第二步:將5個整數壓入堆棧,輸入以下指令,如圖2-13-2所示。

PUSH1

PUSH2

PUSH3

PUSH4

PUSH5

第三步:依次按F8將參數壓入堆棧中,如圖2-13-3所示。

按F8執行完看到,堆棧中已經壓入我們傳遞的參數。用CALL調用函數,我們怎么編寫這個函數哪?

我們的常用指令不允許兩邊都為內存,所以我們通過ESP棧頂指針來運算。

如果這么寫:MOVEAX,DWORDPTRDS:[ESP],那么EAX里的值是什么?

我們編寫完參數后,調用CALL,會將CALL下一行的指令地址傳入堆棧,這個時候ESP的值就是CALL函數地址,堆棧的變化如圖2-13-4:

圖2-13-4堆棧圖

第三步:編寫函數,輸入以下指令,如圖2-13-5所示。

這5個參數依次是:ESP+0x14、ESP+0x10、ESP+0xC、ESP+0x8、ESP+0x4

所以我們的函數可以這樣編寫:

MOVEAX,DWORDPTRDS:[ESP+0x14]

ADDEAX,DWORDPTRDS:[ESP+0x10]

ADDEAX,DWORDPTRDS:[ESP+0xC]

ADDEAX,DWORDPTRDS:[ESP+0x8]

ADDEAX,DWORDPTRDS:[ESP+0x4]

RETN

第四步:使用CALL調用函數,輸入CALL0x77068E4D,如圖2-13-6所示。

第五步:按F7觀察堆棧窗口數據變化,如圖2-13-7所示。

圖2-13-7中,執行完CALL指令,并將CALL指令下一行地址壓入堆棧中,當前黑色定位光標在函數體開始的地址,當前ESP是0x0019FFD8,堆棧窗口中的內存使用是從高地址向低地址使用的,所以ESP+14是參數的開始。我們可以雙擊堆棧窗口中的內存地址,如圖2-13-8所示。

第六步:把EAX寄存器的數據變為0x00000000,依次按F8,查看結果是否正確,如圖2-13-9所示。

1+2+3+4+5=15,轉化成16進制為F。看圖2-13-9中,EAX寄存器的值為0x00000000F,說明運算結果正確,證明我們編寫的函數是正確的。

第七步:按F8執行RETN指令,如圖2-13-10所示。

以上是堆棧傳參的過程,總結:堆棧傳參是將參數壓入堆棧中,函數在運算時通過ESP尋址的方式去查找對應的參數并進行運算。

思考:函數執行完了,可是我們的數據還保存在堆棧中,該怎么解決呢?