AT&T 将在 Visual Studio 2017 年内联 asm
AT&T to inline asm in Visual Studio 2017
我正在尝试将使用 AT&T 语法编写的程序集从 DevC++ 项目转换为 Visual Studio 中的内联程序集。
这是我要转换的 AT&T:
void Painter::drawRectangle(int surface, int x, int y, int width, int height, int red, int green, int blue) {
asm("mov %0, %%eax":: "r" (0x004EAA90));
asm("call *%eax");
asm("mov %eax, %ecx");
asm("mov (%ecx), %eax");
asm("push %0":: "m" (blue));
asm("push %0":: "m" (green));
asm("push %0":: "m" (red));
asm("push %0":: "m" (height));
asm("push %0":: "m" (width));
asm("push %0":: "m" (y));
asm("push %0":: "m" (x));
asm("push %0":: "m" (surface));
asm("call *0x14(%eax)");
}
到目前为止我做了什么:
void _drawrectangle(int surface, int x, int y, int width, int height, int red, int green, int blue)
{
__asm
{
mov eax, 0x004eaa90
call dword ptr [eax]
mov ecx, eax
mov eax, [ecx]
push blue
push green
push red
push height
push width
push y
push x
push surface
call dword ptr [eax + 0x14]
}
}
我正在我的 DLL 中编写它,我已经将其注入到游戏中。游戏一打开就崩溃。而且我已经在 C++ 中连接了另一个绘图函数,它起作用了。
希望你能在正确的方向上帮助 me/guide 我。谢谢。
以下是如何在不使用内联汇编的情况下用 C++ 编写函数:
#ifndef _MSC_VER
/* For GCC and clang */
#undef __thiscall
#define __thiscall __attribute__((thiscall))
#endif
struct some_interface {
virtual void _unknown_0() = 0;
virtual void _unknown_4() = 0;
virtual void _unknown_8() = 0;
virtual void _unknown_C() = 0;
virtual void _unknown_10() = 0;
virtual void __thiscall drawRectangle(int surface, int x, int y,
int width, int height,
int red, int green, int blue) = 0;
};
const auto get_interface = (some_interface *(*)()) 0x4EAA90;
void
drawRectangle(int surface, int x, int y, int width, int height,
int red, int green, int blue) {
get_interface()->drawRectangle(surface, x, y, width, height,
red, green, blue);
}
您尝试翻译的代码首先调用了一个函数,该函数 returns 指向某个 class 至少定义了 6 个虚拟方法的对象的指针。然后它调用该对象的第 6 个虚方法。 some_interface
结构最低限度地重新创建 class 因此可以调用第 6 个虚拟方法。 get_interface
常量是一个函数指针,指向位于 0x4EAA90 的函数,在 C++ 中函数指针可以像函数一样使用。
以上代码generates the following assembly in GCC 8.2:
drawRectangle(int, int, int, int, int, int, int, int):
subl , %esp
movl 55472, %eax
call *%eax
movl (%eax), %edx
movl %eax, %ecx
pushl 44(%esp)
pushl 44(%esp)
pushl 44(%esp)
pushl 44(%esp)
pushl 44(%esp)
pushl 44(%esp)
pushl 44(%esp)
pushl 44(%esp)
call *20(%edx)
addl , %esp
ret
和 following assembly with Visual C++ 2017:
void drawRectangle(int,int,int,int,int,int,int,int) PROC ; drawRectangle, COMDAT
mov eax, 5155472 ; 004eaa90H
call eax
push DWORD PTR _blue$[esp-4]
mov ecx, eax
push DWORD PTR _green$[esp]
mov edx, DWORD PTR [eax]
push DWORD PTR _red$[esp+4]
push DWORD PTR _height$[esp+8]
push DWORD PTR _width$[esp+12]
push DWORD PTR _y$[esp+16]
push DWORD PTR _x$[esp+20]
push DWORD PTR _surface$[esp+24]
call DWORD PTR [edx+20]
ret 0
void drawRectangle(int,int,int,int,int,int,int,int) ENDP ; drawRectangle
我正在尝试将使用 AT&T 语法编写的程序集从 DevC++ 项目转换为 Visual Studio 中的内联程序集。
这是我要转换的 AT&T:
void Painter::drawRectangle(int surface, int x, int y, int width, int height, int red, int green, int blue) {
asm("mov %0, %%eax":: "r" (0x004EAA90));
asm("call *%eax");
asm("mov %eax, %ecx");
asm("mov (%ecx), %eax");
asm("push %0":: "m" (blue));
asm("push %0":: "m" (green));
asm("push %0":: "m" (red));
asm("push %0":: "m" (height));
asm("push %0":: "m" (width));
asm("push %0":: "m" (y));
asm("push %0":: "m" (x));
asm("push %0":: "m" (surface));
asm("call *0x14(%eax)");
}
到目前为止我做了什么:
void _drawrectangle(int surface, int x, int y, int width, int height, int red, int green, int blue)
{
__asm
{
mov eax, 0x004eaa90
call dword ptr [eax]
mov ecx, eax
mov eax, [ecx]
push blue
push green
push red
push height
push width
push y
push x
push surface
call dword ptr [eax + 0x14]
}
}
我正在我的 DLL 中编写它,我已经将其注入到游戏中。游戏一打开就崩溃。而且我已经在 C++ 中连接了另一个绘图函数,它起作用了。
希望你能在正确的方向上帮助 me/guide 我。谢谢。
以下是如何在不使用内联汇编的情况下用 C++ 编写函数:
#ifndef _MSC_VER
/* For GCC and clang */
#undef __thiscall
#define __thiscall __attribute__((thiscall))
#endif
struct some_interface {
virtual void _unknown_0() = 0;
virtual void _unknown_4() = 0;
virtual void _unknown_8() = 0;
virtual void _unknown_C() = 0;
virtual void _unknown_10() = 0;
virtual void __thiscall drawRectangle(int surface, int x, int y,
int width, int height,
int red, int green, int blue) = 0;
};
const auto get_interface = (some_interface *(*)()) 0x4EAA90;
void
drawRectangle(int surface, int x, int y, int width, int height,
int red, int green, int blue) {
get_interface()->drawRectangle(surface, x, y, width, height,
red, green, blue);
}
您尝试翻译的代码首先调用了一个函数,该函数 returns 指向某个 class 至少定义了 6 个虚拟方法的对象的指针。然后它调用该对象的第 6 个虚方法。 some_interface
结构最低限度地重新创建 class 因此可以调用第 6 个虚拟方法。 get_interface
常量是一个函数指针,指向位于 0x4EAA90 的函数,在 C++ 中函数指针可以像函数一样使用。
以上代码generates the following assembly in GCC 8.2:
drawRectangle(int, int, int, int, int, int, int, int):
subl , %esp
movl 55472, %eax
call *%eax
movl (%eax), %edx
movl %eax, %ecx
pushl 44(%esp)
pushl 44(%esp)
pushl 44(%esp)
pushl 44(%esp)
pushl 44(%esp)
pushl 44(%esp)
pushl 44(%esp)
pushl 44(%esp)
call *20(%edx)
addl , %esp
ret
和 following assembly with Visual C++ 2017:
void drawRectangle(int,int,int,int,int,int,int,int) PROC ; drawRectangle, COMDAT
mov eax, 5155472 ; 004eaa90H
call eax
push DWORD PTR _blue$[esp-4]
mov ecx, eax
push DWORD PTR _green$[esp]
mov edx, DWORD PTR [eax]
push DWORD PTR _red$[esp+4]
push DWORD PTR _height$[esp+8]
push DWORD PTR _width$[esp+12]
push DWORD PTR _y$[esp+16]
push DWORD PTR _x$[esp+20]
push DWORD PTR _surface$[esp+24]
call DWORD PTR [edx+20]
ret 0
void drawRectangle(int,int,int,int,int,int,int,int) ENDP ; drawRectangle