找回密码
 注册

QQ登录

只需一步,快速开始

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

[复制链接]
发表于 2008-9-28 16:22:28 | 显示全部楼层 |阅读模式
&nbsp;&nbsp;在 Win32汇编中,我们经常要和 Api 打交道,另外也会常常使用自己编制的类似于 Api 的带参数的子程序,本文要讲述的是在子程序调用的过程中进行参数传递的概念和分析。一般在程序中,参数的传递是通过堆栈进行的,也就是说,调用者把要传递给子程序(或者被调用者)的参数压入堆栈,子程序在堆栈取出相应的值再使用,比如说,如果你要调用 SubRouting(Var1,Var2,Var3),编译后的最终代码<SPAN style="COLOR: red">可能</SPAN>是<BR><BR>push Var3<BR>push Var2<BR>push Var1<BR>call SubRouting<BR>add esp,12<BR><BR>也就是说,调用者首先把参数压入堆栈,然后调用子程序,在完成后,由于堆栈中先前压入的数不再有用,调用者或者被调用者必须有一方把堆栈指针修正到调用前的状态。参数是最右边的先入堆栈还是最左边的先入堆栈、还有由调用者还是被调用者来修正堆栈都必须有个约定,不然就会产生不正确的结果,这就是我在前面使用“可能”这两个字的原因:各种语言中调用子程序的约定是不同的,它们的不同点见下表:<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p>
/ X/ r- ?$ J  H. a3 n<TABLE style="WIDTH: 581.25pt; mso-cellspacing: 0cm; mso-padding-alt: 0cm 0cm 0cm 0cm" cellSpacing=0 borderColorDark=#ffffff cellPadding=0 width=775 borderColorLight=#000000 border=1>+ |8 M" h! D) e" d8 K+ B$ v' B
<TBODY>2 G  b/ x7 m# z# o% G" \
<TR>( o! D! r5 J$ C  A
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; PADDING-TOP: 0cm">
$ L, w0 e& |( p7 x<P class=MsoNormal><SPAN lang=EN-US>&nbsp;</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><o:p></o:p></SPAN></P></TD>0 L6 |) w" u( U! j" m$ K: w
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; PADDING-TOP: 0cm">8 W* \! r$ }) p# n' k
<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US>C</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><o:p></o:p></SPAN></P></TD>
0 f. m* {# {  i3 K& _& V<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; PADDING-TOP: 0cm">& V5 }: o1 |  c- ?( }, k
<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US>SysCall</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><o:p></o:p></SPAN></P></TD>
4 ]. z/ O1 w) p3 S0 K, W8 q<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; PADDING-TOP: 0cm">9 g- [! |  h9 r9 U! z
<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US>StdCall</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><o:p></o:p></SPAN></P></TD>' T+ w2 G. l/ p! O1 R- l; X
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; PADDING-TOP: 0cm">( b6 x+ \9 x' M4 |
<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US>Basic</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><o:p></o:p></SPAN></P></TD>
; k$ a8 ?( P8 J$ t4 q4 Z2 X7 w5 l+ x% [- u<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; PADDING-TOP: 0cm">
: T! \$ N- L+ r<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US>Fortran</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><o:p></o:p></SPAN></P></TD>
  P: J8 {7 v+ G; F- y* m! ?) Z; A4 p<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; PADDING-TOP: 0cm">
6 u( p/ ~5 m1 z# g4 @<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US>Pascal</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><o:p></o:p></SPAN></P></TD></TR>1 E3 w  Q& [( W1 q7 w6 S+ w+ k* h6 ?9 @
<TR>' N; I; w2 p4 e8 ^3 r
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; WIDTH: 28%; PADDING-TOP: 0cm" width="28%">
; ]  f0 o3 V' O% L& _) E( o5 k<P class=MsoNormal><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">参数从左到右</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><o:p></o:p></SPAN></P></TD>$ a# t3 q+ i2 B9 \6 ]7 R# B$ R/ A
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
  ]+ F0 G0 J2 x0 i( q4 ]! e( Q6 P<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US>&nbsp;</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><o:p></o:p></SPAN></P></TD>/ w6 \. x# p8 L: Z* S) m
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">' N" U- ]. u8 u& e) q- _. d
<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US>&nbsp;</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><o:p></o:p></SPAN></P></TD>
  x* a4 o. a/ T, f<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
