在 Win32匯編中,我們經(jīng)常要和 Api 打交道,另外也會(huì)常常使用自己編制的類(lèi)似于 Api 的帶參數(shù)的子程序,本文要講述的是在子程序調(diào)用的過(guò)程中進(jìn)行參數(shù)傳遞的概念和分析。一般在程序中,參數(shù)的傳遞是通過(guò)堆棧進(jìn)行的,也就是說(shuō),調(diào)用者把要傳遞給子程序(或者被調(diào)用者)的參數(shù)壓入堆棧,子程序在堆棧取出相應(yīng)的值再使用,比如說(shuō),如果你要調(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>也就是說(shuō),調(diào)用者首先把參數(shù)壓入堆棧,然后調(diào)用子程序,在完成后,由于堆棧中先前壓入的數(shù)不再有用,調(diào)用者或者被調(diào)用者必須有一方把堆棧指針修正到調(diào)用前的狀態(tài)。參數(shù)是最右邊的先入堆棧還是最左邊的先入堆棧、還有由調(diào)用者還是被調(diào)用者來(lái)修正堆棧都必須有個(gè)約定,不然就會(huì)產(chǎn)生不正確的結(jié)果,這就是我在前面使用“可能”這兩個(gè)字的原因:各種語(yǔ)言中調(diào)用子程序的約定是不同的,它們的不同點(diǎn)見(jiàn)下表:<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p>
. A6 x4 l, y! p- S* {<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>
7 ?- Q k3 R& |5 @8 w; h/ a/ o; a<TBODY>
% L/ w" M0 v! [! _<TR>
2 n- R( z7 B: e1 Y2 S% B<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; PADDING-TOP: 0cm">- @* k0 p8 F4 E' I& }3 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>$ [6 v: c$ o: w& j2 \ K* z5 ?
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; PADDING-TOP: 0cm">
' T D. c9 H& o/ a0 {5 y( Z<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>
8 l) u; y- u5 Y, H5 V8 n6 z' o* ?( G1 k<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; PADDING-TOP: 0cm">+ B" B7 k1 ]5 I$ u) n) y
<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># Z: c; m+ d- T$ e9 D
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; PADDING-TOP: 0cm">
+ Y; w8 \" l- `0 e7 T$ 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>% n( y) W2 S/ S: j- t: {
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; PADDING-TOP: 0cm">
/ P# K+ N0 j9 K D<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>- L) W4 j7 W# {7 |$ f R* I s
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; PADDING-TOP: 0cm">
' l- i2 \( f: o* S; W, P# m) k<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>' {0 z( y# r; D: t
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; PADDING-TOP: 0cm">
% M9 N' }) c% c. C<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>( ?. L4 N9 H5 U$ w: F, ~, l
<TR>
& Z% j( {1 z! J+ n' g' X<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; WIDTH: 28%; PADDING-TOP: 0cm" width="28%">0 j4 a- d. u$ G0 m, Y# n
<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>3 ^& H5 y! O# A6 G; S( [
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
) X+ Y8 C9 C: C0 k2 |9 I6 h<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>. L9 { y% z4 `# L6 [- J2 ~
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
; J, \ t) [5 r! w, Q8 _1 w( h V<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>
; z* z6 h8 @& y$ W) V) {* d<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
' ]3 ~! l3 X3 W- T L<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>& J1 D0 Q) z8 |0 ^1 @- A, \
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">. m4 Z/ [5 D: j" r) H* Y# L$ 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>+ E+ ^7 l- F# U" T* u- K
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
9 q: O) l' l* I0 L* u<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 m, E- F* }% j F! j- v
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
% t3 l4 c# o3 m4 s/ 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></TR>$ o+ J- h* y1 b
<TR>* S6 Z0 K! G8 [& K0 g8 _# d( q) i
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; WIDTH: 28%; PADDING-TOP: 0cm" width="28%">
) Q. X) v4 [. o4 a<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>
5 o+ m' X( [' l W9 L9 H2 d<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
, K' i* Z: A5 H' h0 p4 q<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>
* d8 S" h8 L6 o8 m$ Y7 N% a! t<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
' L: w, t. m' A5 p: P( A" o9 E<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 F3 o v* i- z A. E( g
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
: W0 B( P( P9 b' c7 E9 E<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# F3 j6 d9 k% [" n( `<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
+ u* }, s. l8 L8 X D4 W<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>. R, S0 s6 Z+ H! e' x: ?
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
5 b) K1 G6 q6 a& p% U. Q# M<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>6 C z1 B* Z. T
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">$ n1 y8 t- n& k! g. 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>2 |% i8 N/ ? ?
<TR>9 l _/ A- a0 i6 W
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; WIDTH: 28%; PADDING-TOP: 0cm" width="28%">6 J/ \- t" ]2 R4 X
<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>) D" o5 o* T0 a- W, q$ Z) C
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">. E1 N' J: w% f3 D. k# 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>
% \5 m2 }$ A5 l) R4 t7 l4 ?- p<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
+ R6 x+ w) e3 P# |5 E. w<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>* A7 c' f9 B" p4 a6 e5 i8 @9 g- j7 F1 \) C
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
9 c; J; j) Y; h1 v<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>4 S* T. {6 T. t$ H3 l. N
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">& s! F9 e. Q3 {0 x' s1 V1 S
<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>' p/ |9 B( Z+ U' Y3 K% v2 m' ?8 S' K
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
- F% q& A9 q, `; n! m$ N6 l<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>6 C& F: O& m5 [2 k) ~
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
, n2 _% G* I+ ?. 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>% k) E% S# Q. L
<TR>% x S! ~7 H) E0 w' L' I5 F4 C
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; WIDTH: 28%; PADDING-TOP: 0cm" width="28%">
1 Y& ^1 W+ b, H2 t. x- `# F9 [<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>
0 D' w5 t# p; X( c, Y<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
4 T0 O: @9 N( 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>
2 [: b$ N2 r0 t* c$ {+ _1 y% W<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%"># e$ A, q/ q3 j- p
<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 M: Q/ p1 r6 H6 u; L o3 t<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">( S- Y. |- L# E5 x" R& j: U$ U
<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/ N- _! h; h# \<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">! C8 X( K+ l2 u& n7 x- X b3 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>) \% d, m/ g0 s1 P, m0 o: N9 t# C
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">$ R0 p1 v9 w2 k! 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>6 D1 u# j4 B8 e/ B+ _
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">0 f7 B5 \+ ^. p4 a, M7 ]2 t
<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>, L4 A& e1 y$ c0 P4 \/ j
<P><SPAN lang=EN-US>VARARG 表示參數(shù)的個(gè)數(shù)可以是不確定的,有一個(gè)例子就是 C 中的 printf 語(yǔ)句,在上表中,StdCall 的定義有個(gè)要說(shuō)明的地方,就是如果 StdCall 使用 :VARARG 時(shí),是由調(diào)用者清除堆棧的,而在沒(méi)有:VARARG時(shí)是由被調(diào)用者清除堆棧的。<BR>在 Win32 匯編中,約定使用 StdCall 方式,所以我們要在程序開(kāi)始的時(shí)候使用 .model stdcall 語(yǔ)句。也就是說(shuō),在 API 或子程序中,最右邊的參數(shù)先入堆棧,然后子程序在返回的時(shí)候負(fù)責(zé)校正堆棧,舉例說(shuō)明,如果我們要調(diào)用 MessageBox 這個(gè) API,因?yàn)樗亩x是 MessageBox(hWnd,lpText,lpCaption,UType) 所以在程序中要這樣使用:<o:p></o:p></SPAN></P>: ~* k$ q; H$ T: F. G
<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>8 a. y6 n8 N+ s
<P>我們不必在<SPAN lang=EN-US> API 返回的時(shí)候加上一句 add sp,4*4 來(lái)修正堆棧,因?yàn)檫@已經(jīng)由 MessageBox 這個(gè)子程序做了。在 Windows API 中,唯一一個(gè)特殊的 API 是 wsprintf,這個(gè) API 是 C 約定的,它的定義是 wsprintf(lpOut,lpFormat,Var1,Var2...),所以在使用時(shí)就要:<o:p></o:p></SPAN></P>3 a7 \% A1 q' N1 v | m
<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# \( L: h$ o* c* N# R, V& e/ r: k
<P><SPAN lang=EN-US> <o:p></o:p></SPAN></P>
" L- o e! K E7 }& m, m<P><SPAN lang=EN-US> <o:p></o:p></SPAN></P>) u) |; S) D; \( s; h j0 g* G( A
<P><SPAN lang=EN-US> <o:p></o:p></SPAN></P>; O, j1 y& |% g1 ~/ ?) i
<P><SPAN lang=EN-US> <o:p></o:p></SPAN></P>
4 M2 M1 v" u8 c$ K4 O% ]<P><SPAN lang=EN-US> <o:p></o:p></SPAN></P>( z7 |. E" L5 y! X
<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ù),因?yàn)槿笔?duì)堆棧操作的寄存器有<SPAN lang=EN-US> ESP 和 EBP,而 ESP是堆棧指針,無(wú)法暫借使用,所以一般使用 EBP 來(lái)存取堆棧,假定在一個(gè)調(diào)用中有兩個(gè)參數(shù),而且在 push 第一個(gè)參數(shù)前的堆棧指針 ESP 為 X,那么壓入兩個(gè)參數(shù)后的 ESP 為 X-8,程序開(kāi)始執(zhí)行 call 指令,call 指令把返回地址壓入堆棧,這時(shí)候 ESP 為 X-C,這時(shí)已經(jīng)在子程序中了,我們可以開(kāi)始使用 EBP 來(lái)存取參數(shù)了,但為了在返回時(shí)恢復(fù) EBP 的值,我們還是再需要一句 push ebp 來(lái)先保存 EBP 的值,這時(shí) ESP 為 X-10,再執(zhí)行一句 mov ebp,esp,根據(jù)右圖可以看出,實(shí)際上這時(shí)候 [ebp + 8] 就是參數(shù)1,[ebp + c]就是參數(shù)2。另外,局部變量也是定義在堆棧中的,它們的位置一般放在 push ebp 保存的 EBP 數(shù)值的后面,局部變量1、2對(duì)應(yīng)的地址分別是 [ebp-4]、[ebp-8],下面是一個(gè)典型的子程序,可以完成第一個(gè)參數(shù)減去第二個(gè)參數(shù),它的定義是:<BR><BR>MyProc proto Var1,Var2 ;有兩個(gè)參數(shù)<BR>local lVar1,lVar2 ;有兩個(gè)局部變量<o:p></o:p></SPAN></P>
4 `8 ]/ w1 R; O5 |; C& x) P<P>注意,這里的兩個(gè)<SPAN lang=EN-US> local 變量實(shí)際上沒(méi)有被用到,只是為了演示用,具體實(shí)現(xiàn)的代碼是:<BR><BR>MyProc proc<BR><BR>push ebp<BR>mov ebp,esp<o:p></o:p></SPAN></P>
. t/ z2 p( C! `<P><SPAN lang=EN-US>sub esp,8<o:p></o:p></SPAN></P>7 I* g- k. O$ S
<P><SPAN lang=EN-US>mov eax,dword ptr [ebp + 8]<BR>sub eax,dword ptr [ebp + c]<o:p></o:p></SPAN></P>/ s' l- |9 r `1 Z) H1 s% C4 z
<P><SPAN lang=EN-US>add esp,8<o:p></o:p></SPAN></P>8 ~! Y" q7 r0 s2 C/ B5 ^
<P><SPAN lang=EN-US>pop ebp<BR>ret 8<o:p></o:p></SPAN></P>
# N7 |6 E: C/ o6 v$ B<P><SPAN lang=EN-US>MyProc endp<BR><BR>現(xiàn)在對(duì)這個(gè)子程序分析一下,push ebp/mov ebp,esp 是例行的保存和設(shè)置 EBP 的代碼,sub esp,8 在堆棧中留出兩個(gè)局部變量的空間,mov /add 語(yǔ)句完成相加,add esp,8 修正兩個(gè)局部變量使用的堆棧,ret 8 修正兩個(gè)參數(shù)使用的堆棧,相當(dāng)于 ret / add esp,8 兩句代碼的效果??梢钥闯?,這是一個(gè)標(biāo)準(zhǔn)的 Stdcall 約定的子程序,使用時(shí)最后一個(gè)參數(shù)先入堆棧,返回時(shí)由子程序進(jìn)行堆棧修正。當(dāng)然,這個(gè)子程序?yàn)榱搜菔緢?zhí)行過(guò)程,使用了手工保存 ebp 并設(shè)置局部變量的方法,實(shí)際上,386 處理器有兩條專(zhuān)用的指令是完成這個(gè)功能用的,那就是 Enter 和 Leave,Enter 語(yǔ)句的作用就是 push ebp/mov ebp,esp/sub esp,xxx,這個(gè) xxx 就是 Enter 的,Leave 則完成 add esp,xxx/pop ebp 的功能,所以上面的程序可以改成:<o:p></o:p></SPAN></P>/ p D& h' P& F: `: K {
<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>) M6 }: ?' r1 q$ ]& T: y; {' @
<P>好了,說(shuō)到這兒,參數(shù)傳遞的原理也應(yīng)該將清楚了,還要最后說(shuō)的是,在使用<SPAN lang=EN-US> Masm32 編 Win32 匯編程序的時(shí)候,我們并不需要記住 [ebp + xx] 等麻煩的地址,或自己計(jì)算局部變量需要預(yù)留的堆??臻g,還有在 ret 時(shí)計(jì)算要加上的數(shù)值,Masm32 的宏指令都已經(jīng)把這些做好了,如在 Masm32 中,上面的程序只要寫(xiě)成為:<o:p></o:p></SPAN></P>4 I6 w+ O4 m* f; U" `: |) g( }2 h
<P><SPAN lang=EN-US>MyProc proc Var1,Var2<BR>local lVar1,lVar2<o:p></o:p></SPAN></P>& y7 F O5 ^9 F' }- _) g( r& ^
<P><SPAN lang=EN-US>mov eax,Var1<BR>sub eax,Var2<BR>ret<o:p></o:p></SPAN></P>7 w y l' `* C
<P><SPAN lang=EN-US>MyProc endp<o:p></o:p></SPAN></P>
! v/ b8 Z% B7 p q2 h, H<P>編譯器會(huì)自動(dòng)的在<SPAN lang=EN-US> mov eax,Var1 前面插上一句 Enter 語(yǔ)句,它的參數(shù)會(huì)根據(jù) local 定義的局部變量的多少自動(dòng)指定,在 ret 前會(huì)自動(dòng)加上一句 Leave,同樣,編譯器會(huì)根據(jù)參數(shù)的多少把 ret 替換成 ret xxx,把 mov eax,Var1 換成 mov eax,dword ptr [ebp + 8] 等等。<o:p></o:p></SPAN></P>3 x# ^" b7 x! S
<P>最后是使用<SPAN lang=EN-US> Masm32 的 invoke 宏指令,在前面可以看到,調(diào)用帶參數(shù)的子程序時(shí),我們需要用 push 把參數(shù)壓入堆棧,如果不小心把參數(shù)個(gè)數(shù)搞錯(cuò)了,就會(huì)使堆棧不平衡,從而使程序從堆棧中取出錯(cuò)誤的返回地址引起不可預(yù)料的后果,所以有必要有一條語(yǔ)句來(lái)完成自動(dòng)檢驗(yàn)的任務(wù),invoke 就是這樣的語(yǔ)句,實(shí)際上,它是自動(dòng) push 所有參數(shù),檢測(cè)參數(shù)個(gè)數(shù)、類(lèi)型是否正確,并使用 call 來(lái)調(diào)用的一個(gè)宏指令,對(duì)于上面的 push/push/call MyProc 的指令,可以用一條指令完成就是:<o:p></o:p></SPAN></P>
4 G$ Q3 y4 w5 q+ R7 q9 ?* c, Q<P><SPAN lang=EN-US>invoke MyProc,Var1,Var2<o:p></o:p></SPAN></P>
3 d! P' V0 K) e2 a<P>當(dāng)然,當(dāng)程序編譯好以后你去看機(jī)器碼會(huì)發(fā)現(xiàn)它被正確地?fù)Q成了同樣的<SPAN lang=EN-US> push/push/call 指令。但是,在使用 invoke 之前,為了讓它進(jìn)行正確的參數(shù)檢驗(yàn),你需要對(duì)函數(shù)進(jìn)行申明,就象在 C 中一樣,申明的語(yǔ)句是:<o:p></o:p></SPAN></P>
6 ]$ L. g3 y- c5 i; S. u6 x<P><SPAN lang=EN-US>MyProc proto :DWORD,:DWORD<o:p></o:p></SPAN></P>
' W: ^/ v, ~4 i P9 ]/ d<P>語(yǔ)句中<SPAN lang=EN-US> proto 是關(guān)鍵字,表示申明,:DWORD 表示參數(shù)的類(lèi)型是 double word 類(lèi)型的,有幾個(gè)就表示有幾個(gè)參數(shù),在 Win32 中參數(shù)都是 double word 型的,申明語(yǔ)句要寫(xiě)在 invoke 之前,所以我們一般把它包括在 include 文件中,好了,綜合一下,在 Masm32 中使用一個(gè)帶參數(shù)的子程序或者 Api ,我們只需用:<o:p></o:p></SPAN></P>
1 x4 h+ e) A" e6 t<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> |