青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

沒畫完的畫

喂馬 劈柴 BBQ~
posts - 37, comments - 55, trackbacks - 0, articles - 0
  C++博客 ::  :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理
注: 本文摘自互聯(lián)網(wǎng),本人看了按理解加了些東西

為了弄清楚函數(shù)的堆棧,Google了一下,找到下面代碼作為實(shí)驗(yàn)
 1#include <stdio.h>
 2#include <string.h>
 3
 4void func1(int input1, int input2)
 5{
 6    int j;
 7    char c;
 8    short k;
 9
10    j = 0;
11    c = 'a';
12    k = 1;
13
14    printf("sum=%d\n", input1+input2);
15
16    return;
17}

18
19int main()
20{
21    char output[8= "abcdef";
22    int i, j;
23
24    i=2;
25    j=3;
26    func1(i,j);
27
28    printf("%s\r\n", output);
29
30    return 0;
31}

32


本人在 vc6 + winxp 進(jìn)行調(diào)試
vc6 中在 fun1 設(shè)置斷點(diǎn),按F5,  到達(dá)斷點(diǎn)后,選擇菜單 view -> Disassembly 就可以看到代碼對(duì)應(yīng)的匯編語句

調(diào)用 func1() 之前

26:       func1(i,j);
004010D7   mov         ecx,dword ptr [ebp-10h]
004010DA   push        ecx
004010DB   mov         edx,dword ptr [ebp-0Ch]
004010DE   push        edx
004010DF   call        @ILT+0(func1) (00401005)
004010E4   add         esp,8
------------------------------------------------
EAX = 00000000 EBX = 7FFDE000 ECX = 00006665 EDX = 00370E00
ESI = 00000000 EDI = 0012FF80
EIP = 004010D7 ESP = 0012FF24 EBP = 0012FF80 EFL = 00000246
------------------------------------------------
i,j 分別存放在棧中,地址分別是
------------------------------------------------
ebp-10h = 0x0012FF80h - 0x10h = 0x0012FF70h
ebp-0Ch = 0x0012FF80h - 0x0Ch = 0x0012FF74h

0012FF70  03 00 00 00 02 00 00  .......
0012FF77  00 61 62 63 64 65 66  .abcdef

0012FF6D  CC CC CC 03 00 00 00  燙.....
0012FF74  02 00 00 00 61 62 63  ....abc

從內(nèi)存存放的內(nèi)容可知, i, j 分別存放于 0x0012FF70H, 0x0012FF74H
分別占了四個(gè)字節(jié)

在調(diào)用 func1() 之前, 先將 i, j 壓入堆棧, 壓入堆棧的順序是 i, j
(故出棧的順序是j, i, 請(qǐng)記住, 這里的 傳遞函數(shù)參數(shù) 默認(rèn)是 __cdecl) 

接著調(diào)用了 call 指令
執(zhí)行 call 指令之前的寄存器狀態(tài)
------------------------------------------------
EAX = 00000000 EBX = 7FFDE000 ECX = 00000003 EDX = 00000002
ESI = 00000000 EDI = 0012FF80
EIP = 004010DF ESP = 0012FF1C EBP = 0012FF80 EFL = 00000246
------------------------------------------------
執(zhí)行 call 指令之后的寄存器狀態(tài)
EAX = 00000000 EBX = 7FFDE000 ECX = 00000003 EDX = 00000002
ESI = 00000000 EDI = 0012FF80
EIP = 00401005 ESP = 0012FF18 EBP = 0012FF80 EFL = 00000246
------------------------------------------------
變化的是 EIP 與 ESP
棧頂指針寄存器ESP:保存棧頂?shù)刂?指針)
此時(shí) ESP 向低地址偏移了四個(gè)字節(jié)
可見 call 指令執(zhí)行了一個(gè) push 操作

查看 ESP 對(duì)象的地址 0x0012FF18 的內(nèi)容
0012FF18  E4 10 40 00 02 00 00  ..@....
0012FF1F  00 03 00 00 00 00 00  .......

push 進(jìn)去的數(shù)是 0x004010E4, 再看回調(diào)用 call 之后的代碼

26:       func1(i,j);
004010D7   mov         ecx,dword ptr [ebp-10h]
004010DA   push        ecx
004010DB   mov         edx,dword ptr [ebp-0Ch]
004010DE   push        edx
004010DF   call        @ILT+0(func1) (00401005)
004010E4   add         esp,8

push 進(jìn)去的數(shù)剛好是 call 指令后面的指令地址 0x004010E4  

為什么沒有看到push指令呢?
原來在CALL操作中,隱式地把call指令后續(xù)第一條指令的地址0x004010E4 入棧,
然后再無條件地跳轉(zhuǎn)到func1()函數(shù)繼續(xù)執(zhí)行。

@ILT+0(?func1@@YAXHH@Z):
00401005   jmp         func1 (00401020)

004010DF   call        @ILT+0(func1) (00401005)

奇怪的事情是 call 后面的操作數(shù)應(yīng)該是 func1 的地址 0x00401020 才對(duì), 為何是 0x00401005?
還是一個(gè) @ILT+0 的東東是什么?

在DEBUG版本中,VC匯編程序會(huì)產(chǎn)生一個(gè)函數(shù)跳轉(zhuǎn)指令表,
該表的每個(gè)表項(xiàng)存放一個(gè)函數(shù)的跳轉(zhuǎn)指令。
程序中的函數(shù)調(diào)用就是利用這個(gè)表來實(shí)現(xiàn)跳轉(zhuǎn)到相應(yīng)函數(shù)的入口地址。

ILT就是函數(shù)跳轉(zhuǎn)指令表的名稱,是Import Lookup Table的縮寫;
@ILT就是函數(shù)跳轉(zhuǎn)指令表的首地址。
在DEBUG版本中增加函數(shù)跳轉(zhuǎn)指令表,其目的是加快編譯速度,當(dāng)某函數(shù)的地址發(fā)生變化時(shí),只需要修改ILT相應(yīng)表項(xiàng)即可,而不需要修改該函數(shù)的每一處引用。
注意:在RELEASE版本中,不會(huì)生成ILT,也就是說call指令的操作數(shù)直接是函數(shù)的入口地址,例如在本例中是這樣的:call 00401020


接下來, 應(yīng)該看一下 jmp func1 后, 做了哪些東西

4:    void func1(int input1, int input2)
5:    {
00401020   push        ebp
00401021   mov         ebp,esp
00401023   sub         esp,4Ch
00401026   push        ebx
00401027   push        esi
00401028   push        edi
00401029   lea         edi,[ebp-4Ch]
0040102C   mov         ecx,13h
00401031   mov         eax,0CCCCCCCCh
00401036   rep stos    dword ptr [edi]
------------------------------------------------
此時(shí)各寄存器的值為
EAX = 00000000 EBX = 7FFDE000 ECX = 00000003 EDX = 00000002
ESI = 00000000 EDI = 0012FF80
EIP = 00401020 ESP = 0012FF18 EBP = 0012FF80 EFL = 00000246

ebp 為 main 函數(shù)層的 棧內(nèi)存基地址
esp 為 當(dāng)前的棧頂?shù)刂?/p>

00401020   push        ebp
00401021   mov         ebp,esp

這兩個(gè)語句 先把 ebp 壓入堆棧, 再把 esp 賦值給 ebp
這兩句的作用將在后面說明

00401023   sub         esp,4Ch
然后,棧頂指針esp向低地址偏移76(0x4C)字節(jié)。這里相當(dāng)于為func1()函數(shù)層分配了棧內(nèi)存。
(為什么偏偏是 76 是字節(jié)?)
(題外話: 平時(shí)程序調(diào)試的 stack over 又是如何造成的?)

接著又把 ebx, esi, edi 分別入棧, 目的是為了保存 main 函數(shù)層的相關(guān)內(nèi)容
00401026   push        ebx
00401027   push        esi
00401028   push        edi

最后用0xCC初始化上述為func1()函數(shù)層所分配的棧內(nèi)存的每個(gè)字節(jié)。這里每一步用F11單步跟蹤,棧內(nèi)存的變化你會(huì)看得更清楚。
00401029   lea         edi,[ebp-4Ch]     ; 將有效的地址 [ebp-0x4Ch] 賦值到 edi
0040102C   mov         ecx,13h           ;
00401031   mov         eax,0CCCCCCCCh    ;
00401036   rep stos    dword ptr [edi]   ;

stos指令:
字符串存儲(chǔ)指令 STOS
格式: STOS OPRD
其中OPRD為目的串符號(hào)地址.
功能: 把AL(字節(jié))或AX(字)中的數(shù)據(jù)存儲(chǔ)到DI為目的串地址指針?biāo)鶎ぶ返拇鎯?chǔ)器單元中去.指針DI將根據(jù)DF的值進(jìn)行自動(dòng)調(diào)整.
由于上面的指令是 dword ptr 類型
dword 表示雙字 ptr 表示取首地址
那么 stos    dword ptr [edi] 執(zhí)行的操作就是
將 ES:[DI]←AX,DI←DI±4   (DI 加或減是由 DF 標(biāo)志位確定的)
如果是 那么 stos word ptr [edi] 的話那么就是
將 ES:[DI]←AL,DI←DI±2   (DI 加或減是由 DF 標(biāo)志位確定的)
不然推出 stos BYTE ptr [edi]

注:
DF:方向標(biāo)志DF位用來決定在串操作指令執(zhí)行時(shí)有關(guān)指針寄存器發(fā)生調(diào)整的方向。

重復(fù)前綴
格式: REP           ;CX<>0 重復(fù)執(zhí)行字符串指令

REP 每執(zhí)行一次后面的字符串指令后, cx減1, 直至 cx 為0
在本例中, 每次拷貝 sizeof(DWORD) 四個(gè)字節(jié), 而堆棧大小是 76(0x4C) 個(gè)字節(jié), 故 只需要重復(fù)執(zhí)行 76 / 4 = 19(0x13) 次就可以了

0040102C   mov         ecx,13h           ;

現(xiàn)在終于清楚

00401029   lea         edi,[ebp-4Ch]     ; 將有效的地址 [ebp-0x4Ch] 賦值到 edi
0040102C   mov         ecx,13h           ;
00401031   mov         eax,0CCCCCCCCh    ;
00401036   rep stos    dword ptr [edi]   ;

的作用就是把堆棧的數(shù)據(jù)置為 0xCC;


困了,先去睡下再寫第2集~~

Feedback

# re: 函數(shù)堆棧是這么回事 第1集[未登錄]  回復(fù)  更多評(píng)論   

2008-09-26 10:43 by flyswift
很好很強(qiáng)大。LZ繼續(xù)。

# re: 函數(shù)堆棧是這么回事 第1集  回復(fù)  更多評(píng)論   

2008-09-26 13:55 by ljbxc
支持,繼續(xù)

# re: 函數(shù)堆棧是這么回事 第1集  回復(fù)  更多評(píng)論   

2008-09-26 15:23 by luke
入棧的順序應(yīng)該是j,i吧?

# re: 函數(shù)堆棧是這么回事 第1集  回復(fù)  更多評(píng)論   

