欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
匯編中參數的傳遞和堆棧修正
  

|






   在 Win32匯編中,我們經(jīng)常要和 Api 打交道,另外也會(huì )常常使用自己編制的類(lèi)似于 Api 的帶參數的子程序,本文要講述的是在子程序調用的過(guò)程中進(jìn)行參數傳遞的概念和分析。一般在程序中,參數的傳遞是通過(guò)堆棧進(jìn)行的,也就是說(shuō),調用者把要傳遞給子程序(或者被調用者)的參數壓入堆棧,子程序在堆棧取出相應的值再使用,比如說(shuō),如果你要調用 SubRouting(Var1,Var2,Var3),編譯后的最終代碼可能

   push Var3
   push Var2
   push Var1
   call SubRouting
   add esp,12

   也就是說(shuō),調用者首先把參數壓入堆棧,然后調用子程序,在完成后,由于堆棧中先前壓入的數不再有用,調用者或者被調用者必須有一方把堆棧指針修正到調用前的狀態(tài)。參數是最右邊的先入堆棧還是最左邊的先入堆棧、還有由調用者還是被調用者來(lái)修正堆棧都必須有個(gè)約定,不然就會(huì )產(chǎn)生不正確的結果,這就是我在前面使用“可能”這兩個(gè)字的原因:各種語(yǔ)言中調用子程序的約定是不同的,它們的不同點(diǎn)見(jiàn)下表:
  C SysCall StdCall Basic Fortran Pascal
參數從左到右      
參數從右到左      
調用者清除堆棧          
允許使用:VARARG      

   VARARG 表示參數的個(gè)數可以是不確定的,有一個(gè)例子就是 C 中的 printf 語(yǔ)句,在上表中,StdCall 的定義有個(gè)要說(shuō)明的地方,就是如果 StdCall 使用 :VARARG 時(shí),是由調用者清除堆棧的,而在沒(méi)有:VARARG時(shí)是由被調用者清除堆棧的。在 Win32 匯編中,約定使用 StdCall 方式,所以我們要在程序開(kāi)始的時(shí)候使用 .model stdcall 語(yǔ)句。也就是說(shuō),在 API 或子程序中,最右邊的參數先入堆棧,然后子程序在返回的時(shí)候負責校正堆棧,舉例說(shuō)明,如果我們要調用 MessageBox 這個(gè) API,因為它的定義是 MessageBox(hWnd,lpText,lpCaption,UType) 所以在程序中要這樣使用:

   push MB_OK
   push offset szCaption
   push offset szText
   push hWnd
   call MessageBox
   ...

   我們不必在 API 返回的時(shí)候加上一句 add sp,4*4 來(lái)修正堆棧,因為這已經(jīng)由 MessageBox 這個(gè)子程序做了。在 Windows API 中,唯一一個(gè)特殊的 API 是 wsprintf,這個(gè) API 是 C 約定的,它的定義是 wsprintf(lpOut,lpFormat,Var1,Var2...),所以在使用時(shí)就要:

   push 1111
   push 2222
   push 3333
   push offset szFormat
   push offset szOut
   call wsprintf
   add esp,4*5

   下面要講的是子程序如何存取參數,因為缺省對堆棧操作的寄存器有 ESP 和 EBP,而 ESP是堆棧指針,無(wú)法暫借使用,所以一般使用 EBP 來(lái)存取堆棧,假定在一個(gè)調用中有兩個(gè)參數,而且在 push 第一個(gè)參數前的堆棧指針 ESP 為 X,那么壓入兩個(gè)參數后的 ESP 為 X-8,程序開(kāi)始執行 call 指令,call 指令把返回地址壓入堆棧,這時(shí)候 ESP 為 X-C,這時(shí)已經(jīng)在子程序中了,我們可以開(kāi)始使用 EBP 來(lái)存取參數了,但為了在返回時(shí)恢復 EBP 的值,我們還是再需要一句 push ebp 來(lái)先保存 EBP 的值,這時(shí) ESP 為 X-10,再執行一句 mov ebp,esp,根據上圖可以看出,實(shí)際上這時(shí)候 [ebp + 8] 就是參數1,[ebp + c]就是參數2。另外,局部變量也是定義在堆棧中的,它們的位置一般放在 push ebp 保存的 EBP 數值的后面,局部變量1、2對應的地址分別是 [ebp-4]、[ebp-8],下面是一個(gè)典型的子程序,可以完成第一個(gè)參數減去第二個(gè)參數,它的定義是:

   MyProc proto Var1,Var2 ;有兩個(gè)參數
   local lVar1,lVar2 ;有兩個(gè)局部變量

   注意,這里的兩個(gè) local 變量實(shí)際上沒(méi)有被用到,只是為了演示用,具體實(shí)現的代碼是:

