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

雁過無痕

  C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
  弄著玩的。功能是簡單的實現函數轉發,即
      調用CALL(func),轉為調用func(),
      調用CALL(func, arg1, arg2) ,轉為調用func(arg1, arg2)

  代碼中,宏CALL/STDCALL分別用來調用  __cdecl/__stdcall 調用規定的函數
             unsafe_call 兩者都可調用,但它不是多線程安全的。

  代碼只支持x86 32位, 除內嵌匯編部分,盡量符合C++11標準。
       
原理:
     剛進入函數時,
     [esp]           函數返回地址
     [esp + 4]     第一個參數,即轉發函數的地址
     [esp + 8]     第二個參數,即轉發函數的的第一個參數
     ... 
   
      只要寫三行匯編指令實現一個c_call函數,就可調用轉發函數
      pop eax                             ; eax為函數返回地址
      xchg dword ptr[esp], eax     ; eax為轉發函數的地址,[esp]為函數返回地址
      jmp eax
     
     當轉發函數是__cdecl,即轉發函數不會調節棧,由于在c_call,pop eax,使esp多加了4,因而在調用完c_call后應該手動將esp值減4,保證棧平衡。
   
    當轉發函數是__stdcall,轉發函數會調節棧,調用轉發函數完畢后,棧已經保持平衡,因而調用c_call完畢,不應該進行棧指針調節。似乎將c_call的調用改為__stdcall即可,但實際上c_call有變長參數,改成__stdcall沒效果,每次調用編譯器還是會自動生成調節棧指針代碼。因而只能每次調用完畢,編譯器給esp加了多少,就手動減多少。(編譯器不一定會生成 call  xxxx; add esp, xx這樣的代碼,通過改函數返回地址,忽略后面的add esp, xx指令是很糟糕的做法。)
call_redirect
posted on 2012-08-05 21:02 flyinghearts 閱讀(1865) 評論(8)  編輯 收藏 引用 所屬分類: C++

評論

# re: 內嵌匯編實現的函數轉發 2012-08-06 14:02 rix
typedef int (*func_ptr)(...);
int call_fun(func_ptr func, ...);
#define PUSH __asm push 0
int call_fun(func_ptr func, ...)
{
*((int*)(&func)-1) = (*((int*)(&func)-1))^(*((int*)(&func)));
*((int*)(&func)) = (*((int*)(&func)-1))^(*((int*)(&func)));
*((int*)(&func)-1) = (*((int*)(&func)-1))^(*((int*)(&func)));
return (int)func;
}

#define START_CALL PUSH
#define END_CALL

int main (int argc, char * argv[])
{
START_CALL;
call_fun((func_ptr)func_1, 1, 2);
END_CALL;
START_CALL;
printf("func_2 return=%d\n", call_fun((func_ptr)func_2));
END_CALL;
START_CALL;
call_fun((func_ptr)func_3, "printf this:%d, %s\n", 1, "ok");
END_CALL;
return 0;
}  回復  更多評論
  

# re: 內嵌匯編實現的函數轉發[未登錄] 2012-08-06 15:31 heroboy
這樣?
template<class T,class A1>
T Call(T(*f)())
{
return f();
}

template<class T,class A1>
T Call(T(*f)(A1),A1 a)
{
return f(a);
}

template<class T,class A1,class A2>
T Call(T(*f)(A1),A1 a,A2 b)
{
return f(a,b);
}
  回復  更多評論
  

# re: 內嵌匯編實現的函數轉發 2012-08-06 21:43 flyinghearts
@rix
這個代碼顯然是錯的。
call_fun只是簡單返回 func的值而已。  回復  更多評論
  

# re: 內嵌匯編實現的函數轉發 2012-08-06 21:57 flyinghearts
@heroboy
你的模板寫錯了。

用模板優點不說了,就說說缺點吧:
如果轉發函數的參數是不定的,模板無法匹配到。
另外,類型匹配太嚴格了,若參數類型是const char*, 傳入"123"字符串都要先轉下類型,特別是參數是數字時,非要查看下參數是int還是long,還是其它的。用起來太累人。



  回復  更多評論
  

