2011-12-26 71 views
0

我有一個簽名爲double func(double,...)的函數,我確定我傳遞給func的所有參數都是double類型的。所有參數都存儲在一個名爲arguments的向量中,我只是想知道是否有辦法編寫一個通用代碼來將argumentVector中指定的任意數量的參數傳遞給func?C++:調用與數組中存儲的各種參數的函數?

類似:

for (int i=0;i<agumentVector.size();i++) 
    pushstack(argumentVector[i]); 
res = call(func); 

到目前爲止,我已經試過這個代碼,但它似乎有問題:

double* param = &argumentVector[0]; 

for(int i=0;i<argumentVector.size();i++) 
{ 
    _asm sub   esp,8; 
    _asm fld   param; 
    _asm fstp  qword ptr [esp]; 
    param++; 

} 
_asm call  func; 
_asm add   esp,10h; 
_asm fstp  qword ptr res; 

--just一個瘋狂的結果我得到!此代碼運行沒有任何問題:

double x[2] = {5,6}; 
double *param = x; 
double res; 

    _asm sub   esp,8; 
    _asm fld   x; 
    _asm fstp  qword ptr [esp]; 
    _asm sub   esp,8; 
    _asm fld   x+8; 
    _asm fstp  qword ptr [esp]; 
    param++; 
_asm call  p; 
_asm add   esp,10h; 
_asm fstp  qword ptr res; 

cout << res << "\n"; 

而在這一個參數不能正確傳遞!

double x[2] = {5,6}; 
double *param = x; 
double res; 

    _asm sub   esp,8; 
    _asm fld   param; 
    _asm fstp  qword ptr [esp]; 
    _asm sub   esp,8; 
    _asm fld   param+8; 
    _asm fstp  qword ptr [esp]; 
    param++; 
_asm call  p; 
_asm add   esp,10h; 
_asm fstp  qword ptr res; 

cout << res << "\n"; 

你知道爲什麼嗎?我雖然x和param都是簡單的數組!

--edit2--

這裏是完整的彙編代碼到目前爲止VC產生

double x[2] = {5,6}; 
010E1A05 fld   qword ptr [[email protected] (10EB928h)] 
010E1A0B fstp  qword ptr [ebp-48h] 
010E1A0E fld   qword ptr [[email protected] (10EB878h)] 
010E1A14 fstp  qword ptr [ebp-40h] 
    double *param = x; 
010E1A17 lea   eax,[ebp-48h] 
010E1A1A mov   dword ptr [ebp-54h],eax 
    double res; 
    p(param[0],param[1]); 
010E1A1D mov   esi,esp 
010E1A1F mov   eax,dword ptr [ebp-54h] 
010E1A22 sub   esp,8 
010E1A25 fld   qword ptr [eax+8] 
010E1A28 fstp  qword ptr [esp] 
010E1A2B mov   ecx,dword ptr [ebp-54h] 
010E1A2E sub   esp,8 
010E1A31 fld   qword ptr [ecx] 
010E1A33 fstp  qword ptr [esp] 
010E1A36 call  dword ptr [ebp-14h] 
010E1A39 fstp  st(0) 
010E1A3B add   esp,10h 
010E1A3E cmp   esi,esp 
010E1A40 call  @ILT+795(__RTC_CheckEsp) (10E1320h) 

    { 
     _asm sub   esp,8; 
010E1A45 sub   esp,8 
     _asm fld   param+8; 
010E1A48 fld   dword ptr [ebp-4Ch] 
     _asm fstp  qword ptr [esp]; 
010E1A4B fstp  qword ptr [esp] 

     _asm sub   esp,8; 
010E1A4E sub   esp,8 
     _asm fld   param; 
010E1A51 fld   dword ptr [ebp-54h] 
     _asm fstp  qword ptr [esp]; 
010E1A54 fstp  qword ptr [esp] 

    } 
    _asm call  p; 
010E1A57 call  dword ptr [ebp-14h] 
    _asm add   esp,10h; 
010E1A5A add   esp,10h 
    _asm fstp  qword ptr res; 
010E1A5D fstp  qword ptr [ebp-64h] 

    cout << res << "\n"; 
010E1A60 push  offset string "\n" (10EB834h) 
010E1A65 mov   esi,esp 
010E1A67 sub   esp,8 
010E1A6A fld   qword ptr [ebp-64h] 
010E1A6D fstp  qword ptr [esp] 
010E1A70 mov   ecx,dword ptr [__imp_std::cout (10EF3A8h)] 
010E1A76 call  dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (10EF3ACh)] 
010E1A7C cmp   esi,esp 
010E1A7E call  @ILT+795(__RTC_CheckEsp) (10E1320h) 
010E1A83 push  eax 
010E1A84 call  std::operator<<<std::char_traits<char> > (10E1294h) 
010E1A89 add   esp,8 
    return 0; 
