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:
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
Method 2
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
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
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.
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.
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.
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.
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:
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...
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...
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 :).
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:
Then later, just modify the defines if necessary
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
Unfourtunatly at that point it has become enough overkill that using in-line ASM with either method I mentioned isn't so bad. :)