#### Archived

This topic is now archived and is closed to further replies.

# accessing member vars in assembly

This topic is 5572 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

In a member function, why isn't it possible to access meber variables directly? for instance: void someclass::foor() { __asm mov ebx,m_iVariable } do I have to do this:? void someclass::foor() { int iVar = iVariable; __asm mov ebx,iVar } If you can't tell, I'm new to assembly Oh yea, one other thing while I'm asking newbie questions. I have this code: double distx = 5.0; double radius; __asm { mov ax, distx mov cx, ax // error C2443: operand size conflict mul cx mov ax, bx mov radius, bx } Which gives me the error on the line above. Why is this? [edited by - Mulligan on September 9, 2002 7:15:30 PM]

##### Share on other sites
When you access member variables in c++ code, you''re implicitly accessing them through the this pointer. My guess is that you need to do that explicitly in the assembly code. I think the syntax is:

__asm mov ebx, someclass PTR [this].m_iVariable

##### Share on other sites
That answers that, thanks. Now how bout the second question?

##### Share on other sites

I think the error you are getting is not on the line you indicated, but on the line above. You are trying to assign a double value to a 16-bit integer register. Obviously this will not work.

try something like this (may not compile! use as an example and go look it up )

double distx = 5.0;double radius;__asm{    fld [distx]    fmul [distx]    fstp [radius]}

There are different types of registers in the cpu. Some store whole integer value, some store floating point (fractional) values. Your code was trying to assign a fractional value to an integer register. For more information, go to the developers section on the intel web site and download a few manuals.

[edited by - Jx on September 10, 2002 8:48:15 AM]

##### Share on other sites
Oh ok, I think I''m begining to get a grip on things now. Thanks!

##### Share on other sites
quote:
Original post by Mulligan
Oh yea, one other thing while I''m asking newbie questions. I have this code:

double distx = 5.0;
__asm
{
mov ax, distx
mov cx, ax // error C2443: operand size conflict
mul cx
mov ax, bx

}

Which gives me the error on the line above. Why is this?

As far as I can remember, cx is an 16 bit register. Try replacing cx with ecx( as ecx is supposed to be the 32 bit equivalent of cx ). I''m a bit rusty in assembler...
That should work for you though...

at mutedfaith.com.
<º>

Cyberdrek

##### Share on other sites
I always wanted to know how you determined which register to use in assembly. That part always confused me.

##### Share on other sites
quote:
Original post by daerid
I always wanted to know how you determined which register to use in assembly. That part always confused me.

use eax, ebx, ecx, edx when storing 32 bit values

use ax, bx, cx, dx when storing 16 bit values

use ah, al etc when storing 8 bit values

use MM0 - MM7 for MMX registers

use XMM0 - XMM7 for SSE registers

use ST0 - ST7 for FPU registers

use ebp and esp to access the stack

use eip rarely it is the instruction pointer

use ds, es, fs, gs when you need segments in 16bit code or as a segment selector in 32bits. you shouldn''t need to play with these at all really

There are a few other registers which are special so I won''t go into them here...

When deciding, just pick which data type you need really. Of course, if you perform an instruction using EAX it affects AX, AH and AL because AX is actually just the lower 16 bits of EAX. AH is the higher 8 bits of AX, and AL is the lower 8 bits of AX.

Phew.. hope that gets the point across

##### Share on other sites
Thanks, explained much. Now I can do floating point arithmitic on 'float's but not 'double's. Any bigger better registers for that?
Anyway, this compiles bacause i changed everything to 'float':
__asm
{
mov eax, distx
mov ebx, eax
mul ecx
mov ebx, eax

mov eax, disty
mov ecx, eax
mul ecx

mov eax, distz
mov ecx, eax
mul ecx

}

this block represents the C++ form of this:
dRadius = distx*distx + distz*distz + disty*disty;

...but it doesn't work. I'm still an seembly idiot, so let into me if im doing really stupid mistakes.

One last question, which may answer the question above, when I execute the command "mul eax" which registers are multiplied? The result is left in eax, correct?

[edited by - Mulligan on September 11, 2002 11:22:53 PM]

##### Share on other sites
I belive i see your problem (assuming that was a copy and paste)
in the first block you are moving eax into ebx but then mul eax by ecx, which is either gonna be zero or a random value depending

also, as a side note, isnt it good practise with asm routines to push onto the stack any registers you plan on using and then poping them off at the end, as the process or is probably using ''em to hold data

##### Share on other sites
quote:
Original post by _the_phantom_
I belive i see your problem (assuming that was a copy and paste)
in the first block you are moving eax into ebx but then mul eax by ecx, which is either gonna be zero or a random value depending

also, as a side note, isnt it good practise with asm routines to push onto the stack any registers you plan on using and then poping them off at the end, as the process or is probably using ''em to hold data

Yeah, normally it is good practice - but... in the VC++ help files it says (and i know these are not to be taken as gospel) that certain registers can be used without saving and restoring them. Obviously I know that under certain conditions, this does not hold true, but for his case i''m sure it''s fine.

##### Share on other sites
quote:
Original post by Mulligan
Thanks, explained much. Now I can do floating point arithmitic on 'float's but not 'double's. Any bigger better registers for that?
Anyway, this compiles bacause i changed everything to 'float':
__asm
{
mov eax, distx
mov ebx, eax
mul ecx
mov ebx, eax

mov eax, disty
mov ecx, eax
mul ecx

mov eax, distz
mov ecx, eax
mul ecx

}

this block represents the C++ form of this:
dRadius = distx*distx + distz*distz + disty*disty;

...but it doesn't work. I'm still an seembly idiot, so let into me if im doing really stupid mistakes.

One last question, which may answer the question above, when I execute the command "mul eax" which registers are multiplied? The result is left in eax, correct?

[edited by - Mulligan on September 11, 2002 11:22:53 PM]

Ok - you are still missing the point. If you look at the numbers you are using, they are decimal values - regardless of wether they are doubles or floats. These values _cannot_ be stored in EAX, EBX, ECX etc etc. They can only be stored in the floating point unit's registers which I have already mentioned are ST0 - ST7 (or something similar at least).

The registers EAX, EBX, ECX etc can only be used for storing whole numbers like 4, 32, 65536 etc etc. The floating point registers are used for holding values like 3.14159, -0.910192 etc.

So....

Going back to my first answer - i'll comment the code a little more:

double distx = 5.0;double radius;__asm{         fld [distx]              ; this line loads your distx into ST0     fmul [distx]             ; this line multiplies distx by ST0 - or effectively, by itself - and stores the result back into ST0     fstp [radius]            ; this line takes the result from ST0 and puts it into radius     }

Do you see?

Also - you can tell i'm using floating point instructions because they are all prefixed by the letter "f". For example "fmul" as opposed to the "mul" instruction you are using.

I thank the others for trying to help you, but the reason that your code doesn't work isn't that your using ecx by mistake or whatever - it's that your using the wrong registers all together.

Take a look at the post where i outline what registers to use for certain values. See where I say "use ST0 - ST7 for FPU registers"? That is what you need.....

[edited by - Jx on September 11, 2002 12:07:40 AM]

##### Share on other sites
quote:
Original post by Jx
Yeah, normally it is good practice - but... in the VC++ help files it says (and i know these are not to be taken as gospel) that certain registers can be used without saving and restoring them. Obviously I know that under certain conditions, this does not hold true, but for his case i''m sure it''s fine.

I think, personaly, I''d push/pop ''em anyways, at least during testing.

That said, I personal wouldnt use assember any more (unless it was an small mircoprocessor) because i''m pretty certain the compiler can turn my C/C++ into better assembler than I could write

(that said, learning assembler is a nice exercise and does give you a better insight into how it all works and can help you write code a bit)

##### Share on other sites
quote:
Original post by _the_phantom_

That said, I personal wouldnt use assember any more (unless it was an small mircoprocessor) because i''m pretty certain the compiler can turn my C/C++ into better assembler than I could write

Most of the time, you may be right and I certainly wouldn''t advocate writing all your functions in assembly, BUT: according to my knowledge, my MSVC++ compiler doesn'' optimize for MMX, 3DNow!, SSE/SSE2 etc so the only way to use these powerful instructions is to hand code the functions. Not only that, but sometimes the compiler does make stupid decisions when optimizing functions - but you really should follow that age old phrase: "Profile before you optimize"

In other words: why spend time optimizing your opengl initialization code when it''s only going to get called once? take a look at which parts of the code get called most and a) see if any algorithmic changes could speed them up, and b) make sure you are not performing any unnecessary calculations or allocations within the loop. If you still have a bottleneck - think about breaking out the assembler....

