程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 從反匯編來學習C++<1> 參數傳遞--常量

從反匯編來學習C++<1> 參數傳遞--常量

編輯:關於C語言

前言

國內大牛們在這方面的著作其實已經比較多了,但他們的重心多是教會大家逆向分析。我寫這系列的目的,則是為了通過反匯編來更好的理解C++中的一些概念。

文中第一次出現的匯編指令我都會簡單解釋一下,方便不熟悉匯編又想了解匯編的人查看。但是匯編的大多數指令都會涉及到直接尋址,間接尋址,寄存器間接尋址等等,詳細介紹這個就脫離本文的主題了,各位若想要更深入的說明,還請各位自己查看相關資料。


那就開始吧。

正文


傳遞常量

先來看看最簡單的參數傳遞是如何實現的。


void testInt(int i)
{
    i = 10;
}
int main()
{
    testInt(1); //傳遞常量
    return 0;
}

反匯編如下

主函數做了這些事

00A813CE  push        1
00A813D0  call        testInt (0A81082h)
00A813D5  add         esp,4

匯編指令解釋:

push data data是四個字節的數據,這條指令將data壓入堆棧,然後堆棧指針ESP 減去 4

call addr addr是函數地址。這條指令會將當前指令的下一條指令的地址壓入堆棧。然後跳轉到地址為addr的指令處,繼續執行。

add ptr,data ptr指向的數據加上data後,存儲在ptr指向的空間


下面來看看testInt函數反匯編後是什麼樣的。注意:下面顯示的地址值可能和上面提到過的不同。這是因為每次重新調試程序的時候,函數的地址都會改變,請不要在意。


009B1380  push        ebp
009B1381  mov         ebp,esp
009B1383  sub         esp,0C0h
009B1389  push        ebx
009B138A  push        esi
009B138B  push        edi
009B138C  lea         edi,[ebp+FFFFFF40h]
009B1392  mov         ecx,30h
009B1397  mov         eax,0CCCCCCCCh
009B139C  rep stos    dword ptr es:[edi]
009B139E  mov         dword ptr [ebp+8],0Ah
009B13A5  pop         edi
009B13A6  pop         esi
009B13A7  pop         ebx
009B13A8  mov         esp,ebp
009B13AA  pop         ebp
009B13AB  ret

匯編指令解釋:

mov ptr1,ptr2 將ptr2指向的數據存儲在ptr1指向的空間

sub ptr1,ptr2 ptr1指向的數據減去ptr2指向的數據,將結果存儲在ptr1指向的空間。

lea ptr,data 將data存儲在ptr指向的空間。注意是data,而不是data指向的數據。

rep stos ptr 這條指令是這樣執行的:重復判斷ecx是否為0。為0則結束該指令。否則將eax寄存器中的內容存儲在ptr指向的空間。每循環一次,ecx減1,如果設置了direction flag,edi減1,否則加1。通常ptr都是一個由edi組成的表達式,不然循環多次,把eax的值放在同一個地方,就沒意義了。

pop ptr 這條指令與push相對。先彈出棧頂的一個四字節數據,存儲在ptr指向的空間,然後esp加4。

ret 與call相對。彈出棧頂的一個四字節數據,存儲在EIP寄存器中。實現函數返回。


第1-10行 幾乎所有的函數體中都有,主要作用是保存ebp,ebx,esi,edi這四個寄存器的值,以便在本函數中可以隨意使用這四個寄存器,而不會影響調用函數。 為了堆棧平衡,esp寄存器的值也要保存。

第12-16行 恢復ebp,ebx,esi,edi,esp寄存器的值。

第11行 十幾行的指令只有這行是我們寫在函數內的i = 10;反匯編出來的結果。

ebp+8是什麼呢?

首先可以看到3-11行並未改變ebp的值。然後我們將第3行之前影響堆棧的指令按照執行順序給列出來。

push 1

call testInt

push ebp

mov ebp,esp

這4條指令執行完後堆棧是這樣的:

214204715.png

由上圖就可以知道esp+8是第一個參數的地址。第11行指令把0Ah存在了這個地址指向的空間,也就是執行了i = 10;

當然這系列操作毫無意義,函數返回後,除了參數所占其余棧空間全部釋放。函數返回後,又立即給esp加上4,好了,參數所占的棧空間也釋放了。


本文出自 “三人乘虎” 博客,請務必保留此出處http://darhx.blog.51cto.com/7920146/1304242

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved