Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing class members from inline assembly in Visual C++

Here is my code:

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
    }
}

Where _buffer and _width are Graph class members:

private:
    DWORD _width;
    DWORD* _buffer;

It does not work; I get 0 value from both variables, but they have some other values in fact.

I can fix it by copying class variables to local variables and using them:

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
    }
}

What's the problem with direct usage? Is it possible?

like image 345
Pavel Tupitsyn Avatar asked Nov 19 '11 07:11

Pavel Tupitsyn


2 Answers

On the off chance that you have something that really does need assembly (see Bo's answer), there is an article here on accessing C or C++ data in inline assembly blocks.

In your case we get:

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
    }
}
like image 113
Necrolis Avatar answered Sep 23 '22 09:09

Necrolis


Why use assembly in the first place?!

Isn't this

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
    }
}

the same as

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

Just storing c at a computed memory address.


Or, even simpler

_buffer[y * _width + x] = c;

Now we're talking!

like image 40
Bo Persson Avatar answered Sep 23 '22 09:09

Bo Persson