/ k( n, S: C# T" @2 Z$ G! P<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US>&nbsp;</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><o:p></o:p></SPAN></P></TD>
0 I# P5 Z5 ]$ y<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">- n% @; p0 |2 [) x1 ~; p# N  L9 l
<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><o:p></o:p></SPAN></P></TD>
: a' @1 M5 q, k' S8 S# O' G<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
! }, p9 [" Q: ~5 u9 N<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><o:p></o:p></SPAN></P></TD>
, S/ O8 e* ~2 }9 W9 ~+ F<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
/ L7 ?5 C# b: [) ^* h<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><o:p></o:p></SPAN></P></TD></TR>
" y) |# |8 J+ U7 x. h( Y! d<TR>
4 o# T; ^. r. Q* G' z: h<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; WIDTH: 28%; PADDING-TOP: 0cm" width="28%">+ N$ i4 d, O0 f# f' k
<P class=MsoNormal><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">参数从右到左</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><o:p></o:p></SPAN></P></TD>+ y) \# y) [3 Y) _8 M& n
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">* k  I: T, h: g% C" \: [
<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><o:p></o:p></SPAN></P></TD>
& S0 T& y  t) A8 S7 x1 x! n<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">- V! y: S7 k$ Q4 _# W
<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><o:p></o:p></SPAN></P></TD>* Q1 N" c, x4 Q* ^+ }
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">. {$ n7 V2 V" l, [
<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><o:p></o:p></SPAN></P></TD>9 Y; a. }( C! [+ K# V5 `7 \  f
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
" L, i+ w  g7 U* l3 c  a<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US>&nbsp;</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><o:p></o:p></SPAN></P></TD>0 q9 n- \) b2 O
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
; B& {- y* l5 O1 D+ _# y+ i<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US>&nbsp;</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><o:p></o:p></SPAN></P></TD>
8 ?% t4 I2 v& U; I  B0 _1 \. p<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">+ I; _( d  a# x/ e
<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US>&nbsp;</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><o:p></o:p></SPAN></P></TD></TR>
% x/ x3 x2 G9 o<TR>; [" ?0 p% A- @
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; WIDTH: 28%; PADDING-TOP: 0cm" width="28%">% p# ^$ |' \$ F/ D, Z0 x4 P
<P class=MsoNormal><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">调用者清除堆栈</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><o:p></o:p></SPAN></P></TD>4 E# a9 B) W# Z2 P  r/ A; w
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
- c) k3 b$ d  O& E2 P/ v; `$ R: |+ A0 k<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><o:p></o:p></SPAN></P></TD>
7 X/ F( a, T6 ~7 G1 V<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
0 [5 d- Y* _" O% I& d! g5 y! a3 N<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US>&nbsp;</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><o:p></o:p></SPAN></P></TD>8 q0 M2 _. |. |! w1 T' y
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">$ d' l( L: d! y- B
<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US>&nbsp;</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><o:p></o:p></SPAN></P></TD>0 g. E, {' X0 J. u  k
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">+ I( c) n: J" p/ n. I0 o3 s
<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US>&nbsp;</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><o:p></o:p></SPAN></P></TD>* F; L& t& D% D8 N$ F( P
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
, ~0 Q, n# z1 _8 ?' Z<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US>&nbsp;</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><o:p></o:p></SPAN></P></TD>! U3 A8 |/ c$ n
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
; h6 B4 S& B, {) B; E( ]<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US>&nbsp;</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><o:p></o:p></SPAN></P></TD></TR>
) {: k; \* q" K; p4 n1 A3 X8 v1 w<TR>; V0 N6 a0 g% }4 ?3 |& C# F
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; WIDTH: 28%; PADDING-TOP: 0cm" width="28%">  \' u2 |  @1 `7 B3 a) M% V
<P class=MsoNormal><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">允许使用</SPAN><SPAN lang=EN-US>:VARARG</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><o:p></o:p></SPAN></P></TD>; u5 }  X  l- W+ _
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">' I3 e: x* D( y
<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><o:p></o:p></SPAN></P></TD>
% z8 E9 p% c  A4 v<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
/ S% |0 F5 }; g4 B% `5 }<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><o:p></o:p></SPAN></P></TD>; J7 {' z; W7 F1 h
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
8 b  C! u7 y% k) _) V) C4 d<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><o:p></o:p></SPAN></P></TD>
3 ?  L- n  u! A. ]) `/ g* ]<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">0 T6 r5 F' |7 F0 x! g8 z1 r9 l0 V. N" \
<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US>&nbsp;</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><o:p></o:p></SPAN></P></TD>2 z7 v' s% P) H. H+ I6 l6 r; D* ?
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">0 M, Z! _; d( T9 w3 v: c9 i
<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US>&nbsp;</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><o:p></o:p></SPAN></P></TD>
( I+ K# O/ i$ v5 N! j( O. I4 k<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">, E; j  h$ N$ W% U" p: I- v/ {
<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US>&nbsp;</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><o:p></o:p></SPAN></P></TD></TR></TBODY></TABLE>  n* H# b$ l# C% x' F
<P><SPAN lang=EN-US>VARARG 表示参数的个数可以是不确定的,有一个例子就是 C 中的 printf 语句,在上表中,StdCall 的定义有个要说明的地方,就是如果 StdCall 使用 :VARARG 时,是由调用者清除堆栈的,而在没有:VARARG时是由被调用者清除堆栈的。<BR>在 Win32 汇编中,约定使用 StdCall 方式,所以我们要在程序开始的时候使用 .model stdcall 语句。也就是说,在 API 或子程序中,最右边的参数先入堆栈,然后子程序在返回的时候负责校正堆栈,举例说明,如果我们要调用 MessageBox 这个 API,因为它的定义是 MessageBox(hWnd,lpText,lpCaption,UType) 所以在程序中要这样使用:<o:p></o:p></SPAN></P>, O) \8 h1 Q$ d5 A
<P><SPAN lang=EN-US>push MB_OK<BR>push offset szCaption<BR>push offset szText<BR>push hWnd<BR>call MessageBox<BR>...<o:p></o:p></SPAN></P>$ ^* x, [, ~! C
<P>我们不必在<SPAN lang=EN-US> API 返回的时候加上一句 add sp,4*4 来修正堆栈,因为这已经由 MessageBox 这个子程序做了。在 Windows API 中,唯一一个特殊的 API 是 wsprintf,这个 API 是 C 约定的,它的定义是 wsprintf(lpOut,lpFormat,Var1,Var2...),所以在使用时就要:<o:p></o:p></SPAN></P>4 L% K6 X* p: Q$ i5 k
<P><SPAN lang=EN-US>push 1111<BR>push 2222<BR>push 3333<BR>push offset szFormat<BR>push offset szOut<BR>call wsprintf<BR>add esp,4*5</SPAN></P>2 `! Z+ A( c; b
<P><SPAN lang=EN-US>&nbsp;<o:p></o:p></SPAN></P>' v0 B; }1 P. d2 t, L
<P><SPAN lang=EN-US>&nbsp;<o:p></o:p></SPAN></P>+ i" @2 d) d3 w5 F
<P><SPAN lang=EN-US>&nbsp;<o:p></o:p></SPAN></P>1 W4 r2 F1 l1 D/ t; _6 n8 ]3 T0 y
<P><SPAN lang=EN-US>&nbsp;<o:p></o:p></SPAN></P>
: Y' h7 Q4 ?. }( ]) \& d<P><SPAN lang=EN-US>&nbsp;<o:p></o:p></SPAN></P>
: p* {  t3 `5 Q: P& r! L<P><?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /><v:shapetype id=_x0000_t75 stroked="f" filled="f" path=" m@4@5 l@4@11@9@11@9@5 xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600"><v:stroke joinstyle="miter"></v:stroke><v:formulas><v:f eqn="if lineDrawn pixelLineWidth 0 "></v:f><v:f eqn="sum @0 1 0 "></v:f><v:f eqn="sum 0 0 @1 "></v:f><v:f eqn="prod @2 1 2 "></v:f><v:f eqn="prod @3 21600 pixelWidth "></v:f><v:f eqn="prod @3 21600 pixelHeight "></v:f><v:f eqn="sum @0 0 1 "></v:f><v:f eqn="prod @6 1 2 "></v:f><v:f eqn="prod @7 21600 pixelWidth "></v:f><v:f eqn="sum @8 21600 0 "></v:f><v:f eqn="prod @7 21600 pixelHeight "></v:f><v:f eqn="sum @10 21600 0 "></v:f></v:formulas><v:path o:connecttype="rect" gradientshapeok="t" o:extrusionok="f"></v:path><o:lock aspectratio="t" v:ext="edit"></o:lock></v:shapetype><v:shape id=_x0000_s1026 style="MARGIN-TOP: 0px; Z-INDEX: 1; MARGIN-LEFT: 130.25pt; WIDTH: 170.25pt; POSITION: absolute; HEIGHT: 180pt; mso-wrap-distance-left: 3.75pt; mso-wrap-distance-top: 3.75pt; mso-wrap-distance-right: 3.75pt; mso-wrap-distance-bottom: 3.75pt; mso-position-horizontal: right; mso-position-horizontal-relative: text; mso-position-vertical-relative: line" alt="" coordsize="21600,21600" type="#_x0000_t75" o:allowoverlap="f"><?xml:namespace prefix = w ns = "urn:schemas-microsoft-com:office:word" /><w:wrap type="square"></w:wrap></v:shape>下面要讲的是子程序如何存取参数,因为缺省对堆栈操作的寄存器有<SPAN lang=EN-US> 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],下面是一个典型的子程序,可以完成第一个参数减去第二个参数,它的定义是:<BR><BR>MyProc proto Var1,Var2 ;有两个参数<BR>local lVar1,lVar2 ;有两个局部变量<o:p></o:p></SPAN></P>
; K$ e$ e7 Y7 |% l/ y8 ?1 B- ?<P>注意,这里的两个<SPAN lang=EN-US> local 变量实际上没有被用到,只是为了演示用,具体实现的代码是:<BR><BR>MyProc proc<BR><BR>push ebp<BR>mov ebp,esp<o:p></o:p></SPAN></P>0 I9 d9 U" E0 r9 [4 D# f' e
<P><SPAN lang=EN-US>sub esp,8<o:p></o:p></SPAN></P>
: \$ J4 H$ p6 W1 h<P><SPAN lang=EN-US>mov eax,dword ptr [ebp + 8]<BR>sub eax,dword ptr [ebp + c]<o:p></o:p></SPAN></P>
5 U7 }3 [+ q/ c- E) {, T( L4 w) x4 q# b<P><SPAN lang=EN-US>add esp,8<o:p></o:p></SPAN></P>
9 H0 A; n' W0 r<P><SPAN lang=EN-US>pop ebp<BR>ret 8<o:p></o:p></SPAN></P>, a0 A1 ^2 \8 J# S5 `# e
<P><SPAN lang=EN-US>MyProc endp<BR><BR>现在对这个子程序分析一下,push ebp/mov ebp,esp 是例行的保存和设置 EBP 的代码,sub esp,8 在堆栈中留出两个局部变量的空间,mov /add 语句完成相加,add esp,8 修正两个局部变量使用的堆栈,ret 8 修正两个参数使用的堆栈,相当于 ret / add esp,8 两句代码的效果。可以看出,这是一个标准的 Stdcall 约定的子程序,使用时最后一个参数先入堆栈,返回时由子程序进行堆栈修正。当然,这个子程序为了演示执行过程,使用了手工保存 ebp 并设置局部变量的方法,实际上,386 处理器有两条专用的指令是完成这个功能用的,那就是 Enter 和 Leave,Enter 语句的作用就是 push ebp/mov ebp,esp/sub esp,xxx,这个 xxx 就是 Enter 的,Leave 则完成 add esp,xxx/pop ebp 的功能,所以上面的程序可以改成:<o:p></o:p></SPAN></P>
( d1 e% w! k0 v& b- Y( C6 h3 E6 {<P><SPAN lang=EN-US>MyPorc proc<BR>enter 8,0<BR><BR>mov eax,dword ptr [ebp + 8]<BR>sub eax,dword ptr [ebp + c]<BR><BR>leave<BR>ret 8<BR>MyProc endp<o:p></o:p></SPAN></P>
! T5 v8 u8 h1 p0 q6 E& G4 d<P>好了,说到这儿,参数传递的原理也应该将清楚了,还要最后说的是,在使用<SPAN lang=EN-US> Masm32 编 Win32 汇编程序的时候,我们并不需要记住 [ebp + xx] 等麻烦的地址,或自己计算局部变量需要预留的堆栈空间,还有在 ret 时计算要加上的数值,Masm32 的宏指令都已经把这些做好了,如在 Masm32 中,上面的程序只要写成为:<o:p></o:p></SPAN></P>
' K3 S1 v) x* V<P><SPAN lang=EN-US>MyProc proc Var1,Var2<BR>local lVar1,lVar2<o:p></o:p></SPAN></P>& M* L% J/ j1 Y' r- t( R1 I4 G
<P><SPAN lang=EN-US>mov eax,Var1<BR>sub eax,Var2<BR>ret<o:p></o:p></SPAN></P>; {# D' h6 K8 \# P
<P><SPAN lang=EN-US>MyProc endp<o:p></o:p></SPAN></P>
2 ~% I+ L& V% y5 \<P>编译器会自动的在<SPAN lang=EN-US> mov eax,Var1 前面插上一句 Enter 语句,它的参数会根据 local 定义的局部变量的多少自动指定,在 ret 前会自动加上一句 Leave,同样,编译器会根据参数的多少把 ret 替换成 ret xxx,把 mov eax,Var1 换成 mov eax,dword ptr [ebp + 8] 等等。<o:p></o:p></SPAN></P>, j* t: L. L  B1 _, [
<P>最后是使用<SPAN lang=EN-US> Masm32 的 invoke 宏指令,在前面可以看到,调用带参数的子程序时,我们需要用 push 把参数压入堆栈,如果不小心把参数个数搞错了,就会使堆栈不平衡,从而使程序从堆栈中取出错误的返回地址引起不可预料的后果,所以有必要有一条语句来完成自动检验的任务,invoke 就是这样的语句,实际上,它是自动 push 所有参数,检测参数个数、类型是否正确,并使用 call 来调用的一个宏指令,对于上面的 push/push/call MyProc 的指令,可以用一条指令完成就是:<o:p></o:p></SPAN></P>8 b$ p/ Y, b% u  g& W
<P><SPAN lang=EN-US>invoke MyProc,Var1,Var2<o:p></o:p></SPAN></P>
* L2 m. F5 _% I1 V. p) @<P>当然,当程序编译好以后你去看机器码会发现它被正确地换成了同样的<SPAN lang=EN-US> push/push/call 指令。但是,在使用 invoke 之前,为了让它进行正确的参数检验,你需要对函数进行申明,就象在 C 中一样,申明的语句是:<o:p></o:p></SPAN></P>6 R( A" q- _3 c# v
<P><SPAN lang=EN-US>MyProc proto :DWORD,:DWORD<o:p></o:p></SPAN></P>
6 ~. v0 u% S( S<P>语句中<SPAN lang=EN-US> proto 是关键字,表示申明,:DWORD 表示参数的类型是 double word 类型的,有几个就表示有几个参数,在 Win32 中参数都是 double word 型的,申明语句要写在 invoke 之前,所以我们一般把它包括在 include 文件中,好了,综合一下,在 Masm32 中使用一个带参数的子程序或者 Api ,我们只需用:<o:p></o:p></SPAN></P>
+ i0 \% ?* |  k% @<P><SPAN lang=EN-US>...<BR>MyProc proto :dword,:dword<BR>... <BR>.data<BR>x dd ?<BR>y dd ?<BR>dwResult dd ?<BR>...<BR>mov x,1<BR>mov y,2<BR>invoke MyProc x,y<BR>mov dwResult,eax<BR>... <o:p></o:p></SPAN></P>
您需要登录后才可以回帖 登录 | 注册

本版积分规则

QQ|本地广告联系: QQ:905790666 TEL:13176190456|Archiver|手机版|小黑屋|汶上信息港 ( 鲁ICP备19052200号-1 )

GMT+8, 2026-4-30 20:13

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表