【发布时间】:2011-12-26 19:57:45
【问题描述】:
我有一个带有签名double func(double,...) 的函数,我确信我传递给 func 的所有参数都是双精度类型。所有参数都存储在一个称为参数的向量中,我只是想知道是否有办法编写通用代码将argumentVector中指定的任意数量的参数传递给func?
类似:
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;
——我得到了一个疯狂的结果!此代码运行没有任何问题:
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 [__real@4014000000000000 (10EB928h)]
010E1A0B fstp qword ptr [ebp-48h]
010E1A0E fld qword ptr [__real@4018000000000000 (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;
【问题讨论】:
-
你能修改
func()吗?还是你不得不在调用方做所有事情? -
我可以创建一个测试函数(就像我已经做过的那样),但最后我正在尝试使用一些库,所以我被困在客户端!
-
如果您可以访问可变参数模板,则可以通过参数包中的递归和参数准备来做到这一点。只是一个想法,因为我现在没有时间把它写成一个完整的答案。
-
可以肯定的是,使用 g++ -S -l 编译它,这样您就可以向我们展示在该函数调用中生成的程序集的其余部分,看看它是否有任何区别。
-
@ManuelFerreria 我正在使用 VC,但我已经发布了编译器生成的汇编代码
标签: c++ assembly argument-passing