2016-11-05 176 views
-3

我正在讀一本關於程序集的書,我正試着學習一點關於這種語言的知識。我有一些代碼來了解他在做什麼,但我遇到了麻煩。以彙編語言開頭

有人請解釋下面的代碼是什麼?

push ebp   //put in top the stack, right? 
mov ebp, esp  //mov the value esp to ebp 
push ecx   // ok... 
mov eax, [ebp+8] //What's ebp+8? 
add eax, [ebp+0Ch] //What's ebp+0Ch? 
add eax, [ebp+10h] //What's ebp+10h 
mov [ebp-4], eax //What's ebp-4 
mov eax, [ebp-4] 
mov esp, ebp 
pop ebp 
retn 

總結:是什麼讓這段代碼? 我什麼都不懂。

+0

棧也是普通的內存。所以要操縱堆棧中的值,你也可以用[esp]來解決它。進入你的程序後,[esp]指向返回地址(堆棧頂部)。 'push ebp'將存儲舊的'ebp'值,[esp]現在指向舊的ebp,[esp + 4]是返回地址(堆棧「向下增長」,'push dword value'做'esp - = 4') 。然後在調用你(第一個參數)之前,'[esp + 8]'是由棧上的調用者推送的dword。當你將'esp'複製到'ebp'時,你現在可以用'[ebp + 8]'來解決它。在調試器中運行它,將存儲器窗口指向esp區域,然後觀察那裏的值。 – Ped7g

+1

什麼使得這段代碼是什麼? –

回答

1

在解釋的代碼,所述PUSH操作碼的功能,必須定義:

它遞減堆棧指針,然後存儲在堆棧的頂部的源操作數。

所以,首先,下面兩行創建一個標準的堆棧幀。他們分配給EBP堆棧指針(ESP當前位置,這是通過引用它們相對於EBP(所謂基本指針)訪問堆棧上的局部變量非常有用。

push ebp   //put in top the stack, right? 
mov ebp, esp  //mov the value esp to ebp 

現在EBP指向當前堆棧位置。

下面的行推ECX到堆棧(ESP) - 降低ESP由4. EBP保持不變。

push ecx   // ok... 

因爲EBP調用時這個函數減去4(見上文),將下面的行

mov eax, [ebp+8] //What's ebp+8? 

移動第一參數EBP+8EAX仍然指向堆棧中的位置。

記住:

  • 進入時:ESP = X(=返回地址推入有由CALLPUSH EBP
  • 後:ESP = X-4(=返回地址是在ESP + 4)
  • 然後EBP被設定爲:ESP = X-4(EBP = ESP = X-4(現在指向EBP的舊值))
  • 所以返回地址位於​​和第一參數位於EBP+8(32位= 4字節)。

等等這樣的:

add eax, [ebp+0Ch] //What's ebp+0Ch? 

[EBP+0Ch]是第二個參數...

add eax, [ebp+10h] //What's ebp+10h 

[EBP+10h]是第三個參數。

因此,以下行將EAX複製到堆棧上的32位值。這是ECX,這是PUSH'd到上面的堆棧。

mov [ebp-4], eax //What's ebp-4 

複製回來以下行ECX局部變量是很沒用......

mov eax, [ebp-4] 

現在堆棧幀通過複製EBPESP恢復。

mov esp, ebp 
pop ebp 

下面一行只是做一個32位附近回報給調用者:

retn 

我認爲這解釋了這個子程序的功能相當不錯。

+0

對於向下增長的堆棧,寫入是錯誤的*輸入時:ESP = x ...在PUSH EBP後:ESP = x + 4 * –

+0

*然後EBP設置爲:ESP = x + 4(=返回地址+4 )*我無法對這句話做出正確的迴應! –

+0

@SepRoland:當然,你的權利。我修復了這個錯誤並添加了一些進一步的解釋 – zx485

3

我會評論每一行與它做什麼:

push ebp   //Saves EBP 
mov ebp, esp  //Establishes a pointer 
push ecx   //Creates local storage 
mov eax, [ebp+8] //This retrieves the 1st parameter 
add eax, [ebp+0Ch] //This retrieves the 2nd parameter 
add eax, [ebp+10h] //This retrieves the 3rd parameter 
mov [ebp-4], eax //This holds the original ECX, now overwritten by the sum of all 3 parameters 
mov eax, [ebp-4] //This sum is the final result in EAX 
mov esp, ebp  //Forgets about the local storage 
pop ebp   //Restores EBP 
retn    //Returns 

採用push ecx創建本地存儲提供了一個較短的程序。
另一種方法是sub esp,4

所以這段代碼的最終目標是計算3個數字的總和。

+1

有時候少就是多。 –