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