【问题标题】:Accessing class members from inline assembly in Visual C++在 Visual C++ 中从内联程序集访问类成员
【发布时间】:2012-01-01 19:41:42
【问题描述】:

这是我的代码:

void Graph::PutPixel(DWORD x, DWORD y, DWORD c)
{
    __asm 
    {
        Mov Eax, y
        Mov Ebx, _width
        Mul Ebx
        Add Eax, x
        Shl Eax, 2 // Multiply by four
        Add Eax, _buffer
        Mov Edi, Eax
        Mov Eax, c
        StosD
    }
}

其中 _buffer 和 _width 是 Graph 类成员:

private:
    DWORD _width;
    DWORD* _buffer;

它不起作用;我从两个变量中得到 0 值,但实际上它们还有一些其他值。

我可以通过将类变量复制到局部变量并使用它们来修复它:

void Graph::PutPixel(DWORD x, DWORD y, DWORD c)
{
    DWORD bufAddr = (DWORD)_buffer;
    DWORD w = _width;
    __asm 
    {
        Mov Eax, y
        Mov Ebx, w
        Mul Ebx
        Add Eax, x
        Shl Eax, 2 // Multiply by four
        Add Eax, bufAddr
        Mov Edi, Eax
        Mov Eax, c
        StosD
    }
}

直接使用有什么问题?有可能吗?

【问题讨论】:

  • 您是否尝试过,在您的第一个示例中,使用Mov Ebx, ._width 等。
  • 这里有一个解决方案,还是不太方便:Mov Esi, this;移动 Ebx, [Esi]._width
  • 你应该可以做到msdn.microsoft.com/en-us/library/7y325bw3.aspx,只是不能调用类方法。
  • @Kefir 您使用this 指针的评论暗示了问题:您正在使用一个类及其成员变量。汇编器不是 C++,在汇编器中你会以最小的步骤做很多事情,所以这似乎是你的答案。该解决方案有什么不方便的地方?
  • 这似乎解决了问题...stackoverflow.com/questions/4583288/…

标签: c++ assembly inline-assembly


【解决方案1】:

如果您有一些确实需要汇编的东西(请参阅 Bo 的回答),有一篇文章 here 介绍了在内联汇编块中访问 C 或 C++ 数据。

在你的情况下,我们得到:

void Graph::PutPixel(DWORD x, DWORD y, DWORD c)
{
    __asm 
    {
        mov ecx,this
        mov Eax, y
        mov Ebx, [ecx]Graph._width //alias ecx to type 'Graph' and access member
        mul Ebx
        add Eax, x
        shl Eax, 2
        add Eax, [ecx]._buffer //access member with bound alias
        mov Edi, Eax
        mov Eax, c
        stosd
    }
}

【讨论】:

  • 您的答案似乎很旧,尽管信息很好并且仍然有效,但提供的链接不会指向任何当前材料,因此在这段时间内可能无法做更多事情。所以我会在你的答案之前添加。
【解决方案2】:

为什么首先要使用汇编?!

这不是

void Graph::PutPixel(DWORD x, DWORD y, DWORD c)
{
    __asm 
    {
        Mov Eax, y
        Mov Ebx, _width
        Mul Ebx
        Add Eax, x
        Shl Eax, 2 // Multiply by four
        Add Eax, _buffer
        Mov Edi, Eax
        Mov Eax, c
        StosD
    }
}

DWORD* ptr = ((y * _width) + x) + _buffer;
*ptr = c;

只需将c 存储在计算出的内存地址。


或者,更简单

_buffer[y * _width + x] = c;

现在我们开始讨论了!

【讨论】:

  • 我以这种方法为例。这是最简单的一种。 PutSprite 等其他方法要复杂得多,我希望将它们组装起来。事实上,我正在尝试将我的旧 DOS 游戏移植到 C++。所有的绘图方法都是用汇编编写的并在内存缓冲区上操作,所以我唯一需要改变的是我如何将内存中的图片输出到屏幕上。我想保持 asm 方法不变,只是为了好玩。
【解决方案3】:

正如上面从其他答案中所述,可以像这样使用 Visual Studio 访问内联汇编中的类或结构的成员。 如需更多信息,请访问 Microsoft 网站上的 https://docs.microsoft.com/en-us/cpp/assembler/inline/accessing-c-or-cpp-data-in-asm-blocks?view=vs-2019

// InlineAssembler_Accessing_C_asm_Blocks.cpp
// processor: x86
#include <stdio.h>
struct first_type
{
   char *weasel;
   int same_name;
};

struct second_type
{
   int wonton;
   long same_name;
};

int main()
{
   struct first_type hal;
   struct second_type oat;

   __asm
   {
      lea ebx, hal
      mov ecx, [ebx]hal.same_name ; Must use 'hal'
      mov esi, [ebx].weasel       ; Can omit 'hal'
   }
   return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-04
    相关资源
    最近更新 更多