根据 MSDN 文档,“this”指针在使用默认 __thiscall 时存储在 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
最佳答案
我不知道你是误读了文档,还是
它写得不好,但是__thiscall
确实不意味着this
指针存储在ECX中;这意味着指向对象的指针是
通过 ECX。在更大的功能中,我看到它从一个
在函数的不同地方注册到另一个,并且在一些
案例,我已经看到它溢出到内存中。你不能指望它在
ECX。并且它的位置可以根据中的其他代码而改变
函数,以及传递给编译器的优化标志。
在您的情况下,由于您的
函数是内联的,并且可能已经内联。 (除了那个
_asm
可能会抑制内联。)常量传播(一种非常简单且
广泛使用的优化技术)几乎肯定意味着你的
调用 c.getX1()
将只使用 42
,没有函数调用,也没有
访问 c
任何东西。
总的来说,内联汇编是一个棘手的问题,正是因为你 不知道编译器使用的是什么寄存器。通常,在 除了实际的汇编程序指令外,还会有指令 告诉编译器诸如哪些寄存器和哪些变量你 使用,您将能够在 汇编程序和其他此类信息。除非你使用这些,否则你可以 对内联汇编程序的假设非常非常少。
但是每个编译器都有自己的规则。通常具有特殊语法。
例如 mov eax, [cx].x
或 mov eax, x
可能是
Microsoft 内联汇编程序需要什么。无论如何,没有办法
根据您所写的内容,编译器可能会推断出
您正在访问 c.x
。由于所有其他用途都已被淘汰
通过不断传播,这将是一个非常糟糕的编译器,甚至
生成了一个变量c
。
编辑:
FWIW:Microsoft 内联汇编程序的文档位于
http://msdn.microsoft.com/en-us/library/4ks26t93%28v=vs.71%29.aspx .我
没有详细看过,但是有一节是关于“使用 C 或
__asm block 中的 C++ 符号”。这可能会解释你如何
以编译器知道的方式在内联汇编程序中访问 x
x
已被访问。
关于c++ - Visual C++ 内联 x86 程序集 : Accessing "this" pointer,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12194083/