Skip to main content
gamedev.net
🔒 Locked

Inline Assembler Issues

Started by luridcortex 3 replies 900+ views
Original Post
luridcortex
luridcortex
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.
Sneftel
Sneftel
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.
luridcortex
luridcortex
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:	}}
C0D1F1ED
C0D1F1ED
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...
LastUnicron
LastUnicron
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]

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.