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

loop_in_codes

低調(diào)做技術(shù)__歡迎移步我的獨立博客 codemaro.com 微博 kevinlynx

一段tricky codes:函數(shù)調(diào)用的那些底層細節(jié)


有一天,被同事問到了下面這段代碼,就簡單分析了一下,發(fā)覺還有點意思:

__declspec(naked)
void call(void* pfn, 
{
    __asm 
    
{
        pop eax;
        add eax, 
3;
        xchg dword ptr[esp], eax;
        push eax;
        ret;
    }

}

 

再看它的用法:

 

void print_str( const char *s )
{
    printf( 
"%s\n", s );
}

call( print_str, 
"a string" );

 

call函數(shù)的大致作用,就是調(diào)用傳遞進去的函數(shù)print_str,并將參數(shù)"a string"傳遞給目標(biāo)
函數(shù)。

但是它是怎么做到的呢?雖然call只有簡單的幾句匯編代碼,但是卻包含了很多函數(shù)在編譯
器中的匯編層實現(xiàn)。要了解這段代碼的意思,需要知道如下相關(guān)知識:

0、函數(shù)調(diào)用的實現(xiàn)中,編譯器通過系統(tǒng)堆棧(ESP寄存器指向)傳遞參數(shù);
1、C語言默認的函數(shù)調(diào)用規(guī)則(_cdecl)中,調(diào)用者從右往左將參數(shù)壓入堆棧,并且調(diào)用者負
責(zé)堆棧平衡,也就是保證調(diào)用函數(shù)的前后,ESP不變;
2、匯編指令call本質(zhì)上是先將返回地址,通常是該條指令的下一條指令壓入堆棧,然后直
接跳轉(zhuǎn)到目標(biāo)位置;
3、匯編指令ret則是先從堆棧棧頂取出返回地址,然后跳轉(zhuǎn)過去;
4、匯編指令add加上其操作數(shù),貌似占3個字節(jié)長度;
5、在visual studio中,DEBUG模式下編譯器會在我們的代碼中插入各種檢測代碼,而
__declspec(naked)則是告訴編譯器:別往這里添加代碼。

了解了以上常識后,再看這段代碼,其本質(zhì)無非就是利用了這些規(guī)則,在代碼段跳來跳去。
我們來逐步分析一下:

在調(diào)用call函數(shù)的地方,大概的代碼為:

 

caller:
// 堆棧狀態(tài),從左往右分別表示棧頂至下
// ret_addr是call后的地址,即add esp, 8的位置
// a1, a2表示函數(shù)參數(shù),callee_addr是這里的print_str
// stack: ret_addr, callee_addr, a1, a2, 
call( print_str, "a string" ); 
add esp, 
8 //清除參數(shù)傳遞所占用的堆棧空間,維持堆棧平衡
end_label //位于add后的指令,后面會提到

call:
// 此時堆棧stack: ret_addr, a1, a2
pop eax // eax = ret_addr; stack: callee_addr, a1, a2, 
add eax, 3 // eax = end_label; stack: callee_addr, a1, a2, 
xchg dword ptr[esp], eax // eax = callee_addr; stack: end_label, a1, a2, 
push eax // stack: callee_addr, end_label, a1, a2, 
ret // 取出callee_addr并跳轉(zhuǎn),也就跳轉(zhuǎn)到print_str函數(shù)的入口,此時堆棧
    
// stack: end_label, a1, a2, 

callee(print_str):

 無視函數(shù)內(nèi)容

ret 
// print_str返回,此時正常情況下,堆棧stack: end_label, a1, a2, 
 
// 取出end_label并跳轉(zhuǎn),stack: a1, a2, 

 

那么當(dāng)callee結(jié)束時,則跳轉(zhuǎn)回caller函數(shù)中。不過,如過你所見,此時堆棧中還保留著再
調(diào)用call函數(shù)時傳入的參數(shù):stack: a1, a2, ...,所以,DEBUG模式下,VS就會提示你堆
棧不平衡。這里簡單的處理就是手動來進行堆棧平衡:

 

    call( print_str, "a string" );
    __asm
    
{
        add esp, 
4
    }

 

傳入了多少個參數(shù),就得相應(yīng)地改變esp的值。

話說距離上篇博客都有半年了,自己都不知道時間晃得如此之快。最近業(yè)余折騰了下android開發(fā)
一不小心就跨年了。
 

posted on 2011-01-02 16:34 Kevin Lynx 閱讀(4932) 評論(4)  編輯 收藏 引用 所屬分類: c/c++

評論

# re: 一段tricky codes:函數(shù)調(diào)用的那些底層細節(jié) 2011-01-03 05:58 淘寶網(wǎng)

哈哈 不錯  回復(fù)  更多評論   

# re: 一段tricky codes:函數(shù)調(diào)用的那些底層細節(jié) 2011-01-06 12:30 miosys

整個懸念就是放在 add eax, 3;
這條指令就是為了在跳轉(zhuǎn)到最外層主調(diào)函數(shù)上時,留出一個指令空間來平棧。
如果用 ADD + WORD,應(yīng)該是 3。當(dāng)然不會BT到加 DWORD。  回復(fù)  更多評論   

# re: 一段tricky codes:函數(shù)調(diào)用的那些底層細節(jié) 2011-01-08 21:47 G++

圍觀,表示看不懂,哈哈哈哈哈~~~!  回復(fù)  更多評論   

# re: 一段tricky codes:函數(shù)調(diào)用的那些底層細節(jié)[未登錄] 2011-03-15 14:36 dophi

已閱  回復(fù)  更多評論   

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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| 一区二区三区四区五区视频| 国产亚洲精品bt天堂精选| 亚洲夫妻自拍| 欧美日韩一区二区视频在线观看| 欧美在线精品免播放器视频| 蜜臀a∨国产成人精品| 亚洲欧美bt| 免费一级欧美在线大片| 欧美一区二区三区免费大片| 欧美成人a∨高清免费观看| 欧美一区国产二区| 欧美激情综合亚洲一二区| 久久国产精品免费一区| 欧美精品一区二区三区高清aⅴ| 久久se精品一区精品二区| 欧美另类视频在线| 男人插女人欧美| 国产日韩欧美a| 亚洲精品一区二区三区99| 狠狠色狠色综合曰曰| 亚洲午夜视频在线观看| 99re66热这里只有精品4| 久久天堂精品| 久久精品女人| 国产精品一区二区视频| 一本综合精品| 中国亚洲黄色| 欧美精品九九99久久| 欧美激情亚洲国产| 在线国产欧美| 久久久av水蜜桃| 久久久久国产精品人| 国产精品一二三四区| 亚洲特色特黄| 亚洲欧美在线免费| 欧美午夜免费影院| 一区二区三区国产精华| 正在播放欧美一区| 欧美日韩免费看| 亚洲看片网站| 一区二区三区视频免费在线观看| 欧美国产免费| 亚洲黄色影院| 一本久久综合亚洲鲁鲁| 欧美精品激情| 99精品99久久久久久宅男| 一区二区三区四区国产| 欧美色图五月天| 亚洲性夜色噜噜噜7777| 欧美一区高清| 一区二区亚洲精品国产| 美女免费视频一区| 亚洲福利专区| 一本不卡影院| 国产精品久久久久久久9999| 亚洲一区二区在线| 久久精品人人| 亚洲国产第一| 欧美日韩精品系列| 亚洲三级免费| 国产亚洲欧美日韩日本| 麻豆成人小视频| 国产九九精品| 欧美一级久久久久久久大片| 久久久久99| 亚洲国产你懂的| 欧美成人综合在线| 日韩午夜av| 久久本道综合色狠狠五月| 国模吧视频一区| 免费在线视频一区| 亚洲另类黄色| 欧美一级网站| 极品av少妇一区二区| 欧美韩日视频| 亚洲欧美另类在线| 久久一区二区三区av| 亚洲精品网址在线观看| 欧美揉bbbbb揉bbbbb| 亚洲欧美国产不卡| 欧美国产日韩二区| 午夜视频在线观看一区二区| 经典三级久久| 欧美日韩在线影院| 性视频1819p久久| 亚洲国产综合在线| 欧美在线观看视频一区二区三区| 亚洲成在人线av| 欧美亚男人的天堂| 麻豆精品视频在线观看| 亚洲视频免费在线| 欧美激情bt| 久久久久.com| 亚洲欧美日韩久久精品| 91久久精品美女高潮| 国产精品一区二区在线| 欧美丰满高潮xxxx喷水动漫| 久久国产精品99精品国产| 亚洲精选在线| 欧美二区在线播放| 久久九九精品| 亚洲欧美中文日韩在线| 亚洲另类黄色| 在线观看91久久久久久| 国产精品欧美激情| 欧美日韩国产成人在线免费 | 亚洲精品在线观看免费| 久久国产欧美日韩精品| 一区二区三区久久网| 亚洲成人在线网站| 国产视频一区二区在线观看| 欧美少妇一区二区| 欧美精品激情在线| 美女尤物久久精品| 久久精品亚洲一区二区| 亚洲欧美成人精品| 亚洲毛片在线观看| 亚洲电影免费在线| 久久在线91| 久久久久国产一区二区三区四区 | 久久躁狠狠躁夜夜爽| 亚洲欧美激情四射在线日 | 亚洲清纯自拍| 男同欧美伦乱| 久久久亚洲高清| 午夜激情综合网| 亚洲夜间福利| 一区二区三区日韩欧美| 夜夜狂射影院欧美极品| 99视频国产精品免费观看| 99精品欧美一区| 夜色激情一区二区| 一区二区三区.www| 亚洲一区二区精品| 午夜精品久久久久久久男人的天堂 | 亚洲无限乱码一二三四麻| 日韩视频在线观看国产| 最新国产成人av网站网址麻豆| 亚洲国产成人在线| 亚洲精品视频一区二区三区| 日韩亚洲精品在线| 这里只有精品视频在线| 亚洲综合视频一区| 欧美一区成人| 久久午夜av| 欧美激情精品久久久久久大尺度 | 国产综合一区二区| ●精品国产综合乱码久久久久| 亚洲第一精品久久忘忧草社区| 伊人久久综合| 亚洲精品美女91| 一区二区三区日韩欧美精品| 午夜视频一区| 久久在线免费观看视频| 欧美国产日韩一区| 日韩亚洲欧美高清| 欧美亚洲一区二区在线| 玖玖玖国产精品| 欧美小视频在线| 国内精品**久久毛片app| 亚洲国产高清一区| 亚洲午夜精品久久| 久久都是精品| 欧美成人一品| 亚洲视频在线免费观看| 久久精品国亚洲| 欧美啪啪一区| 国内成+人亚洲| 亚洲一区二区三区乱码aⅴ| 久久久久久久999精品视频| 亚洲激情影院| 欧美呦呦网站| 欧美乱妇高清无乱码| 国产精品自拍网站| 亚洲片在线资源| 欧美一区二区三区的| 欧美国产精品| 亚洲欧美bt| 欧美日韩不卡在线| 国产一区二区三区四区五区美女| 亚洲久久一区| 久久蜜桃精品| 中文成人激情娱乐网| 免费在线观看日韩欧美| 国产婷婷色一区二区三区| 一本色道综合亚洲| 玖玖玖国产精品| 亚洲一区美女视频在线观看免费| 免费不卡亚洲欧美| 国产亚洲毛片| 亚洲一卡久久| 亚洲国产婷婷综合在线精品| 久久精品2019中文字幕| 国产精品嫩草久久久久| 亚洲最新合集| 亚洲二区视频在线|