交换两个内存变量相信大家都不陌生,核心的代码就是:
;交换[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