+0

你可以修改'func()'還是你堅持不得不在主叫方做所有事情? – 2011-12-26 20:12:42

+0

我可以創建一個測試函數(正如我已經做的那樣),但最終我試圖與一些庫一起工作,所以我被困在客戶端! – Ali1S232 2011-12-26 20:16:46

+0

如果您有權訪問可變參數模板,則可以在參數包中使用遞歸和參數準備來執行此操作。只是一個想法,因爲我現在沒有時間把它寫成一個完整的答案。 – Xeo 2011-12-26 20:39:41

回答

1

以下工作在Visual Studio中,但我認爲您可以輕鬆地更正內聯彙編語法,以便它符合編譯器的要求。

double variadicDoubleFunc(double, ...) 
{ 
} 

double callVariadicDoubleFunc(double * doubles, unsigned int numDoubles) 
{ 
    // sizeof(double) must be 8! 
    if (numDoubles == 0) 
     return 0.0; 
    double * lastDouble = doubles + (numDoubles - 1); 
    double result = 0.0; 

    __asm mov eax, numDoubles 
    __asm mov edx, lastDouble 
    __asm push esi 
    __asm mov esi, esp 
    __asm and esp, 0xFFFFFFC0 

    __asm label_loop: 
    __asm sub esp, 8 
    __asm fld qword ptr [edx] 
    __asm fstp qword ptr [esp] 
    __asm sub edx, 8 
    __asm sub eax, 1 
    __asm test eax, eax 
    __asm jnz label_loop 

    __asm call variadicDoubleFunc 
    __asm fstp qword ptr result 
    __asm mov esp, esi 
    __asm pop esi 

    return result; 
} 
+0

到目前爲止最好的答案但是當我將它複製到我的代碼中後,它無法正常運行,首先讓事情變得有點混亂的是'move ebp,esp',另一個在程序結束時,我只是改變了它們位置。現在只有兩個參數中的一個可以通過 – Ali1S232 2011-12-26 21:37:11

+0

我想幫助你,但我不明白爲什麼'移動ebp,esp'會阻止代碼正常運行...另外,當你「改變了他們的立場」? (附註:asm代碼中有一些小錯誤,現在就修正它。) – Baltram 2011-12-26 21:50:29

+0

我終於讓你的代碼適合我了!我編輯了您的答案以添加所有更改!但任何方式感謝幫助。並請告訴我如果我不知道它做錯了什麼!我不知道任何程序集,只是使用VC調試器,我已經達到了該代碼! – Ali1S232 2011-12-26 22:00:52

0

你是否在正確的逆轉爲了推動價值?

如果你有 void func(int a, int b, int c)

你要做的:

push c 
push b 
push a 
call func 
add esp, 4*3 

如果你只是想嵌入彙編,並就執行完全一樣,你把它放在:

for(int i=0;i<argumentVector.size();i++) 
{ 
    parm++; 
    __asm__ __volatile__ ( 
         "sub   esp,8;" 
         "fld   parm;" 
         "fstp  qword ptr [esp]") 

} 
__asm__ __volatile__ ("call  func;" 
         "add   esp,10h;" 
         "fstp  qword ptr res;") 

但在做這件事之前,確保它確實是一種優化,而不是過早。

+0

問題是當我在for內部使用匯編代碼時代碼中斷。順便說一下,數字順序之間沒有區別,到目前爲止,我只是試圖將它們全部相乘(後來我會更正它) – Ali1S232 2011-12-26 20:10:41

0

根據我的具體要求,我會做下面你看到的這兩個之一。使用大會將是我的選項清單上的最後一個。

Op。 1如果所有的參數都是相同的類型,爲什麼不傳遞向量?它是類型安全的,當你使用可變長度參數列表時,你不會溢出。請記住,如果您只希望函數使用矢量的一部分,則還可以傳遞開始和結束迭代器。

Op。 2如果您的論點類型不同,請使用Boost.Any

+0

沒有這些是我的選擇,因爲我試圖用這個預定義功能。我可以確保我傳遞了正確數量的參數,並且我知道所有參數都是double類型。但我可能會用各種參數調用這個函數! – Ali1S232 2011-12-26 20:14:29