所以,我希望能够从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字节)。对这个混乱的任何帮助将不胜感激:)
答案 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个字节)。
最佳答案是查看特定编译器的文档。