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

雁過無痕

  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>
            aaa亚洲精品一二三区| 日韩视频免费观看高清在线视频| 狠狠色2019综合网| 国产精品免费视频观看| 欧美成人dvd在线视频| 久久香蕉国产线看观看av| 午夜在线电影亚洲一区| 性欧美video另类hd性玩具| 欧美一区二区三区免费看| 欧美在线一二三| 久久精品国产77777蜜臀| 久热精品视频在线| 欧美大片在线看| 欧美日韩在线视频观看| 国产伦精品一区二区三区| 国产精品日韩在线播放| 国产日韩精品久久| 亚洲国产精品精华液2区45| 亚洲毛片视频| 午夜精品亚洲| 久久久午夜视频| 亚洲第一综合天堂另类专| 久久综合五月天婷婷伊人| 亚洲电影第1页| 亚洲婷婷免费| 久久综合电影一区| 欧美特黄一级大片| 亚洲第一精品电影| 亚洲网址在线| 免费欧美在线| 亚洲小说春色综合另类电影| 久久久久久69| 欧美日韩综合久久| 影院欧美亚洲| 欧美亚洲视频在线观看| 免费亚洲电影| 亚洲在线播放| 欧美精品v日韩精品v韩国精品v | 免费一区二区三区| 亚洲精品一区二区三区蜜桃久| 亚洲一区亚洲| 欧美二区不卡| 国产真实乱子伦精品视频| 亚洲精品乱码久久久久| 欧美一二三视频| 亚洲精品久久久蜜桃| 久久国产毛片| 国产日韩欧美一区在线| 在线亚洲伦理| 久久九九国产精品怡红院| 99re亚洲国产精品| 欧美国产精品中文字幕| 亚洲视频在线播放| 欧美午夜精品电影| 在线看片欧美| 久久精品国产精品亚洲精品| 亚洲毛片在线看| 欧美大秀在线观看| 亚洲国产高清在线| 久热精品视频在线观看| 午夜亚洲影视| 国产日韩欧美综合一区| 性欧美18~19sex高清播放| 亚洲精品乱码久久久久久久久| 久久综合久久综合这里只有精品| 国产酒店精品激情| 午夜一级久久| 午夜欧美视频| 含羞草久久爱69一区| 久久蜜桃精品| 久久午夜电影| 亚洲高清av| 亚洲经典三级| 欧美午夜寂寞影院| 欧美影院一区| 久久精品99无色码中文字幕| 黄色成人av| 欧美成人午夜影院| 欧美黄色网络| 亚洲在线一区二区| 午夜精品福利在线| 黄色精品网站| 91久久在线视频| 国产精品毛片a∨一区二区三区| 亚洲欧美国产毛片在线| 午夜精品一区二区三区电影天堂| 国产一区视频在线看| 欧美成人官网二区| 欧美午夜宅男影院在线观看| 久久er99精品| 欧美国产日韩亚洲一区| 亚洲欧美日本日韩| 久久久久久久久久看片| 99国产精品国产精品久久| 亚洲一区二区黄色| 亚洲国产精品久久精品怡红院 | 亚洲福利专区| 日韩一区二区精品视频| 国产婷婷色综合av蜜臀av| 欧美国产激情二区三区| 国产精品高清在线| 久久人人爽人人爽| 欧美日韩三级一区二区| 久久久久免费观看| 欧美国产日本韩| 久久九九99视频| 国产精品国产三级国产aⅴ9色| 久久综合亚州| 国产精品试看| 亚洲欧洲综合另类| 国产亚洲成av人在线观看导航| 亚洲欧洲精品一区二区精品久久久| 奶水喷射视频一区| 久久精品成人| 一本色道久久综合亚洲精品婷婷 | 国产曰批免费观看久久久| 亚洲国产一区二区精品专区| 国产精品爽爽ⅴa在线观看| 亚洲第一区在线| 国产一区二区精品| 亚洲视频在线观看免费| 亚洲伦理一区| 欧美wwwwww| 欧美激情91| 亚洲二区精品| 久久久久久免费| 久久精品一本久久99精品| 国产精品草莓在线免费观看| 亚洲激情在线播放| 亚洲人成在线播放| 蜜桃av一区二区三区| 久久亚洲精品一区二区| 国产欧美一区二区精品性色| 亚洲精品国精品久久99热| 伊人天天综合| 久久久久国产精品厨房| 久久久久久国产精品一区| 国产精品一区二区三区乱码| 中文一区二区在线观看| 亚洲免费伊人电影在线观看av| 欧美日韩一区高清| 亚洲免费成人| 中文在线不卡| 欧美日韩精品福利| 99re6这里只有精品| 正在播放亚洲| 欧美性猛交视频| 一本一本久久| 亚洲天堂久久| 国产伦精品一区二区三区照片91| 亚洲一区三区视频在线观看| 欧美一区影院| 国产一区二区三区在线观看精品| 性伦欧美刺激片在线观看| 久久精品91久久香蕉加勒比| 国产一区二区三区四区老人| 久久久久久久999精品视频| 免费永久网站黄欧美| 亚洲国产三级网| 欧美日韩亚洲一区二区三区| 亚洲视频自拍偷拍| 久久国产精品久久w女人spa| 国产综合自拍| 欧美高清在线视频| 亚洲电影av| 亚洲视频一区二区| 国产精品天美传媒入口| 欧美中文在线观看| 亚洲国产日韩一级| 亚洲欧美日韩综合一区| 国产一二三精品| 久久亚洲一区| 一本色道久久加勒比88综合| 欧美一区二区三区日韩视频| 黄色工厂这里只有精品| 欧美日韩亚洲免费| 欧美在线91| 亚洲免费观看高清在线观看| 亚洲第一久久影院| 亚洲免费激情| 亚洲视频在线观看视频| 国产精品伦一区| 久久久五月天| 99riav国产精品| 久久久久久亚洲精品杨幂换脸 | 免费亚洲电影| 日韩亚洲欧美一区| 免费观看亚洲视频大全| 亚洲欧美国产va在线影院| 在线观看一区视频| 国产精品剧情在线亚洲| 麻豆精品视频在线观看| 亚洲欧美日韩一区在线| 亚洲激情在线观看| 久久精品中文字幕免费mv| 一区二区电影免费观看| 在线不卡欧美| 国产一区二区高清不卡| 欧美日韩综合视频| 欧美va亚洲va香蕉在线|