当前位置:首页 > 网络编程 > 软件语言 > 汇编 > 汇编中参数的传递和堆栈修正

汇编中参数的传递和堆栈修正

点击次数:42 次 发布日期:2008-11-10 08:14:18 作者:源代码网
源代码网推荐
广告载入中
汇编中参数的传递和堆栈修正:

源代码网整理以下  在 Win32汇编中,我们经常要和 Api 打交道,另外也会常常使用自己编制的类似于 Api 的带参数的子程序,本文要讲述的是在子程序调用的过程中进行参数传递的概念和分析。一般在程序中,参数的传递是通过堆栈进行的,也就是说,调用者把要传递给子程序(或者被调用者)的参数压入堆栈,子程序在堆栈取出相应的值再使用,比如说,如果你要调用 SubRouting(Var1,Var2,Var3),编译后的最终代码可能是 软件开发网 www.mscto.com

源代码网整理以下push Var3
源代码网推荐 push Var2
源代码网推荐 push Var1
源代码网推荐 call SubRouting
源代码网推荐 add esp,12

源代码网整理以下也就是说,调用者首先把参数压入堆栈,然后调用子程序,在完成后,由于堆栈中先前压入的数不再有用,调用者或者被调用者必须有一方把堆栈指针修正到调用前的状态。参数是最右边的先入堆栈还是最左边的先入堆栈、还有由调用者还是被调用者来修正堆栈都必须有个约定,不然就会产生不正确的结果,这就是我在前面使用“可能”这两个字的原因:各种语言中调用子程序的约定是不同的,它们的不同点见下表:

源代码网整理以下 C SysCall StdCall Basic Fortran Pascal
源代码网推荐 参数从左到右 是 是 是
源代码网推荐 参数从右到左 是 是 是
源代码网推荐 调用者清除堆栈 是
源代码网推荐 允许使用:VARARG 是 是 是

源代码网整理以下VARARG 表示参数的个数可以是不确定的,有一个例子就是 C 中的 printf 语句,在上表中,StdCall 的定义有个要说明的地方,就是如果 StdCall 使用 :VARARG 时,是由调用者清除堆栈的,而在没有:VARARG时是由被调用者清除堆栈的。
源代码网推荐 在 Win32 汇编中,约定使用 StdCall 方式,所以我们要在程序开始的时候使用 .model stdcall 语句。也就是说,在 API 或子程序中,最右边的参数先入堆栈,然后子程序在返回的时候负责校正堆栈,举例说明,如果我们要调用 MessageBox 这个 API,因为它的定义是 MessageBox(hWnd,lpText,lpCaption,UType) 所以在程序中要这样使用:

源代码网整理以下push MB_OK
源代码网推荐 push offset szCaption
源代码网推荐 push offset szText
源代码网推荐 push hWnd
源代码网推荐 call MessageBox
源代码网推荐 ... 软件开发网 www.mscto.com

源代码网整理以下我们不必在 API 返回的时候加上一句 add sp,4*4 来修正堆栈,因为这已经由 MessageBox 这个子程序做了。在 Windows API 中,唯一一个特殊的 API 是 wsprintf,这个 API 是 C 约定的,它的定义是 wsprintf(lpOut,lpFormat,Var1,Var2...),所以在使用时就要:

源代码网整理以下push 1111
源代码网推荐 push 2222
源代码网推荐 push 3333
源代码网推荐 push offset szFormat
源代码网推荐 push offset szOut
源代码网推荐 call wsprintf
源代码网推荐 add esp,4*5

源代码网整理以下下面要讲的是子程序如何存取参数,因为缺省对堆栈操作的寄存器有 ESP 和 EBP,而 ESP是堆栈指针,无法暂借使用,所以一般使用 EBP 来存取堆栈,假定在一个调用中有两个参数,而且在 push 第一个参数前的堆栈指针 ESP 为 X,那么压入两个参数后的 ESP 为 X-8,程序开始执行 call 指令,call 指令把返回地址压入堆栈,这时候 ESP 为 X-C,这时已经在子程序中了,我们可以开始使用 EBP 来存取参数了,但为了在返回时恢复 EBP 的值,我们还是再需要一句 push ebp 来先保存 EBP 的值,这时 ESP 为 X-10,再执行一句 mov ebp,esp,根据右图可以看出,实际上这时候 [ebp 8] 就是参数1,[ebp c]就是参数2。另外,局部变量也是定义在堆栈中的,它们的位置一般放在 push ebp 保存的 EBP 数值的后面,局部变量1、2对应的地址分别是 [ebp-4]、[ebp-8],下面是一个典型的子程序,可以完成第一个参数减去第二个参数,它的定义是:

源代码网整理以下MyProc proto Var1,Var2 ;有两个参数
源代码网推荐 local lVar1,lVar2 ;有两个局部变量

源代码网整理以下注意,这里的两个 local 变量实际上没有被用到,只是为了演示用,具体实现的代码是:


源代码网推荐

源代码网供稿.
网友评论 (0)
会员中心
网络编程
本站推荐
网络编程之精华