Visual studio 美国电话电报公司;T到Visual Studio 2017中的内联asm

Visual studio 美国电话电报公司;T到Visual Studio 2017中的内联asm,visual-studio,assembly,inline-assembly,att,dll-injection,Visual Studio,Assembly,Inline Assembly,Att,Dll Injection,我正在尝试将用AT&T语法编写的程序集从DevC++项目转换为VisualStudio中的内联程序集 这是我试图转换的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

我正在尝试将用AT&T语法编写的程序集从DevC++项目转换为VisualStudio中的内联程序集

这是我试图转换的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++中钩住了另一个绘图函数,它工作了。
希望你能帮助我/指引我走向正确的方向。谢谢。

这里,您可以在C++中使用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);
}
您试图翻译的代码首先调用一个函数,该函数返回指向至少定义了6个虚拟方法的某个类对象的指针。然后调用该对象的第六个虚拟方法。
some_接口
struct最小限度地重新创建该类,以便可以调用第六个虚拟方法。<代码> GETIOFFIGION/CODEX>常量是指向函数位于0x4eAA90的函数指针,C++函数指针可以像函数一样使用。 上述代码:


下面是如何在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);
}
您试图翻译的代码首先调用一个函数,该函数返回指向至少定义了6个虚拟方法的某个类对象的指针。然后调用该对象的第六个虚拟方法。
some_接口
struct最小限度地重新创建该类,以便可以调用第六个虚拟方法。<代码> GETIOFFIGION/CODEX>常量是指向函数位于0x4eAA90的函数指针,C++函数指针可以像函数一样使用。 上述代码:



mov-eax,ecx
可能应该是
mov-eax,[ecx]
。为什么要翻转参数的推送顺序?在任何看起来只有两个函数调用的情况下,为什么需要对其进行汇编?这两个调用都不应该使用内联汇编。只要使用普通汇编,就不必担心第一个示例中的代码会中断,因为您使用的内联汇编代码是错误的。或者像杰斯特所说的,普通C++也会工作。@ 500内部服务器错误,忘记在测试后切换订单。除非你幸运,并且原始代码已经被编译并编译为<代码> -fNO省略帧指针< /C>,因为你在不告诉编译器的情况下处理堆栈指针。ecx可能应该是
mov-eax,[ecx]
。为什么要翻转参数的推送顺序?在任何看起来只有两个函数调用的情况下,为什么需要对其进行汇编?这两个调用都不应该使用内联汇编。只要使用普通汇编,就不必担心第一个示例中的代码会中断,因为您使用的内联汇编代码是错误的。或者像杰斯特所说,普通C++也会工作。@ 500内部服务器错误,忘记在测试后切换订单。除非你幸运,并且编译了<<代码> -fNO省略帧指针< /代码>,否则原始代码已经被破解,因为你在不告诉编译器的情况下操作堆栈指针。谢谢你能不能请你详细说明一下你是如何看到界面中至少有6个虚拟功能的?我也不明白在0-4-8-C计数到10@SornNaserZupanicMaksumic在十六进制C+4=10中。您如何知道它是对象中的函数而不是变量?此外,如果您有时间,即使不建议这样做:您将如何在内联汇编中编写它?包括保存和加载寄存器。我一直在玩godbolt生产的VS2017代码,但运气不好。只是好奇,太好了。谢谢你能不能请你详细说明一下你是如何看到界面中至少有6个虚拟功能的?我也不明白在0-4-8-C计数到10@SornNaserZupanicMaksumic在十六进制C+4=10中。您如何知道它是对象中的函数而不是变量?此外,如果您有时间,即使不建议这样做:您将如何在内联汇编中编写它?包括保存和加载寄存器。我一直在玩godbolt生产的VS2017代码,但运气不好。只是好奇。
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