MyProc proc

   push ebp
   mov ebp,esp
   sub esp,8
   mov eax,dword ptr [ebp + 8]
   sub eax,dword ptr [ebp + c]
   add esp,8
   pop ebp
   ret 8

MyProc endp

   現在對這個(gè)子程序分析一下,push ebp/mov ebp,esp 是例行的保存和設置 EBP 的代碼,sub esp,8 在堆棧中留出兩個(gè)局部變量的空間,mov /add 語(yǔ)句完成相加,add esp,8 修正兩個(gè)局部變量使用的堆棧,ret 8 修正兩個(gè)參數使用的堆棧,相當于 ret / add esp,8 兩句代碼的效果??梢钥闯?,這是一個(gè)標準的 Stdcall 約定的子程序,使用時(shí)最后一個(gè)參數先入堆棧,返回時(shí)由子程序進(jìn)行堆棧修正。當然,這個(gè)子程序為了演示執行過(guò)程,使用了手工保存 ebp 并設置局部變量的方法,實(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 的功能,所以上面的程序可以改成:

MyPorc proc

   enter 8,0

   mov eax,dword ptr [ebp + 8]
   sub eax,dword ptr [ebp + c]

   leave
   ret 8

MyProc endp

   好了,說(shuō)到這兒,參數傳遞的原理也應該將清楚了,還要最后說(shuō)的是,在使用 Masm32 編 Win32 匯編程序的時(shí)候,我們并不需要記住 [ebp + xx] 等麻煩的地址,或自己計算局部變量需要預留的堆??臻g,還有在 ret 時(shí)計算要加上的數值,Masm32 的宏指令都已經(jīng)把這些做好了,如在 Masm32 中,上面的程序只要寫(xiě)成為:

MyProc proc Var1,Var2
   local lVar1,lVar2

   mov eax,Var1
   sub eax,Var2
   ret

MyProc endp

   編譯器會(huì )自動(dòng)的在 mov eax,Var1 前面插上一句 Enter 語(yǔ)句,它的參數會(huì )根據 local 定義的局部變量的多少自動(dòng)指定,在 ret 前會(huì )自動(dòng)加上一句 Leave,同樣,編譯器會(huì )根據參數的多少把 ret 替換成 ret xxx,把 mov eax,Var1 換成 mov eax,dword ptr [ebp + 8] 等等。
   最后是使用 Masm32 的 invoke 宏指令,在前面可以看到,調用帶參數的子程序時(shí),我們需要用 push 把參數壓入堆棧,如果不小心把參數個(gè)數搞錯了,就會(huì )使堆棧不平衡,從而使程序從堆棧中取出錯誤的返回地址引起不可預料的后果,所以有必要有一條語(yǔ)句來(lái)完成自動(dòng)檢驗的任務(wù),invoke 就是這樣的語(yǔ)句,實(shí)際上,它是自動(dòng) push 所有參數,檢測參數個(gè)數、類(lèi)型是否正確,并使用 call 來(lái)調用的一個(gè)宏指令,對于上面的 push/push/call MyProc 的指令,可以用一條指令完成就是:

invoke MyProc,Var1,Var2

當然,當程序編譯好以后你去看機器碼會(huì )發(fā)現它被正確地換成了同樣的 push/push/call 指令。但是,在使用 invoke 之前,為了讓它進(jìn)行正確的參數檢驗,你需要對函數進(jìn)行申明,就象在 C 中一樣,申明的語(yǔ)句是:

MyProc proto :DWORD,:DWORD

語(yǔ)句中 proto 是關(guān)鍵字,表示申明,:DWORD 表示參數的類(lèi)型是 double word 類(lèi)型的,有幾個(gè)就表示有幾個(gè)參數,在 Win32 中參數都是 double word 型的,申明語(yǔ)句要寫(xiě)在 invoke 之前,所以我們一般把它包括在 include 文件中,好了,綜合一下,在 Masm32 中使用一個(gè)帶參數的子程序或者 Api ,我們只需用:

   ...
   MyProc proto :dword,:dword
   ...
   .data
   x dd ?
   y dd ?
   dwResult dd ?
   ...
   mov x,1
   mov y,2
   invoke MyProc x,y
   mov dwResult,eax
   ...





本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
[轉載]匯編中參數的傳遞和堆棧修正 - 機器細語(yǔ)[ ASM ] - 各類(lèi)程序語(yǔ)言{ Pro...
ebp,esp區別
通過(guò)一段匯編,加深對寄存器ESP和EBP的理解
論函數調用約定
DLL中調用約定和名稱(chēng)修飾(一)
函數調用方式介紹
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久