在 Win32匯編中,我們經(jīng)常要和 Api 打交道,另外也會常常使用自己編制的類似于 Api 的帶參數(shù)的子程序,本文要講述的是在子程序調(diào)用的過程中進行參數(shù)傳遞的概念和分析。一般在程序中,參數(shù)的傳遞是通過堆棧進行的,也就是說,調(diào)用者把要傳遞給子程序(或者被調(diào)用者)的參數(shù)壓入堆棧,子程序在堆棧取出相應(yīng)的值再使用,比如說,如果你要調(diào)用 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>也就是說,調(diào)用者首先把參數(shù)壓入堆棧,然后調(diào)用子程序,在完成后,由于堆棧中先前壓入的數(shù)不再有用,調(diào)用者或者被調(diào)用者必須有一方把堆棧指針修正到調(diào)用前的狀態(tài)。參數(shù)是最右邊的先入堆棧還是最左邊的先入堆棧、還有由調(diào)用者還是被調(diào)用者來修正堆棧都必須有個約定,不然就會產(chǎn)生不正確的結(jié)果,這就是我在前面使用“可能”這兩個字的原因:各種語言中調(diào)用子程序的約定是不同的,它們的不同點見下表:<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p>, v) j( p- i! I. h% i
<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>3 b- I7 [& W) d6 p
<TBODY>/ X; a; t o _4 R. L4 d
<TR>% [9 G8 i: u$ a6 A1 }& _' @
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; PADDING-TOP: 0cm">8 V% s2 D& S! f5 \& j. w
<P class=MsoNormal><SPAN lang=EN-US> </SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋體"><o:p></o:p></SPAN></P></TD>0 L |* H1 x. f5 n+ ~) C
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; PADDING-TOP: 0cm">7 x( E0 _+ ~2 m+ |! 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>
3 s% S$ A( H! s2 V+ V5 K$ D<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; PADDING-TOP: 0cm">
8 E8 i9 s9 J+ y% C7 U! \<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>
3 s. k7 F! ~6 r1 h) t9 A- j& o<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; PADDING-TOP: 0cm">' K- @9 p# P( V9 u4 I& Q
<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>. s& b- V8 w5 D9 d; S4 F" ]
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; PADDING-TOP: 0cm">0 o7 H1 ^# F. X# V% {
<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>
. h6 Q! l: k J% d2 @<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; PADDING-TOP: 0cm">& f; F* W# x2 Y& w# O2 n! A2 X9 f
<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>
! p2 F& o8 ~# x5 K9 L: I* H0 F<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; PADDING-TOP: 0cm">3 W0 E R7 K" [1 N' F- r6 I, j8 q
<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>% |# C6 e2 f& _; Z5 J' ^/ ^
<TR>3 b2 a! k3 n: A% l' Z
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; WIDTH: 28%; PADDING-TOP: 0cm" width="28%">* K* }1 q/ U3 W0 w" s; K( g
<P class=MsoNormal><SPAN style="FONT-FAMILY: 宋體; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">參數(shù)從左到右</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋體"><o:p></o:p></SPAN></P></TD>; u% f5 B1 m2 T( D% [; j
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
7 I9 [% w5 i1 i- m" i<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US> </SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋體"><o:p></o:p></SPAN></P></TD>7 i- v& s O4 ]2 l
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">9 [5 S3 a0 j; M4 ]8 H' R
<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US> </SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋體"><o:p></o:p></SPAN></P></TD>
0 l2 K5 t; L! a4 Q/ W) V; b<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
4 n( V R' \* V+ v) R<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US> </SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋體"><o:p></o:p></SPAN></P></TD>- V& I! O: Y7 n! ?1 h3 {
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
' p. B' X8 E# 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>, b1 ~* E7 v4 W$ E( K* l3 W
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
6 x+ K( }& l. R) w: P( K" 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>
4 ?. g% H9 e/ \<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
1 |8 _: L( d9 [7 K0 ?<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>( M+ g3 A6 L/ r- O1 I6 W
<TR>
8 G4 l0 a$ E( G6 G/ |# c<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; WIDTH: 28%; PADDING-TOP: 0cm" width="28%">7 F" K0 ]( J3 y3 G
<P class=MsoNormal><SPAN style="FONT-FAMILY: 宋體; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">參數(shù)從右到左</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋體"><o:p></o:p></SPAN></P></TD>
4 U- H- ]7 E: G8 j, `2 `7 U: t; q<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">, r2 D" Q: p# Z7 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>
- u) H0 r! b" p; G% K7 b0 ~<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%"># ~/ r* X+ b8 W% n b$ ^& V
<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>
j( G. {" M5 @3 a2 I<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
* r' h3 B a4 C4 I<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( ?5 \/ v. h. E$ H0 K6 c4 o- I
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
( n! }/ P0 y! |# M" q8 z<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US> </SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋體"><o:p></o:p></SPAN></P></TD>
5 q6 F4 d. K: {9 Y<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
( K. p0 i) h/ W! }1 W; X<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US> </SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋體"><o:p></o:p></SPAN></P></TD>+ C, j$ _% B: M+ { s/ g, b
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
) g% [6 z( d' s, v- U& n) o8 A( Y0 n<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US> </SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋體"><o:p></o:p></SPAN></P></TD></TR>
+ l: S& Q3 A% _1 N<TR>9 E. P, [% T3 B" D9 }
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; WIDTH: 28%; PADDING-TOP: 0cm" width="28%">& O% w' p* j4 |4 O, k
<P class=MsoNormal><SPAN style="FONT-FAMILY: 宋體; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">調(diào)用者清除堆棧</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋體"><o:p></o:p></SPAN></P></TD>
* O0 _1 `5 ?. D6 c5 Q% y/ N& k<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">; b/ \) |3 L6 r- }- r% V 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>
2 H: s8 G2 M b* \<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">5 _$ ?2 A. K0 ]2 \
<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US> </SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋體"><o:p></o:p></SPAN></P></TD>2 A; W5 T( o4 p4 L( m) p
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">1 B$ e G, L$ i$ G" k4 E
<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US> </SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋體"><o:p></o:p></SPAN></P></TD>
$ i1 z& c4 Y% v' ~0 [. ^3 L<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">3 Q- I5 H* S5 B
<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US> </SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋體"><o:p></o:p></SPAN></P></TD>( s+ X% S9 p' l6 {
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">0 j5 a# Y2 _" m% C7 d7 Q
<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US> </SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋體"><o:p></o:p></SPAN></P></TD>
/ x% m$ J' }- q1 v+ S2 n4 B# _<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%"> n3 A- W! ~: h# p
<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US> </SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋體"><o:p></o:p></SPAN></P></TD></TR>1 o; \5 @+ ^( X# v( _$ i" R; {$ Z
<TR>0 V( A% e5 M' t# a3 u4 l
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; WIDTH: 28%; PADDING-TOP: 0cm" width="28%">3 W$ R2 q: T( k ?( G; z) Y4 p/ 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>, ~: I- p/ e: r5 Y _0 p9 F
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">! F4 G' q* O7 |6 u; f& ?
<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>
- w, K$ T+ w# b g1 {, @<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
4 D4 R" P# z$ g5 O! }<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>: A0 L; Z! l0 q4 g N# b
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
/ a# I O% v6 j<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> d, m2 P7 W2 T$ i5 T+ E
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">7 G, K% o* q* b1 J v! W- n4 G0 U
<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US> </SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋體"><o:p></o:p></SPAN></P></TD>
$ L% _$ j1 {! w7 K) o<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">! K5 S s! A; P8 t0 f& ~
<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US> </SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋體"><o:p></o:p></SPAN></P></TD>
1 H) n3 u, u+ I% @. q1 x3 @3 L<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
7 n% h6 e# X3 V4 J A<P class=MsoNormal style="TEXT-ALIGN: center" align=center><SPAN lang=EN-US> </SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋體"><o:p></o:p></SPAN></P></TD></TR></TBODY></TABLE>5 S$ P9 t0 M. ~, g" l6 }/ t: {; q
<P><SPAN lang=EN-US>VARARG 表示參數(shù)的個數(shù)可以是不確定的,有一個例子就是 C 中的 printf 語句,在上表中,StdCall 的定義有個要說明的地方,就是如果 StdCall 使用 :VARARG 時,是由調(diào)用者清除堆棧的,而在沒有:VARARG時是由被調(diào)用者清除堆棧的。<BR>在 Win32 匯編中,約定使用 StdCall 方式,所以我們要在程序開始的時候使用 .model stdcall 語句。也就是說,在 API 或子程序中,最右邊的參數(shù)先入堆棧,然后子程序在返回的時候負責校正堆棧,舉例說明,如果我們要調(diào)用 MessageBox 這個 API,因為它的定義是 MessageBox(hWnd,lpText,lpCaption,UType) 所以在程序中要這樣使用:<o:p></o:p></SPAN></P>6 h% r/ \2 @4 d& l: ?. q
<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>
2 K, Z" S% u9 i+ f, R7 ?<P>我們不必在<SPAN lang=EN-US> API 返回的時候加上一句 add sp,4*4 來修正堆棧,因為這已經(jīng)由 MessageBox 這個子程序做了。在 Windows API 中,唯一一個特殊的 API 是 wsprintf,這個 API 是 C 約定的,它的定義是 wsprintf(lpOut,lpFormat,Var1,Var2...),所以在使用時就要:<o:p></o:p></SPAN></P>. I) Y( C: N% J! p9 J- P. 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>. J! H; g; s" Y) b5 y8 f, _# ?
<P><SPAN lang=EN-US> <o:p></o:p></SPAN></P>
) V4 N; n* x+ p `! e<P><SPAN lang=EN-US> <o:p></o:p></SPAN></P>- Z& i% e% J5 H8 }( M" y* j
<P><SPAN lang=EN-US> <o:p></o:p></SPAN></P>! c4 P$ Z7 w" Q3 Q5 }. [3 K# l
<P><SPAN lang=EN-US> <o:p></o:p></SPAN></P>1 o8 x6 I0 S7 H! s" B% \
<P><SPAN lang=EN-US> <o:p></o:p></SPAN></P>2 Z, j* @& O9 h& @& b
<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>下面要講的是子程序如何存取參數(shù),因為缺省對堆棧操作的寄存器有<SPAN lang=EN-US> ESP 和 EBP,而 ESP是堆棧指針,無法暫借使用,所以一般使用 EBP 來存取堆棧,假定在一個調(diào)用中有兩個參數(shù),而且在 push 第一個參數(shù)前的堆棧指針 ESP 為 X,那么壓入兩個參數(shù)后的 ESP 為 X-8,程序開始執(zhí)行 call 指令,call 指令把返回地址壓入堆棧,這時候 ESP 為 X-C,這時已經(jīng)在子程序中了,我們可以開始使用 EBP 來存取參數(shù)了,但為了在返回時恢復 EBP 的值,我們還是再需要一句 push ebp 來先保存 EBP 的值,這時 ESP 為 X-10,再執(zhí)行一句 mov ebp,esp,根據(jù)右圖可以看出,實際上這時候 [ebp + 8] 就是參數(shù)1,[ebp + c]就是參數(shù)2。另外,局部變量也是定義在堆棧中的,它們的位置一般放在 push ebp 保存的 EBP 數(shù)值的后面,局部變量1、2對應(yīng)的地址分別是 [ebp-4]、[ebp-8],下面是一個典型的子程序,可以完成第一個參數(shù)減去第二個參數(shù),它的定義是:<BR><BR>MyProc proto Var1,Var2 ;有兩個參數(shù)<BR>local lVar1,lVar2 ;有兩個局部變量<o:p></o:p></SPAN></P>
( T8 z& u5 H) ]" X<P>注意,這里的兩個<SPAN lang=EN-US> local 變量實際上沒有被用到,只是為了演示用,具體實現(xiàn)的代碼是:<BR><BR>MyProc proc<BR><BR>push ebp<BR>mov ebp,esp<o:p></o:p></SPAN></P>
( \% T! P4 O, J1 e; I% k B<P><SPAN lang=EN-US>sub esp,8<o:p></o:p></SPAN></P>
# w* |2 l2 r' |5 W* n- ?; y" ?<P><SPAN lang=EN-US>mov eax,dword ptr [ebp + 8]<BR>sub eax,dword ptr [ebp + c]<o:p></o:p></SPAN></P>
4 O5 `( D! d* D3 w4 \7 y<P><SPAN lang=EN-US>add esp,8<o:p></o:p></SPAN></P>
) W9 @3 N$ t$ x0 s" i<P><SPAN lang=EN-US>pop ebp<BR>ret 8<o:p></o:p></SPAN></P>- z" h, G: R* e3 y" S/ v
<P><SPAN lang=EN-US>MyProc endp<BR><BR>現(xiàn)在對這個子程序分析一下,push ebp/mov ebp,esp 是例行的保存和設(shè)置 EBP 的代碼,sub esp,8 在堆棧中留出兩個局部變量的空間,mov /add 語句完成相加,add esp,8 修正兩個局部變量使用的堆棧,ret 8 修正兩個參數(shù)使用的堆棧,相當于 ret / add esp,8 兩句代碼的效果??梢钥闯?,這是一個標準的 Stdcall 約定的子程序,使用時最后一個參數(shù)先入堆棧,返回時由子程序進行堆棧修正。當然,這個子程序為了演示執(zhí)行過程,使用了手工保存 ebp 并設(shè)置局部變量的方法,實際上,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>
4 \! g6 I. @1 d% u* M<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>
, K# ^( `, f* N" Y9 ]. @4 q. z<P>好了,說到這兒,參數(shù)傳遞的原理也應(yīng)該將清楚了,還要最后說的是,在使用<SPAN lang=EN-US> Masm32 編 Win32 匯編程序的時候,我們并不需要記住 [ebp + xx] 等麻煩的地址,或自己計算局部變量需要預留的堆??臻g,還有在 ret 時計算要加上的數(shù)值,Masm32 的宏指令都已經(jīng)把這些做好了,如在 Masm32 中,上面的程序只要寫成為:<o:p></o:p></SPAN></P>
, ~ p! L7 s9 g+ r4 Q0 W<P><SPAN lang=EN-US>MyProc proc Var1,Var2<BR>local lVar1,lVar2<o:p></o:p></SPAN></P>6 U: E7 `- z! u/ ~& ]
<P><SPAN lang=EN-US>mov eax,Var1<BR>sub eax,Var2<BR>ret<o:p></o:p></SPAN></P>
& A& [) ?; S5 T j, N1 L<P><SPAN lang=EN-US>MyProc endp<o:p></o:p></SPAN></P>! Z. \3 ]9 F, {/ x
<P>編譯器會自動的在<SPAN lang=EN-US> mov eax,Var1 前面插上一句 Enter 語句,它的參數(shù)會根據(jù) local 定義的局部變量的多少自動指定,在 ret 前會自動加上一句 Leave,同樣,編譯器會根據(jù)參數(shù)的多少把 ret 替換成 ret xxx,把 mov eax,Var1 換成 mov eax,dword ptr [ebp + 8] 等等。<o:p></o:p></SPAN></P>6 t# P" ~* [( p h
<P>最后是使用<SPAN lang=EN-US> Masm32 的 invoke 宏指令,在前面可以看到,調(diào)用帶參數(shù)的子程序時,我們需要用 push 把參數(shù)壓入堆棧,如果不小心把參數(shù)個數(shù)搞錯了,就會使堆棧不平衡,從而使程序從堆棧中取出錯誤的返回地址引起不可預料的后果,所以有必要有一條語句來完成自動檢驗的任務(wù),invoke 就是這樣的語句,實際上,它是自動 push 所有參數(shù),檢測參數(shù)個數(shù)、類型是否正確,并使用 call 來調(diào)用的一個宏指令,對于上面的 push/push/call MyProc 的指令,可以用一條指令完成就是:<o:p></o:p></SPAN></P>
8 }" ]9 D' ?0 F" A* Y0 z<P><SPAN lang=EN-US>invoke MyProc,Var1,Var2<o:p></o:p></SPAN></P>
2 {7 Q4 |) E: g) J, r5 `" }<P>當然,當程序編譯好以后你去看機器碼會發(fā)現(xiàn)它被正確地換成了同樣的<SPAN lang=EN-US> push/push/call 指令。但是,在使用 invoke 之前,為了讓它進行正確的參數(shù)檢驗,你需要對函數(shù)進行申明,就象在 C 中一樣,申明的語句是:<o:p></o:p></SPAN></P>
, D# q0 g$ x& b6 W$ m! V' @; T# Z<P><SPAN lang=EN-US>MyProc proto :DWORD,:DWORD<o:p></o:p></SPAN></P>+ Y3 ^ J6 p1 `
<P>語句中<SPAN lang=EN-US> proto 是關(guān)鍵字,表示申明,:DWORD 表示參數(shù)的類型是 double word 類型的,有幾個就表示有幾個參數(shù),在 Win32 中參數(shù)都是 double word 型的,申明語句要寫在 invoke 之前,所以我們一般把它包括在 include 文件中,好了,綜合一下,在 Masm32 中使用一個帶參數(shù)的子程序或者 Api ,我們只需用:<o:p></o:p></SPAN></P>, z/ g' ~3 D( i5 ^6 J. z7 U. r3 d
<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> |