找回密码
 注册

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>* [; I+ `7 ^( h! d1 p8 E' J
<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>& D+ _! Z0 z6 [; `4 |* o! ?
<TBODY>
2 O( U- d, H* S" s$ k4 x<TR>
" ^  s% D9 j" N: s& ]# d* I<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; PADDING-TOP: 0cm">% X% P9 {' l" G
<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>
5 F  r8 ~, W2 F3 N9 n! o<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; PADDING-TOP: 0cm">
% a( P. t4 N, W+ ~4 c) q) s<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>
9 Y+ o/ x5 Y. i<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; PADDING-TOP: 0cm">
* x, P% a) S, d<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>
0 ~2 f( `6 |7 G/ T: e<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; PADDING-TOP: 0cm">+ E3 b; f7 y$ c, T1 H* F7 E
<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>& a! ?  U! W' L% K. ~
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; PADDING-TOP: 0cm">  a) g7 d" N2 B7 s/ [" b
<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>
1 u: O$ J% L& W# d<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; PADDING-TOP: 0cm">& [) W( d4 Q, X* W0 t
<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>( G1 n$ a) E+ ?- O& G" Z! s
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; PADDING-TOP: 0cm">, B8 A6 A4 u2 a- Q8 h, a; ?0 _
<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>, N8 a: m$ V6 p( d* Y
<TR>
1 Z" B( J3 O" b4 u  I<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; WIDTH: 28%; PADDING-TOP: 0cm" width="28%">" E4 A! i7 ^/ y7 l: k0 O1 Z
<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>: ]) e# x3 a+ n3 F
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
) n5 ?, G  \/ T* l* K  n5 q9 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>/ x/ Q1 [  i+ ?# K! E
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
5 O2 J( E' X3 v" ?6 l<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>
& Y1 ~1 C% E/ M' J<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
3 E- t, R+ T0 U  f+ y<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>1 H4 |& _; i% }/ r% p7 r) V$ o0 e
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">1 ?  \, b- y# b- Y, w) M
<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 L- O8 O$ l8 f5 O<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">7 p6 s% X( s3 z- c# C( z& 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>
- x5 N* P& C4 k; m& ]<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
! h2 x2 u. P8 [+ U  B3 m5 f, R<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>
& b  [6 j/ Q7 r<TR>
: s2 ^- C* V. h1 L3 e& K<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; WIDTH: 28%; PADDING-TOP: 0cm" width="28%">
, S7 U% [1 |8 P0 E/ c' `<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>$ b5 A4 C' c8 y" S! E5 {! W3 ~
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
: {+ W9 d7 j& v" @6 [+ p0 t<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>
) ?5 ]8 u+ x  D) G  E<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">! n+ R1 Q3 h/ r9 U% A" X5 Z6 ]. A) X
<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>
' x+ ~# |  Z$ Y<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
- Q  Q9 |' B2 `5 ~% x1 H7 a7 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>
1 ?; \0 Y/ ]6 [3 q' O<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">' P: v9 ^7 d7 X$ t# T1 g) u
<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>
1 J6 h& f4 b/ v<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">0 d2 U- v4 v5 f+ D1 c4 z. j
<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>6 S) P" |/ I6 c
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
+ W1 l/ f, P1 b/ Q1 J$ |<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>
# ^2 ~9 B5 @+ G( a2 z6 S4 d7 {<TR>
* N; V) E; M+ g* s<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; WIDTH: 28%; PADDING-TOP: 0cm" width="28%"># x5 ~9 c" O0 T4 y# C) E, l
<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>7 K. o* l  u" r6 r& l  E0 Z1 Z
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
7 z/ j' A8 X' J1 ?9 p3 ~<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>
/ Q- ^. U% U8 B. P: y' V9 a; ^<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">! ~; j  r! ~6 G- w2 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>
4 |9 ^8 W, [0 w# x<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
5 S4 |1 r, u& i" w1 f" h<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>/ y7 h- _  n3 l* w3 g2 ?
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
: ~, q: Y' p) @  Z7 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>
7 e1 j5 s9 X! [7 x<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
0 C1 _- H. n* Y7 Z" `6 {0 x* [( `<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>4 X7 s3 E3 G( c' k  y, a  e6 t/ o
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
6 a' B' H8 {+ [<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>/ Z) e4 N3 O' ]& f5 R$ D2 D
<TR>
5 K+ Q2 N# R& {* C! |; e3 ]$ g3 J<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; WIDTH: 28%; PADDING-TOP: 0cm" width="28%">
& D% J) m0 Q7 H+ q- A) z* Q<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>3 b- C% x8 D+ Z* [7 E) E' N% z
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">! S, [- V- C: I4 m5 j7 [
<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>
! T1 Q5 G6 j3 a; R- B+ b+ C5 d<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
+ h  C  r' [, A0 u  K+ ^, ?, h- U9 @& 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>
2 v# d4 f7 k1 @# S: r<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">2 `' ]# h6 a- ^
<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>
. C& Q3 D# X/ c9 P<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
8 ?" @& r  j1 Q, G<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 S5 |. M, K! d5 h* C
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
2 A1 {6 j5 o; ^1 ^4 Q/ T" X: M4 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>3 J9 G) U9 _( E* ~3 t# x" }6 o
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">; D! I$ x& b* h7 w2 ]& Z' b/ m
<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>  |8 l0 H) s' x2 E( b' Y
<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>
- ^# q3 b; z, k/ j& T( k<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>! V" C: G4 {* N7 ?
<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>6 b0 ?9 v2 M* N% }4 ]* Y
<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>
# a- I0 s( z& X% p9 f) E. h5 ^8 ~  T<P><SPAN lang=EN-US>&nbsp;<o:p></o:p></SPAN></P>- ]# v: c, z* |/ n5 {3 ]
<P><SPAN lang=EN-US>&nbsp;<o:p></o:p></SPAN></P>+ {# d% o$ O/ e# o3 t
<P><SPAN lang=EN-US>&nbsp;<o:p></o:p></SPAN></P>
; r7 c& I+ y3 R" A. V/ U) K<P><SPAN lang=EN-US>&nbsp;<o:p></o:p></SPAN></P>
+ t7 s+ r! g. B3 R0 ^3 W8 w<P><SPAN lang=EN-US>&nbsp;<o:p></o:p></SPAN></P>( R# }3 Q- b% I) F; v5 ]
<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>
0 S& }; S# C7 B) H<P>注意,这里的两个<SPAN lang=EN-US> local 变量实际上没有被用到,只是为了演示用,具体实现的代码是:<BR><BR>MyProc proc<BR><BR>push ebp<BR>mov ebp,esp<o:p></o:p></SPAN></P>: j' b1 D  w+ Y  c$ h) M" N/ u6 ^
<P><SPAN lang=EN-US>sub esp,8<o:p></o:p></SPAN></P>
( C( U* o( n4 ^. I<P><SPAN lang=EN-US>mov eax,dword ptr [ebp + 8]<BR>sub eax,dword ptr [ebp + c]<o:p></o:p></SPAN></P>6 s% o( L& X  w1 t5 J# ]
<P><SPAN lang=EN-US>add esp,8<o:p></o:p></SPAN></P>* s$ W, g: ^, E: D+ N: ~, o) B
<P><SPAN lang=EN-US>pop ebp<BR>ret 8<o:p></o:p></SPAN></P>
, `' m0 h+ s2 M$ c& }% S% O<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>
$ V( t; U0 w9 \& c7 a5 t) l6 L1 B1 y- Y<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>
9 V+ _2 l8 W& K' n<P>好了,说到这儿,参数传递的原理也应该将清楚了,还要最后说的是,在使用<SPAN lang=EN-US> Masm32 编 Win32 汇编程序的时候,我们并不需要记住 [ebp + xx] 等麻烦的地址,或自己计算局部变量需要预留的堆栈空间,还有在 ret 时计算要加上的数值,Masm32 的宏指令都已经把这些做好了,如在 Masm32 中,上面的程序只要写成为:<o:p></o:p></SPAN></P>  e4 g3 Q' t/ o3 L
<P><SPAN lang=EN-US>MyProc proc Var1,Var2<BR>local lVar1,lVar2<o:p></o:p></SPAN></P>$ B: M" c$ ~3 Y' t% ?
<P><SPAN lang=EN-US>mov eax,Var1<BR>sub eax,Var2<BR>ret<o:p></o:p></SPAN></P>
9 ?9 p6 g6 Q% g; Y<P><SPAN lang=EN-US>MyProc endp<o:p></o:p></SPAN></P>
- _( W* |% B/ q& a- m6 `. O& E! g<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>
+ X- Y8 U$ y8 g. ?" J5 u<P>最后是使用<SPAN lang=EN-US> Masm32 的 invoke 宏指令,在前面可以看到,调用带参数的子程序时,我们需要用 push 把参数压入堆栈,如果不小心把参数个数搞错了,就会使堆栈不平衡,从而使程序从堆栈中取出错误的返回地址引起不可预料的后果,所以有必要有一条语句来完成自动检验的任务,invoke 就是这样的语句,实际上,它是自动 push 所有参数,检测参数个数、类型是否正确,并使用 call 来调用的一个宏指令,对于上面的 push/push/call MyProc 的指令,可以用一条指令完成就是:<o:p></o:p></SPAN></P>4 _2 L6 H" ?8 A3 `, H# v4 @
<P><SPAN lang=EN-US>invoke MyProc,Var1,Var2<o:p></o:p></SPAN></P>
( k* ?8 U" I, `<P>当然,当程序编译好以后你去看机器码会发现它被正确地换成了同样的<SPAN lang=EN-US> push/push/call 指令。但是,在使用 invoke 之前,为了让它进行正确的参数检验,你需要对函数进行申明,就象在 C 中一样,申明的语句是:<o:p></o:p></SPAN></P>+ O& K7 J, W7 ], m) m# p  s( z
<P><SPAN lang=EN-US>MyProc proto :DWORD,:DWORD<o:p></o:p></SPAN></P>
4 F% f' q# C0 S- n<P>语句中<SPAN lang=EN-US> proto 是关键字,表示申明,:DWORD 表示参数的类型是 double word 类型的,有几个就表示有几个参数,在 Win32 中参数都是 double word 型的,申明语句要写在 invoke 之前,所以我们一般把它包括在 include 文件中,好了,综合一下,在 Masm32 中使用一个带参数的子程序或者 Api ,我们只需用:<o:p></o:p></SPAN></P>
( S7 U; J  I1 ]) f# n3 f' q<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-7-30 02:29

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

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