Hey all.

I use ASM extensively in a lot of stuff we do at my work.  I always use the built in assembler for ease of use and speed but my main peeve is the difficulty in accessing member class variables.

Lets say I had this class:


class TClass
{
  public:
    dword m_dwVar1;
    dword m_dwVar2;
 
    void Whatever();
}


So in Whatever() I would like to write some small assembly code that uses the member variables.  So far, I know of only 2 methods of doing this:

Method 1


  void TClass::Whatever()
  {
    __asm
    {
        mov ecx, this

        // access m_dwVar1
        mov eax,

        // access m_dwVar2
        mov eax,
    }
}



Method 2

  void TClass::Whatever()
  {
    dword dwVar1 = m_dwVar1;
    dword dwVar2 = m_dwVar2;

    __asm
    {
        mov eax, dwVar1
        mov eax, dwVar2   
    }
}



As you can see both of these methods would work to get the values of var1 and 2 and with a little changes to the code, you can even write values back into them.  Would I would like to know is if there is a better more straight forward way of doing this sort of thing.

I'd like to see what others have done in these cases.

Thanks

Phred
Posted on 2005-11-09 11:13:42 by Phred
It's my personal belief that, when combining assembly and HLLs, you should only shell out to assembly when you have a fairly "costly" routine - when there's enough speed gained that pushing a couple of variables and doing a call won't be a burden.

If you find yourself in need of a lot of small-and-fast routines, a refactor of your source is probably in order; ie, rather than building a "DrawSprite" with a super-fast PutPixel routine... you should drop the putpixel mentality, and do direct pixel manipulation in DrawSprite.

Last time I tried, I couldn't come up with better ways of accessing member variables than what you have posted - vc2003 seems to turn "mov eax, m_blah" into a "mov eax, 0". Your "this + 0" and "this + 4" is extremely unmanagable, and doing copies back and forth via temps is a bit annoying...

So you'd rather see me do a call like "asm_transformvertices(m_transformedVertList, m_blueprintVertList, m_xformMatrix);" instead of implementing it with inline assembly.
Posted on 2005-11-09 12:46:10 by f0dder
Ya that is true... although I don't mind so much doing a to get to a variable so long as I make a note in the decleration that member variable order is not to be touched.... :)

Or ya... the transfer is safer and yes we need assembler for alot of our stuff... the over head of the call is reduced when I make it a fastcall and the variable transfer is peanuts compared to the main code I'm working with.
Posted on 2005-11-09 14:00:50 by Phred
http://www.ultranos.com/asm
See "ATC" there  - C++ wrapper for MASM (sorry, no inline asm). Only doesn't support inheritance of 2 or more classes at once.
You'll need to use "EnterHostedClass" and "LeaveHostedClass" - to make ATC not build constructors.
Your above code would need the following asm:

EnterHostedClass

class TClass,,C++ compatible
long m_dwVar1
long m_dwVar2
void Whatever
endclass

LeaveHostedClass


asm_TClass_Whatever proc ; usually would be TClass_Whatever
assume ecx:ptr TClass

mov eax,.dwVar1
mov eax,.dwVar2

assume ecx:nothing
ret
asm_TClass_Whatever endp


You could rename asm_TClass_Whatever to the mangled name your C++ compiler makes (the ??TClass????Whatever@0AOZD) , for it to get recognized by the linker immediately...
Posted on 2005-11-10 00:09:31 by Ultrano
That's an interesting soloution Ultrano!  But then I would have to code the whole class in MASM when I really want very few select functions written in ASM :).
Posted on 2005-11-10 07:23:33 by Phred
No no, just define the class definition, even less - only the data-members.
It's mostly copy-paste work :)
If your class has no virtual funcs, I forgot to say, it has to be "non-virtual" instead of "C++ compatible"
But classes are mostly with virtual funcs (otherwise they're usually useless).

Anyway, it's recommended to know your compiler's output, and conform to it - then you'll be perfectly sure in what you're doing with that class data in asm.

Maybe a fourth solution will be to continue in C++, but have your code like this:

#define TClass__m_dwVar1
#define TClass__m_dwVar2

class TClass{
  public:
    dword m_dwVar1;
    dword m_dwVar2;
 
    void Whatever();
}

void TClass::Whatever() {
    __asm
    {
        mov ecx, this // btw, isn't this line useless??

        mov eax,TClass__m_dwVar1
        mov eax,TClass__m_dwVar2
    }
}

//-------- class CVirtual ---------------------
#define CVirtual__var1
#define CVirtual__var2

class CVirtual{
virtual ~CVirtual();
  public:
    dword m_dwVar1;
    dword m_dwVar2;
 
    void DoIt();
}

void CVirtual::DoIt() {
    __asm
    {
        mov eax,CVirtual__var1
        add eax,CVirtual__var2
    }
}


Then later, just modify the defines if necessary
Posted on 2005-11-10 07:39:26 by Ultrano
Unfourtunatly at that point it has become enough overkill that using in-line ASM with either method I mentioned isn't so bad.  :)
Posted on 2005-11-10 07:50:21 by Phred