gpt4 book ai didi

c++ - Visual C++ 内联 x86 程序集 : Accessing "this" pointer

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:08:47 26 4
gpt4 key购买 nike

根据 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].xmov 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++ 符号”。这可能会解释你如何以编译器知道的方式在内联汇编程序中访问 xx 已被访问。

关于c++ - Visual C++ 内联 x86 程序集 : Accessing "this" pointer,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12194083/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com