C代码+汇编 C的 函数汇编学习分析 rep stos dword ptr [edi]
如分析有誤,請在評論區中,指出 謝謝合作
 主要是分析C的函數調用在匯編中的執行流程
本章主要是說一下函數調用時堆棧的變化,重點理解部分
C代碼
#include"stdafx.h" int plus(int x,int y){return x+y; }int main() { plus(0,1);return 0; }匯編代碼 VC6.0++ 反編譯所得 (如分析有誤,請在評論區提出,謝謝)
//函數部分 0040100A jmp plus (00401010) //跳轉到 00401010內存位置 0040100F int 3 //無視 00401010 push ebp //ebp壓棧 00401011 mov ebp,esp // esp的值 賦給 ebp 00401013 sub esp,40h //esp = esp-40H //esp寄存器是棧首位置,相當于提升堆棧,開辟 00401016 push ebx //壓棧 00401017 push esi //壓棧 00401018 push edi //壓棧 00401019 lea edi,[ebp-40h] //將ebp的內存地址 - 40H 后所得的內存地址 賦值給 edi寄存器 0040101C mov ecx,10h 將 10H (16) 賦給 ecx寄存器 00401021 mov eax,0CCCCCCCCh 將 ,0CCCCCCCCh 賦值給eax 00401026 rep stos dword ptr [edi] //循環 ecx的次數 00401028 mov eax,dword ptr [ebp+8] //將ebp+8的內存地址的值 賦給 eax 0040102B add eax,dword ptr [ebp+0Ch] // eax = eax + (ebp+0Ch)的值 0040102E pop edi //彈出棧 0040102F pop esi //彈出棧 00401030 pop ebx //彈出棧 00401031 mov esp,ebp //恢復堆棧 00401033 pop ebp //彈出棧底 00401034 ret //相當于 pop eip//main函數部分 0040B76E push 1 //壓棧 因為C函數的調用約定 '__stdcall', plus(0,1); 參數從右向左壓入堆棧 0040B770 push 0 //壓棧 0040B772 call @ILT+5(plus) (0040100a) 0040B777 add esp,8一步一步來,這里的話 需要畫圖哈.別急
前置條件:
堆棧的特點是 前大后小(內存地址) 本章是 32位寄存器 所以一次性 4
 main函數中, (棧首)esp的寄存器的值為 0019FEF4 , (棧尾)ebp的寄存器的值為 0019FF40
 自繪圖
 
 匯編圖
 
代碼邏輯執行開始,主要是堆棧的變
------1
0040B76E push 1 //壓棧 因為C函數的調用約定 '__stdcall', plus(0,1); 參數從右向左壓入堆棧 0040B770 push 0 //壓棧 0040B772 call @ILT+5(plus) (0040100a)0040B777 0040B777 add esp,8push壓棧時: 修改的 esp(棧頂的值) -4
 執行前三句:結果如圖
 前兩句應該很好理解
 call指令,在指令執行的時候,會把call的內存地址 下一行的內存地址 壓入堆棧中
 
 --------2
第一行跳轉,不用多說
 第二行無視
 第三行: push ebp//將堆棧的底,壓入到內存地址
 
第一句 ebp = esp,含義為 執行這個函數開辟內存
 
 第二局 esp的內存地址 減去40H = 19FEA4? 個人見解:提升堆棧 40H=64(十進制) 因為32寄存器 堆棧為4 所以就是提升 64/4= 16
 
前三句沒什么好說的
 就是壓棧
 
 lea edi,[ebp-40h] //這句話就有點意思了。 ebp-40H就是剛才 esp-40H的地址一樣的,將值賦值給EDI
高能從這里開始 就比較有意思了
0040101C mov ecx,10h //重復次數 00401021 mov eax,0CCCCCCCCh //eax = 0XCCCCCCCC 00401026 rep stos dword ptr [edi] //第一句 ecx寄存器一般用來計數, 10H = 16(十進制) 跟我們剛才 ESP-40H 的內存地址也是16個
 第二句 將0CCCCCCCCh 賦值給EAX寄存器
 第三句 rep stos 【repeat(重復) store(保存) string】
 指令解析
rep 重復前綴指令,英文縮寫 repeat,每執行一次, ecx 減 1,直到 ecx 減至0,重復執行結束
stos 串存儲指令,英文縮寫 store string ,將 eax 中的數據傳送到目的地址(目的地址默認edi寄存器),
 以下兩條指令相當于一條 stos 指令
首次執行的匯編圖
 
 10H = 16(十進制) 所以rep就是執行16次,所得結果如圖
 匯編圖:
 自繪圖
 
自繪圖可以明顯看到 ebp+8 與 ebp+0ch 也就是函數傳參的兩個值
 也就是C代碼 x+y;
這三句都是出棧, 注意出棧后esp的棧頂指針會+4
 這三句的自繪圖,這時esp的棧頂指針的內存地址為 19FEA4
 
這三句是本章重點
00401031 mov esp,ebp 00401033 pop ebp 00401034 ret自繪圖,這三句執行前的堆棧圖
 
當執行 的時候,堆棧的 棧頂與棧尾在同一個位置
 
因為執行pop 所以 esp的棧頂指針(0019FEE4)+4 = (0019FEE8)
 因為 pop彈出的是堆棧 所以 ebp的值會回到 上一次的位置 也就是 0019FF40(有疑問請看第一張自繪圖,這里比較難理解,多看幾遍,建議手畫一畫圖)
ret指令用棧中的數據,修改偏移地址,從而實現近轉移 就相當于 pop eip
 所以ESP棧頂指針(0019FEE8) +4 = (0019FEEC),這時的堆棧圖
 
//esp (0019FEEC)+8 = 0019 FEF4?
 這句就是函數的堆棧平衡,也就是操作數據時,開辟堆棧內存.用完了以后又恢復到 調用函數之前的位置:
 最后的自繪圖
 
總結:
1.調用函數的時候,堆棧會為函數執行開辟內存,
00401011 mov ebp,esp 00401013 sub esp,40h2.調用函數時 用的是Call指令,并且會開辟空間,把函數的參數壓棧,并且把后一個eip地址也壓棧
 特點:
 1.會先將ebp棧底指針壓棧,還有一些寄存器 首要特點push ebp ,mov ebp,esp
 2.Call函數后面的那一句 一般是堆棧平衡的代碼
整理不易,花了好幾個小時,有任何問題請在評論區指出,喜歡的話,點個關注或者喜歡哈
總結
以上是生活随笔為你收集整理的C代码+汇编 C的 函数汇编学习分析 rep stos dword ptr [edi]的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: C代码+汇编 C的for汇编学习分析
 - 下一篇: java 富文本编辑器的标签处理数据