交換兩個內存變量相信大家都不陌生,核心的代碼就是:
;交換[esi],[edi]兩個內存變量
mov eax, [esi]
xchg eax, [edi]
mov [esi],eax
然而現在我們要通過用匯編編寫一段子程序來調用這個子程序來實現交換兩個數,我們定義主函數給子函數傳遞的參數是以地址的形式(指針),傳遞需要交換的兩個內存變量。
源程序如下:
;功能:使用子程序交換兩個內存變量
;作者:王文堃
;創建時間:2016/4/20
INCLUDE vcIO.inc
.data
num1 DWORD 1234
num2 DWORD 5678
str_output BYTE "num1 = %d, num2 = %d",0ah,0
.code
;主程序
main PROC
push offset num1
push offset num2
call swap
invoke printf, offset str_output, num1, num2
ret
main ENDP
;子程序
swap PROC
push ebp
mov ebp, esp
pushad
;body of swap
;[ebp+4] is return addr,[ebp+8] is the first argument,[ebp+12] is the sec agru
mov esi, [ebp+8]
mov edi, [ebp+12]
;swap [esi],[edi]
mov eax, [esi]
xchg eax, [edi]
mov [esi], eax
popad
pop ebp
ret 2*4 ;2 is the num of arguments, 4 is the size of argument
swap ENDP
END main
主程序中
push offset num1 ;將參數進棧
push offset num2 ;將第二個參數進棧
call swap ;調用子函數,有兩個動作,第一個是將下一條指令的地址入棧,第二個動作是轉到子程序,即將eip修改爲子程序的地址
子程序中
子程序一進來就有push ebp 和mov ebp, esp兩句
這裏是剛開始接觸子程序調用的難點,爲什麼不直接使用esp而還要賦給ebp使用ebp呢?
因爲esp的位置會隨着程序pop,push而動態改變
我們後面要訪問第一個參數本來是在[esp+8],但因爲pushad後esp改變了,第一個參數也就不再是[esp+8]
所有我們一進來就將esp保存在ebp中,之後第一個參數就可以通過[ebp+8]訪問需要說明的是通過ebp訪問參數的時候:
[ebp+4]是子程序要返回給主函數的地址
[ebp+8]是第一個參數
[ebp+12]是第二個參數ret 2*4這一句是說明將兩個參數彈出棧不要了,因爲棧中每個數據戰4個字節,所以*4