# re: 內嵌匯編實現的函數轉發 2012-08-13 12:03 rix
@flyinghearts
自己調用下就知道了。
*((int*)(&func)-1) = (*((int*)(&func)-1))^(*((int*)(&func)));
*((int*)(&func)) = (*((int*)(&func)-1))^(*((int*)(&func)));
*((int*)(&func)-1) = (*((int*)(&func)-1))^(*((int*)(&func)));
關鍵在這個交換的地方,而不是返回值。  回復  更多評論
  

# re: 內嵌匯編實現的函數轉發 2012-08-14 21:10 flyinghearts
@rix
你的做法,還是避免不了要 內嵌匯編。這個做法似乎可行,但卻存在很大問題:過于依賴于編譯器怎么優化。有些編譯器會認為那段代碼在做無意義的事,直接優化掉。你用gcc試試。

另外,交換兩個數,那樣寫法,可讀性差,效率也差,。







  回復  更多評論
  

# re: 內嵌匯編實現的函數轉發 2012-08-17 21:25 flyinghearts
@rix
你那樣寫不可取,至少要寫成下面這樣,保證不被優化掉:

void* c_call(void* func, ...)
{
typedef void* type;
const type tmp = func;
volatile type& eip = func;
volatile type& ret_addr = *(&func - 1);
eip = ret_addr;
ret_addr = tmp;
return (void*)tmp;
}

