在 Win32匯編中,我們經(jīng)常要和 Api 打交道,另外也會(huì)常常使用自己編制的類似于 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>
0 s6 G5 m: y) ^<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>9 z) p! O3 `, f# T
<TBODY>
& }0 Z/ X$ U9 J8 H1 q<TR>
+ Q; u& h) Z# _$ ?' U3 C# C<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; PADDING-TOP: 0cm">
9 e- a1 l! }; d& r- F' u<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>
. a( k$ p: {& r* G& Q% d<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; PADDING-TOP: 0cm">) ]+ q. S% |! P9 C
<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>
/ c8 ~0 G8 o+ _<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; PADDING-TOP: 0cm">
4 x" E/ Z- O- _$ ~<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>
! j& { ?9 P: X T, g<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; PADDING-TOP: 0cm">
+ \: O( }( B: V9 Y6 G; ~<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>
7 w- h( n e; \2 [9 H4 v) r8 T7 s: d<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; PADDING-TOP: 0cm">0 j9 b1 x+ w! r! w0 d2 k
<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>
+ v+ f2 Y5 X1 _, I5 \ ~; P<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; PADDING-TOP: 0cm">% y) d6 E/ `9 x! ?4 @
<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>6 w9 `( }) A, w- S& Y% o2 S
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; PADDING-TOP: 0cm">
& B; t1 z- ^. j# s, j4 B( J, u' J<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>- w0 U8 ^5 R/ ~$ Y- _2 \4 v! }
<TR>
3 a m" [# i; d$ X<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; WIDTH: 28%; PADDING-TOP: 0cm" width="28%">
+ w& D+ Y: y0 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>
7 ]9 a: h. h' Z% d' j* k, i<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
* ^6 }3 X. B5 @& o. 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>% U3 Y. Z/ E5 T: [# W1 L# x6 N
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">! K! N* ]: U2 k
<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>
) A; i/ D, K# b1 E; P, ~<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">" O6 ?1 K& I% O
<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>* D1 t) H6 m: V k
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
* H2 c+ H2 Y9 d1 D, 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>
: W" C& s r- w( J! v% I8 k; b<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
q) h& [$ B1 X0 x: \) 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>4 R7 @' s1 x+ ?" q1 f! T1 v) C4 w
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">' h; L5 d9 B& p" r, 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></TR>* g6 E; |4 i3 V, n5 P% @
<TR>
6 u/ ^& U2 l2 Z) }9 s! v* h. F<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; WIDTH: 28%; PADDING-TOP: 0cm" width="28%">7 |8 k1 B2 B0 p# a, M
<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>
7 ]" m. w& ^; ^7 @' X4 F<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
. _7 k2 v& I: b' C- [# 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>
5 d- l* \, D, ?6 A5 ~2 M! ~<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
1 U% }5 X; o; ?# 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>" `+ ~# i4 x: q
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">- p- D1 B" o- c( W3 [0 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>
* m3 r$ R2 o V6 [' P1 K9 f5 [<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">, V3 R) j2 W& t5 s0 s0 P8 D5 l' P' 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>5 S- X7 M9 ~" U; a" I$ U+ c, c
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">( l, P( ?8 I" K, B6 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>
- N6 ?6 f# R/ C: s S1 i<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
& G9 E9 j- P. r7 ]0 U: d% }& O<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 @7 x J( q, j5 V& f7 X
<TR>+ J* Q4 \2 O) F% X h. r
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; WIDTH: 28%; PADDING-TOP: 0cm" width="28%">
8 O) h* c* a" {& d: O x4 W- p$ u<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>. G: M8 o4 R) D4 a; R8 R' @4 Y
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">! L( E# u4 y, 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>
$ W; r) b6 q' p8 p9 j: x- |) b<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
3 Z$ p1 K! D( a% X% {0 k& 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>
: f f6 ~% a/ Q" e4 E% S- s3 [7 F<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">3 I v. f" H# F H9 ^# R% 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>
- t: M$ c1 n* W4 e: o: X<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
0 M/ J# k+ B! ?( N6 O- C; u$ 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>
" J& e& T' d. c8 A<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
' L4 g, S+ ~+ ?9 d7 D<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! T; C: m6 i: Y5 {
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
, F7 T' |. n6 L, }! X8 y6 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></TR>7 Y# m& D. _; j/ X% O- n
<TR>
3 y# D: V- ^0 j2 v7 w<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #66cccc; PADDING-BOTTOM: 0cm; WIDTH: 28%; PADDING-TOP: 0cm" width="28%">- K. j" Z: s1 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>
+ z9 |7 l* u( N% A$ @) w; z6 W$ f<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
. I1 C, n' j3 z9 p2 F# w( 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>, p# |6 ~0 `2 L! g) ?
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">! |8 @ \. r8 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>
% k6 `1 ]6 ?! w; [) J% U% I<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
5 g( v2 r$ a8 k6 t- z: {4 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>. n8 @' [. i2 j8 m
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">8 O0 {$ n8 C# Y1 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>5 i0 q' W' s: H& S* E: }, N- S, k
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">; N/ L9 z0 \5 x- L) T$ 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>6 m. f/ `9 ^7 z8 f9 i6 K4 ?
<TD style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; BACKGROUND: #ccccff; PADDING-BOTTOM: 0cm; WIDTH: 12%; PADDING-TOP: 0cm" width="12%">
$ }' L6 Y+ {2 K- N5 s9 Y<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>
) j5 g- H t$ |7 r/ G) T7 ]' u! E<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>
4 _; r- X3 }8 R( ~4 x/ {1 V 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>3 a% V. I E, E. j: d
<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>
, }4 y' Z+ _& H7 F8 H2 H<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>
9 Y$ q: j% M, t; k5 I z<P><SPAN lang=EN-US> <o:p></o:p></SPAN></P>
( \# ~4 ?( O5 |: o/ |' h7 M; q' q<P><SPAN lang=EN-US> <o:p></o:p></SPAN></P>( W8 i9 ?- r. P$ O/ @1 o" Y
<P><SPAN lang=EN-US> <o:p></o:p></SPAN></P>
; v0 I) \, X+ S; b" y% K* P<P><SPAN lang=EN-US> <o:p></o:p></SPAN></P>& E m$ ~/ T3 p3 {9 H/ q$ ]1 a
<P><SPAN lang=EN-US> <o:p></o:p></SPAN></P>) ?2 }2 f: r( n! \
<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>
' t! \6 x3 L" r( P* S<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>
% ~( W E% }3 ?6 M" t<P><SPAN lang=EN-US>sub esp,8<o:p></o:p></SPAN></P>) l" N8 C, O s, L: \( ]% L }
<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 i R& i) l# n# K: E
<P><SPAN lang=EN-US>add esp,8<o:p></o:p></SPAN></P>
8 a) W5 c V& x$ E2 y<P><SPAN lang=EN-US>pop ebp<BR>ret 8<o:p></o:p></SPAN></P>
2 k0 Y: V" q7 A- w; q4 P; [ G<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 處理器有兩條專用的指令是完成這個(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>
" H8 b$ c1 ^& N3 q: n, B% h<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>7 i/ v8 s3 p6 C5 n
<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>
% f4 M2 A1 o/ m9 I E3 {<P><SPAN lang=EN-US>MyProc proc Var1,Var2<BR>local lVar1,lVar2<o:p></o:p></SPAN></P>2 f [: {- ?/ d3 g( E
<P><SPAN lang=EN-US>mov eax,Var1<BR>sub eax,Var2<BR>ret<o:p></o:p></SPAN></P>
( `) l( E1 Y- E: u8 |. O* z. M<P><SPAN lang=EN-US>MyProc endp<o:p></o:p></SPAN></P>
* n7 y h4 o+ K7 b: e M0 u<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>' S* ]! z" Y; A2 ]
<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ù)、類型是否正確,并使用 call 來(lái)調(diào)用的一個(gè)宏指令,對(duì)于上面的 push/push/call MyProc 的指令,可以用一條指令完成就是:<o:p></o:p></SPAN></P>) ^3 y0 I7 J) L. Z
<P><SPAN lang=EN-US>invoke MyProc,Var1,Var2<o:p></o:p></SPAN></P>
; K0 U7 z1 f8 C1 q/ M3 h7 x<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>2 N! i% q- [8 k! `
<P><SPAN lang=EN-US>MyProc proto :DWORD,:DWORD<o:p></o:p></SPAN></P>0 [" l; Z w# a! H; c3 e
<P>語(yǔ)句中<SPAN lang=EN-US> proto 是關(guān)鍵字,表示申明,:DWORD 表示參數(shù)的類型是 double word 類型的,有幾個(gè)就表示有幾個(gè)參數(shù),在 Win32 中參數(shù)都是 double word 型的,申明語(yǔ)句要寫(xiě)在 invoke 之前,所以我們一般把它包括在 include 文件中,好了,綜合一下,在 Masm32 中使用一個(gè)帶參數(shù)的子程序或者 Api ,我們只需用:<o:p></o:p></SPAN></P>
6 x7 M5 U4 N$ H& E" n* i<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> |