当我从内联汇编中调用它们时,如何将参数传递给C ++函数

时间:2010-02-22 18:47:35

标签: x86 callstack argument-passing inline-assembly

所以,我希望能够从c ++ dll调用函数。 出于某些原因,我想从我的C ++代码中的__asm块中调用它们。 我的问题是:我知道在调用函数之前,我必须按函数调用约定指定的顺序在堆栈上推送它的参数。但是,我可以简单地做这样的事情:

int a=5;   
double b = 5.0;  
__asm{  
       push b 
       push a  
       call functionAddress  
}

令我担心的是,我似乎记得汇编中的标准字大小是2字节,而C ++中int的大小通常是4bytes,而double是8字节。所以,在上面的例子中,我真的推动每个变量的全部值,或者仅仅是前几个字节?如果上面的代码不正确,那么正确的方法是什么?另外,如果我们调用的函数返回一个double,那么这个值存储在哪里?我假设它不能在寄存器中,因为它只能存储32位(4字节)。对这个混乱的任何帮助将不胜感激:)

3 个答案:

答案 0 :(得分:13)

要推送双字节等8字节值,您将无法使用常规PUSH指令。并且您也不会将浮点参数(或双精度数)推送到浮点堆栈。您需要“手动”将这些胖参数放在堆栈中。例如,将π作为参数推送到函数f:

  __asm {
    FLDPI                    // load pi onto FP stack
    SUB ESP,8                // make room for double on processor stack
    FSTP QWORD PTR [ESP]     // store pi in proc stack slot (and pop from FP stack)
    CALL f
    ADD ESP,8                // clean up stack (assuming f is _cdecl)
  }

答案 1 :(得分:4)

32位x86架构自动将压入堆栈的值填充到32位。

你必须记住一些事情。如果您正在调用的函数使用__cdecl调用约定,则必须“弹出”之后推送的内容。但是,对于__stdcall函数,您不能这样做。

extern "C" int    __cdecl   function1(int, double);
extern "C" double __stdcall function2(char, char*);

int a = 5;
double b = 5.0;
int retval1;
char c = '5';
char *d = "Hello";
double retval2;

__asm {
    push b
    push a
    call function1
    add esp, 4*2 // "pop" what we pushed
    mov retval1, eax
    push d
    push c
    call function2
    mov retval2, eax
}

答案 2 :(得分:1)

通常,您会推送计算机单词的完整大小。这根据芯片而有所不同,但在32位Intel上将是4字节,在64位Intel上,将是8(取决于编译器 - Visual Studio仍然只支持IA32汇编 - 所以4个字节)。

最佳答案是查看特定编译器的文档。