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