但是這樣又存在一個大問題:要保證調用這個函數時,不會被內聯,一但被內聯,bug就來了。




  回復  更多評論
  

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            ●精品国产综合乱码久久久久| 亚洲一二三区精品| 亚洲毛片在线| 亚洲人成在线观看网站高清| 亚洲人成毛片在线播放| 亚洲精品乱码久久久久久蜜桃91| 在线观看中文字幕不卡| 亚洲国产高清自拍| 亚洲深夜福利网站| 欧美一区二区三区在| 久久er99精品| 久久综合狠狠| 日韩系列欧美系列| 午夜精品婷婷| 欧美国产先锋| 欧美婷婷六月丁香综合色| 国产精品二区二区三区| 韩国美女久久| 在线视频欧美日韩精品| 久久久久久久尹人综合网亚洲| 欧美高清视频一区二区| 亚洲视频网在线直播| 久久蜜臀精品av| 欧美成人a视频| 国产欧美日韩免费| 亚洲伦理一区| 久久免费黄色| 9国产精品视频| 久久久伊人欧美| 国产精品成人一区二区网站软件 | 久久国产精品亚洲va麻豆| 亚洲福利国产| 亚洲一区国产视频| 欧美激情精品久久久久久| 国内久久婷婷综合| 午夜国产精品影院在线观看| 亚洲国产欧美一区二区三区同亚洲| 午夜国产精品视频免费体验区| 欧美精品日韩www.p站| 国产在线精品成人一区二区三区 | 久久国产精品久久久久久| 欧美精品一区三区| 欧美一区二区在线观看| 国产欧美日本一区视频| 亚洲精品影院在线观看| 久久久精品日韩欧美| 一区二区三区四区精品| 欧美精品成人91久久久久久久| 黄色亚洲免费| 久久综合国产精品| 久久精品国产免费看久久精品| 国产精品免费看| 亚洲一区二区久久| 99伊人成综合| 欧美日韩日本网| 一二三区精品福利视频| 亚洲人成在线影院| 欧美99在线视频观看| 在线精品视频一区二区| 开元免费观看欧美电视剧网站| 欧美一区二区三区四区在线观看地址 | 91久久夜色精品国产九色| 久久香蕉精品| 久久精品亚洲热| 激情成人av| 欧美aaa级| 欧美大片在线看| 野花国产精品入口| 亚洲午夜成aⅴ人片| 国产精品区二区三区日本 | 亚洲一区激情| 夜夜嗨网站十八久久| 欧美午夜片在线观看| 欧美中文字幕精品| 久久久一二三| 一本色道**综合亚洲精品蜜桃冫| 亚洲区欧美区| 欧美视频在线观看视频极品| 欧美亚洲三区| 久久精品99久久香蕉国产色戒| 激情综合色丁香一区二区| 欧美高清视频在线观看| 欧美视频一区二区三区| 久久国产手机看片| 美女在线一区二区| 亚洲午夜激情| 欧美在线播放高清精品| 亚洲破处大片| 亚洲女人小视频在线观看| 一区二区在线看| 亚洲狼人精品一区二区三区| 国产婷婷色一区二区三区| 欧美v国产在线一区二区三区| 欧美人与禽性xxxxx杂性| 亚洲视频第一页| 亚洲国产网站| 欧美日韩人人澡狠狠躁视频| 久久久久国产精品一区三寸| 免费在线成人av| 午夜视黄欧洲亚洲| 美女视频一区免费观看| 欧美一级理论片| 欧美激情视频免费观看| 久久久夜夜夜| 国产精品久久久久一区| 欧美成人午夜免费视在线看片| 国产精品国产自产拍高清av| 男人天堂欧美日韩| 国产乱码精品| 日韩视频免费观看高清完整版| 国内精品视频一区| 亚洲网站在线观看| 亚洲精品视频在线| 久久久噜噜噜久久中文字幕色伊伊| 亚洲一区在线视频| 欧美国产一区二区三区激情无套| 久久影院亚洲| 国产区在线观看成人精品| 一区二区免费在线视频| 亚洲九九爱视频| 欧美ed2k| 欧美成年人网站| 国产综合色在线视频区| 亚洲一区尤物| 亚洲欧美中日韩| 欧美视频一区二区三区…| 亚洲国产成人午夜在线一区| 韩日成人av| 久久精品国产91精品亚洲| 久久狠狠婷婷| 国产欧美精品一区二区三区介绍 | 欧美77777| 麻豆av一区二区三区久久| 国产日韩欧美在线播放不卡| 亚洲午夜精品久久久久久app| 亚洲图色在线| 国产精品国产a级| 国产精品99久久久久久有的能看| 亚洲狼人精品一区二区三区| 欧美r片在线| 最新国产成人av网站网址麻豆| 亚洲经典一区| 欧美老女人xx| 一本大道久久a久久综合婷婷| 亚洲影视在线| 国产欧美精品日韩| 久久久久国产精品一区| 免费欧美视频| 亚洲最新色图| 国产精品家教| 欧美影院在线| 欧美大片一区二区| 亚洲最新视频在线| 国产精品国产三级国产普通话三级| 亚洲欧美日韩精品久久久久| 久久久久久久久久久久久久一区 | 影音先锋日韩资源| 亚洲日本欧美| 国产手机视频精品| 久久久综合网站| 欧美大香线蕉线伊人久久国产精品| 亚洲电影观看| 国产精品v亚洲精品v日韩精品| 亚洲香蕉网站| 麻豆9191精品国产| 中文日韩在线| 国内精品伊人久久久久av一坑| 久久亚洲欧美| 99pao成人国产永久免费视频| 性xx色xx综合久久久xx| 狠狠色香婷婷久久亚洲精品| 欧美国产亚洲视频| 午夜精品久久久久久久白皮肤 | 国产精品久久久久影院亚瑟| 久久久久国产成人精品亚洲午夜| 亚洲黄网站黄| 久久久久九九视频| 亚洲少妇诱惑| 亚洲盗摄视频| 国产精品日日做人人爱| 久久综合九色综合网站| 在线视频精品一| 欧美高清在线视频| 欧美亚洲视频| 中国av一区| 亚洲高清二区| 国产一区二区日韩| 欧美亚洲成人网| 欧美黑人国产人伦爽爽爽| 久久精品免费观看| 亚洲一区免费看| 日韩视频一区| 91久久久国产精品| 老牛影视一区二区三区| 欧美一区二区三区免费观看| 亚洲人成免费| 在线电影一区| 国产一区二区三区在线免费观看 | 久久久久久亚洲精品中文字幕| 亚洲一二三区在线|