Inline Assembler Issues

Started by
3 comments, last by LastUnicron 19 years ago
Hi all, I am having trouble setting values of class memebers using the inline assembler if they have been previously initialized. I cant quite figure out what the problem is exactly, but I have a feeling it has to do with my lack of understanding how certain instructions, like mov, move data around. Here is some code to help illustrate my problem:

class CCpuInfo
{
public:
	/// constructor
	CCpuInfo();
	/// destructor
	virtual ~CCpuInfo();

	... 

	/// find supported features, mmx, sse, 3dnow!, ect..
	void GetFeatures();
	
private:
	BOOL supportSSE;
	BOOL supportSSE2;
	BOOL supportMMX;
	
        ...
};

//------------------------------------------------------------------------------
/**
*/
CCpuInfo::CCpuInfo() :
	supportSSE ( FALSE ),
        supportSSE2 ( FALSE ),
	supportMMX ( FALSE ),
{
}

void CCpuInfo::GetFeatures()
{
	BOOL *_supportSSE = &this->supportSSE;
	BOOL *_supportSSE2 = &this->supportSSE2;
	BOOL *_supportMMX = &this->supportMMX;

	__asm {
			mov eax, 1
			
			CPUID

			test edx, 02000000h		
			jz _NOSSE
			mov [_supportSSE], 1

_NOSSE:		test edx, 04000000h
			jz _NOSSE2
			mov [_supportSSE2], 1

_NOSSE2:	test edx, 00800000h
			jz _EXIT
			mov [_supportMMX], 1
			
_EXIT:
	}
}

If I remove the intialization for the three BOOL's, the GetFeatures() function will set them properly, otherwise they will always be false. I am assuming in the code that the values are true as long as they are not equal to zero.
Advertisement
Are you sure it sets them properly if there's no initialization? I wonder if without initialization, they just happen to end up with nonzero values. Try this: remove the initialization code, and change the asm to set the values to 0 if the features are detected. I'm guessing they'll stay TRUE.
Quote:I wonder if without initialization, they just happen to end up with nonzero values.


Wow, I cant beleive I didnt notice that. Thanks!

Ive also noticed that if I move my data (one of the bools) into a register, and then operate on the data in that register instead of the data directly, it works - though, im still not sure why.

Here is an example of some working code. Ive split the previous function up, so here is the code to check for SSE support:

void CCpuInfo::CheckSupportSSE(){	int *tmp = &this->supportSSE;		__asm {		mov eax, 1		CPUID		test edx, FLAG_SSE		jz _EXIT		mov edx, tmp		mov [edx], 1_EXIT:	}}
Hi luridcortex,

Your _supportSSE is a variable, holding an address to another variable where you would like to store some information. The name _supportSSE itself actually represents the memory location (a pointer) of the _supportSSE variable (which holds the value of a pointer). So what you really need to do is something like:
mov eax, [_supportSSE]mov [eax], 1

Hope that helps...
Here's a straightforward way to set member variables in an __asm block. (Note: I know this works with MSVC - can't vouch for other compilers.)

__asm{    mov ebx, this    mov [ebx].supportSSE, 1}


edit:

Also, to make it work the other way, it's:
__asm{    mov ebx, _supportSSE    mov dword ptr[ebx], 1}


Just remember that if you want to dereference an address with [], the address needs to be in a register. The "dword ptr" part lets the compiler know the size of the object - in this case 4 bytes.


[Edited by - LastUnicron on April 9, 2005 5:09:12 PM]

This topic is closed to new replies.

Advertisement