使用结构参数从程序集中调用C++函数
Calling C++ function from assembly, with struct argument
我得到了一些意外的行为,这可能意味着我不完全理解编译器在做什么。考虑以下人为设计的程序:
#include <stdio.h>
#pragma pack(push, 1)
struct A {
unsigned short a;
unsigned short b;
explicit A() {
printf("constructn");
}
~A() {
printf("destructn");
}
};
#pragma pack(pop)
static_assert(sizeof(A) == 4, "sizeof(A) != 4");
A __stdcall f(int p1, A p2, int p3, int p4) {
printf("%08X %08X %08X %08Xn", p1, p2, p3, p4);
return p2;
}
int main() {
__asm {
push 4
push 3
push 2
push 1
call f
}
return 0;
}
上面的程序会崩溃,但如果我从struct A
中删除A()
和~A()
的定义,它就不会崩溃。这个问题与编译器认为参数在堆栈上的位置有关,在定义了构造函数的情况下,它认为它们比它们所在的位置远4个字节。如果我删除构造函数,我得到的输出是:
00000001 00000002 00000003 00000004
这正是我所期望的,然而,随着构造函数的定义,我得到了
00000002 00000003 00000004 00000000
这显然不是我所期望的。当运行前者时,函数返回RETN 0x10
,后者返回RETN 0x14
,所以看起来它认为应该有另一个参数(为什么?)。我注意到,如果我将f
更改为void
函数,它将按预期工作。那么,有人能向我解释一下发生了什么以及为什么?我已经关闭了所有优化。
在假定级别上,只有简单的值才能通过在寄存器中返回来从函数返回,因此如果需要返回更复杂的对象,编译器会将其视为向返回对象传递指针:
void f(A *return_ptr,int p1,A p2,int p3,int p4);
但是,可以进行某些优化。在您的示例中,您的类包含两个16位short,这两个16比特short可以打包为一个32位整数并返回到寄存器中。但是,如果您定义了一个自定义析构函数,则不再认为该类简单到可以进行此优化。
相关文章:
- 什么时候调用组成单元对象的析构函数
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 函数调用中参数的顺序重要吗
- OpenGL - 在抛出"__gnu_cxx::recursive_init_error"实例后终止调用?
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 在c++类上调用void函数
- 为什么 std::unique 不调用 std::sort?
- 调用专用模板时出错"no matching function for call to [...]"
- 选择要调用的构造函数
- 在内联程序集中定义函数和从 C++ 调用时出现问题
- 如何在内联程序集中调用函数时保留堆栈
- 从重载集中调用具有特定函数的函子
- 如何从gcc内联arm7程序集中调用c++成员函数
- 从程序集中调用的C++方法返回对象数据
- 使用结构参数从程序集中调用C++函数
- 我是否应该将所有对new/delete的调用集中到一个类
- 在一个程序集中从本机调用c#
- 在新托管线程中通过 C# 在混合模式程序集中调用 STL 矢量的push_back