2008-09-27 16:03 by 908971
mark
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美一级视频一区二区| 一区二区欧美在线观看| 亚洲国产经典视频| 亚洲自拍偷拍网址| 亚洲一区在线观看视频| 国产精品免费网站| 亚洲欧美视频在线观看| 亚洲直播在线一区| 亚洲精品在线视频观看| 欧美精品电影| 欧美一区二区三区免费大片| 午夜精品美女久久久久av福利| 国产伦精品一区二区三区在线观看| 亚洲午夜精品| 欧美资源在线观看| 亚洲免费观看高清完整版在线观看熊 | 日韩一区二区免费高清| 亚洲国产日韩欧美在线图片| 欧美日韩综合网| 久久精品国产亚洲一区二区| 欧美大片在线观看| 久久精品免视看| 亚洲一级片在线看| 久久久亚洲国产天美传媒修理工| 亚洲精品一区二区在线| 亚洲手机在线| 日韩一级在线观看| 久久大逼视频| 亚洲欧美激情在线视频| 免费视频久久| 蜜桃视频一区| 国内外成人免费视频 | 亚洲破处大片| 国产一区二区精品久久| 亚洲精品一区二区三区福利| 在线高清一区| 久久三级视频| 欧美激情1区2区| 久久久精品999| 国内精品一区二区三区| 亚洲综合精品一区二区| 亚洲在线一区| 国产热re99久久6国产精品| 亚洲午夜一二三区视频| 亚洲永久免费精品| 国产日产亚洲精品系列| 亚洲免费一在线| 久久精品五月婷婷| 在线观看精品一区| 欧美日韩免费看| 午夜精品久久久久久久男人的天堂 | 欧美激情一区在线| 日韩午夜视频在线观看| 亚洲欧美日韩视频二区| 久久久伊人欧美| 国产精品视频999| 欧美一区二视频| 亚洲高清视频一区二区| 亚洲在线一区二区三区| 国产日韩欧美视频| 久久国产精品99国产| 亚洲福利视频网| 国产精品视频久久久| 免费日韩一区二区| 亚洲午夜一区| 亚洲国产乱码最新视频| 欧美在线影院在线视频| 亚洲乱码国产乱码精品精98午夜| 国产日韩亚洲| 国产精品v亚洲精品v日韩精品| 欧美一级二区| 亚洲女人天堂av| 一区二区冒白浆视频| 欧美黄色免费| 欧美国产日产韩国视频| 亚洲网站啪啪| 一本久久青青| 夜夜嗨av一区二区三区四季av| 黄色综合网站| 亚洲高清不卡一区| 极品尤物av久久免费看| 国内精品亚洲| 136国产福利精品导航网址| 国产欧美日韩| 欧美视频在线一区二区三区| 欧美精品久久久久久| 久久久噜噜噜久久中文字免| 亚洲自啪免费| 久久精品首页| 亚洲欧洲av一区二区| 久久久久久欧美| 美女久久一区| 欧美午夜电影在线| 99精品视频一区| 午夜精品一区二区三区四区| 亚洲一区欧美激情| 亚洲欧美综合精品久久成人| 欧美在线亚洲综合一区| 欧美成人在线影院| 国产精品自拍小视频| 一区在线观看视频| 亚洲日本欧美天堂| 亚洲欧美在线高清| 亚洲娇小video精品| 99这里只有精品| 亚洲欧美日韩爽爽影院| 欧美在线播放一区二区| 亚洲欧洲在线播放| 亚洲欧洲av一区二区| 欧美裸体一区二区三区| 国产色爱av资源综合区| 亚洲已满18点击进入久久| 欧美成人蜜桃| 久久国产精品久久久久久久久久 | 亚洲电影免费观看高清| 欧美在线视频日韩| 国产精品久久久久久av下载红粉| 亚洲国产aⅴ天堂久久| 久久久久欧美精品| 久久久久久精| 一区二区精品在线| 欧美日韩精品系列| 一区二区免费在线播放| 日韩天堂在线观看| 欧美三级特黄| 亚洲女女做受ⅹxx高潮| 亚洲视频一二| 国产精品一区二区女厕厕| 亚洲欧美日本另类| 午夜精品久久久久久99热软件| 欧美亚洲动漫精品| 亚洲欧美综合v| 久久国产欧美精品| 亚洲人成在线影院| 一区二区三区蜜桃网| 日韩视频一区二区| 久久久人成影片一区二区三区| 精品福利av| 国语自产精品视频在线看| 欧美激情精品久久久| 欧美性猛交xxxx乱大交蜜桃| 久久久一区二区| 欧美福利一区| 欧美在线免费播放| 欧美精品久久99| 久久午夜精品| 欧美日本一道本在线视频| 噜噜爱69成人精品| 国产乱肥老妇国产一区二| 麻豆精品精华液| 欧美午夜在线| 欧美激情1区2区3区| 国产精品午夜在线| 亚洲激情偷拍| 亚洲国产精品悠悠久久琪琪| 亚洲午夜视频| 一区二区三区毛片| 免费在线观看成人av| 麻豆精品精华液| 国语对白精品一区二区| 新片速递亚洲合集欧美合集| 亚洲特黄一级片| 欧美视频一二三区| 99在线精品免费视频九九视| 亚洲精品国产精品乱码不99| 午夜精品久久久久久99热| 亚洲综合电影| 国产精品免费看久久久香蕉| 一本一本久久a久久精品综合麻豆| 亚洲国产成人精品久久| 久久久久天天天天| 猛干欧美女孩| 亚洲精品视频在线播放| 欧美精品激情| 一区二区三区成人 | 午夜精品久久99蜜桃的功能介绍| 亚洲综合社区| 激情伊人五月天久久综合| 蜜臀av在线播放一区二区三区| 欧美国产精品| 免费在线日韩av| 一区二区高清视频在线观看| 欧美影片第一页| 在线免费观看日本一区| 国产精品成av人在线视午夜片| 亚洲欧美日韩精品久久| 久久嫩草精品久久久久| 亚洲国产日韩一区| 国产伦精品一区二区三区在线观看| 久久婷婷久久一区二区三区| 亚洲精品激情| 久久伊人亚洲| 久久激情视频久久| 一区二区欧美日韩| 亚洲区第一页| 亚洲第一中文字幕| 激情久久中文字幕| 欧美视频在线观看 亚洲欧| 乱码第一页成人| 久久综合电影|