use*_*427 3 c++ assembly visual-studio-2010 visual-c++
我得到了一些意想不到的行为,这可能意味着我并不完全理解编译器在做什么.考虑以下人为的程序:
#include <stdio.h>
#pragma pack(push, 1)
struct A {
    unsigned short a;
    unsigned short b;
    explicit A() {
        printf("construct\n");
    }
    ~A() {
        printf("destruct\n");
    }
};
#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 %08X\n", p1, p2, p3, p4);
    return p2;
}
int main() {
    __asm {
        push 4
        push 3
        push 2
        push 1
        call f
    }
    return 0;
}
上述程序会崩溃,但如果我删除的定义A(),并~A()从struct A它不会.问题与编译器认为参数在堆栈上的位置有关,并且构造函数定义它认为它们比它们的位置更远4个字节.如果我删除构造函数,我得到的输出是这样的:
00000001 00000002 00000003 00000004
这是我所期望的,但是我得到了构造函数
00000002 00000003 00000004 00000000
这显然不是我的预期.当运行前者时,函数返回with RETN 0x10和后者RETN 0x14,因此看起来它认为应该有另一个参数(为什么?).我注意到如果我改成f一个void函数,它会按预期工作.那么,有人可以向我解释发生了什么,为什么?我关掉了所有的优化.
在assuembly级别,只能通过将函数返回到寄存器中来从函数返回简单值,因此如果需要返回更复杂的对象,编译器会将其视为传递指向返回对象的指针:
void f(A *return_ptr,int p1,A p2,int p3,int p4);
然而,可以进行某些优化.在您的示例中,您的类包含两个16位短路,这两个16位短路可以打包成一个32位整数并返回寄存器.但是,如果定义自定义析构函数,则该类不再被认为足够简单以执行此优化.
| 归档时间: | 
 | 
| 查看次数: | 461 次 | 
| 最近记录: |