_the_phantom: I know you probably know all this so it wasn''t aimed at you - more people like Mulligan who are new to assembly.

##### Share on other sites
quote:
according to my knowledge, my MSVC++ compiler doesn'' optimize for MMX, 3DNow!, SSE/SSE2 etc so the only way to use these powerful instructions is to hand code the functions

It provides relatively high-level class wrappers for the MMX/SSE/SSE2/3DNow! packed datatypes, which may do the job for you.

##### Share on other sites
quote:
Original post by Jx

Please do! =) I used to write EVERYTHING in assembly back in the DOS days. Then I started using C++ to create the main structure of the program. Then I started writing most of my functions in C++. Then CPU power boomed, I got lazy and stopped using ASM altogether. Now, we''re several processors in the future, using 32-bit values AND addressing and I''m completely lost now that I want to get back into using assembly.

Not only that, but just UNDERSTANDING assembly is important for programmers. There''s another thread here titled "Are recursive functions limited? Yes." The poster didn''t know that the stack was being used in every function call and thus crashing their machine. An article on this topic would greatly help a lot of people since not many people really know what''s going on under the hood.

- Jay

Get Tranced!

##### Share on other sites
quote:
Original post by coderx75

I''ve started it, but it''s coming along rather slowly at the moment as I''ve got a lot of other stuff to do right now.

