【发布时间】:2012-08-25 00:23:51
【问题描述】:
根据 MSDN 文档,当对类函数使用默认的 __thiscall 调用约定时,“this”指针存储在 ECX 中。尽管在翻译常规 C++ 代码时肯定会出现这种情况,但我在尝试使用内联汇编访问“this”时遇到了问题。
这是测试程序:
#include <cstdio>
class TestClass
{
long x;
public:
inline TestClass(long x):x(x){}
public:
inline long getX1(){return x;}
inline long getX2()
{
_asm
{
mov eax,dword ptr[ecx]
}
}
};
int main()
{
TestClass c(42);
printf("c.getX1() = %d\n",c.getX1());
printf("c.getX2() = %d\n",c.getX2());
return 0;
}
两个Get函数翻译如下:
?getX1@TestClass@@QAEJXZ (public: long __thiscall TestClass::getX1(void)):
00000000: 8B 01 mov eax,dword ptr [ecx]
00000002: C3 ret
?getX2@TestClass@@QAEJXZ (public: long __thiscall TestClass::getX2(void)):
00000000: 8B 01 mov eax,dword ptr [ecx]
00000002: C3 ret
我认为可以肯定地说这两个功能是相同的。然而,这是程序的输出:
c.getX1() = 42
c.getX2() = 1
当调用第二个 Get 函数时,显然“this”不存储在 ECX 中,所以我的问题是:如何确保包含内联汇编的类函数遵循调用约定和/或调用方式与常规/非内联函数相同?
编辑:主要功能是这样翻译的:
_main:
00000000: 51 push ecx
00000001: 6A 2A push 2Ah
00000003: 68 00 00 00 00 push offset $SG3948
00000008: E8 00 00 00 00 call _printf
0000000D: 83 C4 08 add esp,8
00000010: 8D 0C 24 lea ecx,[esp]
00000013: E8 00 00 00 00 call ?getX2@TestClass@@QAEJXZ
00000018: 50 push eax
00000019: 68 00 00 00 00 push offset $SG3949
0000001E: E8 00 00 00 00 call _printf
00000023: 33 C0 xor eax,eax
00000025: 83 C4 0C add esp,0Ch
00000028: C3 ret
【问题讨论】:
-
main()对应的反汇编是什么?尤其是你的函数声明为inline,你展示的汇编代码甚至不一定会被使用。 -
@Greg Hewgill:刚刚在我的帖子中插入了 main 函数的代码。
-
看起来编译器已经优化了整个对象,完全不存在了。这有点令人惊讶,因为它不知道您在
_asm块中实际在做什么。 -
尝试使构造函数not内联,看看对象构造是否仍然被优化掉。
-
@Greg Hewgill:是的,对第一个非 asm Get 函数的调用只是直接扩展内联到代码中,但第二个函数是使用 call 指令显式调用的。向函数添加内联 asm 会改变调用约定,这似乎还是有点奇怪:?
标签: c++ visual-c++ x86 this inline-assembly