2013-07-13 31 views
15

我對程序集很陌生,我不明白它的意思是什麼時候,在proc結束時,用ret語句編寫一個數字。程序集中RET的含義

像這樣:

Function Proc 
push ax cx 
. 
...body... 
. 
pop cx ax 
ret 2 
Function endp 

我理解它是與棧指針應該在函數的最後返回?

請幫助我,如果你可以很容易地解釋它。

+6

彙編不是一種語言 - 每個處理器都有自己的語言。你應該問一個特定的架構(x86,看起來)。 – ugoren

+0

x86的答案是[here](http://download.intel.com/products/processor/manual/325383.pdf) – ugoren

+2

題外話:'ret'是一個強大的小指令,開發漏洞軟件的中心:它根據調用堆棧的內存內容來引導程序的控制流程。如果你控制內存('strcpy',我在看你),你控制程序執行流程。 –

回答

14

是的,但ret 2也從堆棧中刪除2個字節的參數。據推測,您的函數被調用,如:

push some_parameter 
call Function 

在這一點上,一個cdecl功能 - 一個「來電者清理」功能(一般使用C) - 將需要add sp, 2「清理棧」,去掉參數。這樣的功能將以簡單的ret結束。

一個stdcall功能,這是你的本事,是個「被叫清理」功能(由Windows API的使用,例如)不需要add sp, 2 - 它已經被ret 2完成。

如果你不知道它,call把返回地址放在堆棧上(並且ret彈出),所以你不能只是pop在你的函數中獲取參數。

3

這意味着RETurn,就像在return高級語言。

在大多數機器上,在從堆棧輸入子程序並將其複製到PC寄存器之前,它將彈出程序計數器的先前值。

對於x86,參數是堆棧上的參數數量。這僅適用於使用的約定是讓子例程處理重置堆棧的情況。

+0

那麼旁邊的數字是什麼意思? –

+0

@RotemMayo請參閱我的編輯。 – alex

+2

小修正:立即數操作數指定在返回時從棧中「彈出」額外_bytes_的數量。 – Michael

6

正如亞歷克斯所說,這意味着返回。 在x86彙編中,當編譯器到達此行時(例如在子例程的末尾),它會從堆棧中彈出最後一個值,該值應該是返回地址,並將其分配給IP寄存器。你可以通過編寫一個簡單的彙編代碼並使用Turbo Debugger進行編譯來更好地理解它。如果你是新手,那麼彙編程序就有一個GUI。你可以找到GUI here

當您在子程序中彈出並向堆棧推送值時,應該存儲返回地址,因爲在子路由的末尾,需要將其推回到堆棧中,然後纔可以將return線。

祝你好運!

12

可以說我有一個程序來添加兩個單詞並將總和留在EAX。這些詞是我想傳遞給堆棧上的過程的參數。一世。E:

push word1 
push word2 
call addtwob 

的過程看起來是這樣的:在棧上

addtwob proc 

push ebp 
mov ebp,esp 
mov eax, [ebp+6]  
add eax, [ebp+8] 
pop ebp 
ret 4 

Endp 

[ebp+6][ebp+8]地址word2word1ret 4只是像往常一樣返回,但隨後將4添加到堆棧指針(esp)中,因此您不必在從調用返回後離開堆棧,因此它可以清除/平衡堆棧而無需彈出先前的推送。

1

你似乎在問一個關於返回的,x86_64的操作數是。在處理器遇到RET附近時由硬件跟隨的算法在Intel instruction set reference manual中示出如下;

(* Near return *) 
IF instruction = near return 
    THEN; 
    IF OperandSize = 32 
     THEN 
     IF top 4 bytes of stack not within stack limits 
      THEN #SS(0); FI; //throw protected mode exception 
     EIP ← Pop(); 
     ELSE 
     IF OperandSize = 64 
      THEN 
      IF top 8 bytes of stack not within stack limits 
       THEN #SS(0); FI; //throw protected mode exception 
      RIP ← Pop(); 
      ELSE (* OperandSize = 16 *) 
      IF top 2 bytes of stack not within stack limits 
       THEN #SS(0); FI; //throw protected mode exception 
      tempEIP ← Pop(); 
      tempEIP ← tempEIP AND 0000FFFFH; 
      IF tempEIP not within code segment limits 
       THEN #GP(0); FI; //throw protected mode exception 
      EIP ← tempEIP; 
     FI; 
    FI; 
    IF instruction has immediate operand 
     THEN (* Release parameters from stack *) 
     IF StackAddressSize = 32 
      THEN 
      ESP ← ESP + SRC; 
      ELSE 
      IF StackAddressSize = 64 
       THEN 
       RSP ← RSP + SRC; 
       ELSE (* StackAddressSize = 16 *) 
      SP ← SP + SRC; 
      FI; 
     FI; 
    FI; 
FI; 
  • 按照這個算法每當遇到一個近返回,返回地址進行檢查,無論是在SS的限制。如果返回地址有效,則根據操作數大小將堆棧頂部彈出到RIP或EIP。

  • 如果操作數大小爲16位,則臨時位置保存彈出的返回地址,該地址與值0x0000FFFF進行與運算,並在檢查CS限制後將其加載到EIP中。

  • 當你的問題詢問如果有一個操作數到近RET指令操作碼會發生什麼。它取決於堆棧地址大小。根據該大小,RSP ESP或SP由操作數增加,並且在所有近RET指令在硬件上完成執行之後。

+1

'pop cx'是OP正在查看16位代碼的一個非常明顯的標誌。出於某種原因,人們會問很多關於16位代碼的Stack Overflow問題。他們中的一些人正在製作玩具操作系統,其中大多數人正在參加大學課程,因爲某些瘋狂的原因而使用emu8086教授8086。 –