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

雁過無痕

  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 閱讀(1856) 評論(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>
            毛片一区二区| 黑人一区二区三区四区五区| 亚洲无吗在线| 一区二区三区四区国产| 一本久久a久久精品亚洲| 99精品热视频只有精品10| 一区二区三区不卡视频在线观看| 一本久久精品一区二区| 宅男在线国产精品| 欧美一级大片在线免费观看| 欧美一区二区三区久久精品| 午夜激情一区| 亚洲精品久久久一区二区三区| 久久久福利视频| 久久精品成人一区二区三区蜜臀| 久久久久久久综合| 欧美电影免费观看高清| 日韩亚洲欧美在线观看| 午夜在线一区| 欧美激情 亚洲a∨综合| 国产精品99一区二区| 国产午夜精品视频免费不卡69堂| 亚洲国产高清一区二区三区| 亚洲天堂成人| 欧美xx视频| 亚洲免费视频成人| 欧美顶级艳妇交换群宴| 国产日产亚洲精品| 99国产精品99久久久久久粉嫩| 欧美在线精品免播放器视频| 亚洲国产精品精华液2区45| 亚洲欧美成aⅴ人在线观看| 久久亚洲图片| 国产欧美精品日韩区二区麻豆天美 | 国产亚洲一区二区在线观看| 亚洲韩国日本中文字幕| 亚洲欧美日韩天堂| 亚洲国产成人av在线| 欧美一区二区三区免费大片| 欧美日韩成人一区二区| 亚洲第一精品夜夜躁人人爽| 欧美一区二区视频在线观看2020 | 麻豆九一精品爱看视频在线观看免费| 欧美三级电影一区| 亚洲激情六月丁香| 玖玖玖国产精品| 亚洲欧美一区二区三区在线| 欧美色欧美亚洲另类二区| 日韩午夜在线观看视频| 欧美国产免费| 老色鬼久久亚洲一区二区| 国内精品视频久久| 久久爱另类一区二区小说| 亚洲午夜精品久久久久久app| 欧美精品在线观看91| 亚洲精品乱码久久久久久日本蜜臀 | 久久一区二区三区四区| 国产欧美日韩麻豆91| 亚洲女爱视频在线| 一区二区三区黄色| 欧美性猛片xxxx免费看久爱 | 久久视频在线看| 国产日产精品一区二区三区四区的观看方式| 亚洲精品日产精品乱码不卡| 亚洲国产精品久久久久秋霞影院 | 亚洲精品视频免费| 亚洲电影成人| 欧美国产视频在线| 99ri日韩精品视频| 亚洲精品资源| 国产精品久久久久久福利一牛影视| 亚洲调教视频在线观看| 一区二区三区四区五区在线| 国产精品免费区二区三区观看| 亚洲欧美精品一区| 亚洲影视九九影院在线观看| 国产毛片一区二区| 久久亚洲风情| 欧美激情一区二区三区高清视频| 亚洲午夜精品久久| 欧美一区国产在线| 最新亚洲视频| 中文精品99久久国产香蕉| 国产欧美精品久久| 米奇777超碰欧美日韩亚洲| 美女精品在线| 亚洲在线视频观看| 久久精品欧美日韩精品| 日韩午夜在线观看视频| 亚洲欧美成人一区二区在线电影| 国内精品久久国产| 亚洲精品久久久久久久久久久久| 欧美性猛交99久久久久99按摩| 久久久久久久999| 欧美精品午夜| 久久麻豆一区二区| 欧美精品www| 久久久久国产精品www| 欧美精品大片| 久久精品国产亚洲高清剧情介绍| 欧美777四色影视在线| 午夜欧美不卡精品aaaaa| 久热成人在线视频| 午夜一区在线| 欧美激情一区在线观看| 久久久久9999亚洲精品| 欧美日韩调教| 欧美激情精品久久久| 国产欧美日韩在线播放| 亚洲乱码国产乱码精品精| 激情欧美丁香| 亚洲一级片在线看| 日韩视频精品在线| 久久国产精品一区二区三区| 亚洲午夜精品国产| 欧美福利视频一区| 老司机精品福利视频| 国产精品手机视频| 亚洲精品一区二| 欧美高清不卡在线| 亚洲国产毛片完整版| 香蕉成人久久| 亚洲一区中文| 欧美日韩国产在线看| 蜜臀av性久久久久蜜臀aⅴ四虎| 国产精品久久97| av成人国产| 亚洲一区二区免费看| 欧美日韩一本到| 亚洲精品久久久久久久久久久| 亚洲高清视频在线| 久久综合狠狠| 免费在线看成人av| 一区二区三区无毛| 久久亚洲精选| 亚洲成色999久久网站| 亚洲黄色有码视频| 欧美福利视频一区| 日韩一区二区高清| 亚洲性视频网址| 国产精品久久久久久福利一牛影视 | 亚洲日本免费| 亚洲人成人99网站| 欧美成人午夜视频| 亚洲欧洲一区| 亚洲一区二区成人| 国产精品成人一区二区艾草| 亚洲天堂av在线免费| 久久av红桃一区二区小说| 国产欧美1区2区3区| 欧美在线亚洲综合一区| 久久永久免费| 亚洲精品小视频在线观看| 欧美日韩国产综合视频在线观看| 在线视频日本亚洲性| 久久久久91| 亚洲美女免费视频| 国产精品九色蝌蚪自拍| 欧美一区二区在线看| 亚洲成人自拍视频| 亚洲欧美激情一区二区| 激情综合久久| 欧美破处大片在线视频| 亚洲欧美成人一区二区三区| 欧美成年视频| 99精品久久久| 国产一区二区剧情av在线| 免费在线亚洲| 亚洲一区高清| 欧美韩日精品| 欧美亚洲一区二区在线观看| 激情国产一区二区| 欧美精品亚洲| 欧美在线观看一区二区三区| 亚洲国产日韩一级| 欧美中文字幕| 夜夜嗨av一区二区三区| 国产亚洲福利社区一区| 欧美激情女人20p| 欧美在线国产精品| 日韩香蕉视频| 亚洲福利视频一区| 久久久久国产一区二区三区四区| 夜夜精品视频| 亚洲国内高清视频| 国产亚洲欧美色| 欧美日韩国产综合网| 亚洲人体大胆视频| 麻豆精品在线视频| 亚洲男人的天堂在线| 亚洲电影观看| 久久久精品欧美丰满| 亚洲欧美精品在线| 亚洲日韩成人| 伊人久久综合97精品| 国产视频亚洲| 国产精品夜色7777狼人| 欧美日韩精品久久久| 欧美精品久久久久久久久久| 久久综合亚州|