c++:调用一个函数,并将不同数量的参数存储在数组中?

发布于 2024-12-23 02:28:46 字数 3960 浏览 3 评论 0原文

我有一个带有签名 double func(double,...) 的函数,并且我确信传递给 func 的所有参数都是 double 类型。所有参数都存储在一些称为参数的向量中,我只是想知道是否有方法编写通用代码以将 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;

I've got a function with signature double func(double,...) and I'm sure all the arguments I'm passing to func are type double. All arguments are stored in some a vector called arguments, I'm just wondering if there is way to write a generic code to pass any number of arguments specified in argumentVector to func?

something like :

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

so far I've tried this code but it seems to have problems:

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 a crazy result I'm getting! this code runs without any problems :

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";

while in this one arguments are not passed properly!

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";

do you have any idea why? I though both x and param were simple arrays!

--edit2--

here is the complete assembly code so far VC generates

    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;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

蝶舞 2024-12-30 02:28:46

以下内容在 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;
}

The following works in Visual Studio, but I think you can easily correct the inline assembler syntax so it fits your compiler's requirements.

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;
}
蓝礼 2024-12-30 02:28:46

根据我的具体要求,我会执行您在下面看到的这两个操作之一。使用 Assembly 将是我的选项列表中的最后一个。

操作。 1 如果所有参数都属于同一类型,为什么不只传递向量呢?它是类型安全的,并且不会像使用可变长度参数列表时那样溢出。请记住,如果您只希望函数使用向量的一部分,您也可以传递开始和结束迭代器。

操作。 2 如果您的参数属于不同类型,请使用 Boost .任意

Depending on my specific requirements, I'd do one of these two you see below. Using Assembly would be last on my list of options.

Op. 1 If all your arguments are of the same type, why not just pass the vector? It's type safe and you can't overflow like when you use variable length argument lists. Remember that you can also pass beginning and ending iterators if you only want the function to use a part of the vector.

Op. 2 If your arguments are of different types, use Boost.Any.

空心↖ 2024-12-30 02:28:46

您是否以正确的相反顺序推送这些值?

如果你有
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;")

但在执行此操作之前,请确保这确实是一种优化,而不是一个不成熟的优化。

Are you pushing the values in the correct reversed order?

If you have
void func(int a, int b, int c)

you have to do:

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

If you just want to embed assembly, and be it executed exactly as you placed it:

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;")

But before doing this, be sure that it is indeed an optimization, and not a premature one.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文