By the way - your music is good! I''ve been listening to it for a little while now, even before I saw the link in your posts. I didn''t realise that "coderx75" and "Jay Flaherty" were the same person until now

No $hit?! COOL! =) And thanks, you''re the first here to mention it. Yes, my sig is a shameless plug =) Where did you originally find my music if not here in the forum? It''s strange but I keep running into people that know who I am from the music. I dig it! =D - Jay "I have head-explody!!!" - NNY Get Tranced! #### Share this post ##### Link to post ##### Share on other sites Erm - not sure, but I think you remixed someone else I listened to on MP3.com or something... if not then i probably just got your name of the charts at mp3.com... [edited by - Jx on September 12, 2002 2:46:26 PM] #### Share this post ##### Link to post ##### Share on other sites quote: Original post by Jx The registers EAX, EBX, ECX etc can only be used for storing whole numbers like 4, 32, 65536 etc etc. The floating point registers are used for holding values like 3.14159, -0.910192 etc. The type of data should be pretty irrelevant. You should be fine putting floats, ints, strings, pointers, and whatever in e(a|b|c|d)x as long as they are 32 bits. Although, one should be careful what operations you do to them quote: Original post by _the_phantom_ That said, I personal wouldnt use assember any more (unless it was an small mircoprocessor) because i'm pretty certain the compiler can turn my C/C++ into better assembler than I could write ??? I highly doubt that, not knowing your assembly skills though. MSVC++ seems to have extremely bad common sense, escpecially when it comes to utilizing registers and hold their values. Instead it constantly "resolves" indirections etc. This piece of crap came to mind now. It is a part of my line routine for drawing a horizontal line. The first column is the C code, second the assembly MSVC++ produced, the third is how I would have implement it in Motorola 680x0 assembly. If I tried, I'm sure could reduce the x86 assembly a lot. if(nPixelCountY == 0) [4] cmp DWORD PTR _nPixelCountY$[ebp], 0	[2] tst.l  d1						[2] jne		SHORT $L667 [2] bne.b .type2 while(nPixelCountX--) [3] mov edx, DWORD PTR _nPixelCountX$[ebp]						[3] mov		eax, DWORD PTR _nPixelCountX$[ebp] [3] sub eax, 1 [3] mov DWORD PTR _nPixelCountX$[ebp], eax						[2] test	edx, edx						[2] je		SHORT $L670 *pAddress++ = dwColorARGB32; [3] mov ecx, DWORD PTR _pAddress$[ebp]						[3] mov		edx, DWORD PTR _dwColorARGB32$[ebp] [2] mov DWORD PTR [ecx], edx [2] move.l d2,(a0)+ [3] mov eax, DWORD PTR _pAddress$[ebp]						[3] add		eax, 4						[3] mov		DWORD PTR _pAddress$[ebp], eax [2] jmp SHORT$L669				[4] dbra   d0,.type1_loop
EDIT: The number inside the brackets are the instruction size. And the labels I've used: .type2 is somewhere after this stuff, and .type1_loop is pointing to the previous move.l instruction

EDIT 2: The disgusting part of this is that this routine should be able to run without any memory access but when putting the pixel there. Instead it is 5 read accesses and 3 writes (including the pixel putting).

[edited by - CWizard on September 12, 2002 5:23:32 PM]

##### Share on other sites
Would this work?
    mov eax, DWORD PTR nPixelCountY    cmp eax, 0    je  done    mov ecx, DWORD PTR nPixelCountX    mov ebx, DOWRD PTR pAddress    mov eax, DWORD PTR dwColorARGB32loop:    mov DWORD PTR [ebx], eax    add ebx, 4    dec ecx    jnz loopdone:

I''m just trying to pick up assembly too

• ### Forum Statistics

• Total Topics
628697
• Total Posts
2984273

• 20
• 9
• 13
• 13
• 11