[solved]asm problem (C++)

Started by
17 comments, last by Programmer16 18 years, 9 months ago
I got a code snippet out of "Tricks of the 3D Game Programming Gurus: Advanced 3D Graphics and Rasterization". It replaces memset(), but when I use it I access violations (I believe that I'm using it incorrectly). Its supposed to clear by QUADs instead of BYTEs (or something like that.) Here are the snippet and a second one that I made:

inline void SetMemory(void* pDest, UINT nData, int iSize)
{
	_asm
	{
		mov edi, pDest;
		mov ecx, iSize;
		mov eax, nData;
		rep stosd;
	}
}

inline void ClearMemory(void* pDest, int iSize)
{
	SetMemory(pDest, 0, iSize);
}


I then tested it with
WNDCLASS WndClass;
dftCommon::ClearMemory(&WndClass, sizeof(WNDCLASS));
Which clears the memory perfectly (just like ZeroMemory(), but after the app returns from main(), I get a large amount of access violations. After switching to ZeroMemory(), they go away. Any ideas? Thanks! [Edited by - Programmer16 on July 4, 2005 1:14:40 PM]
Advertisement
Pardon my ignorance of asm, but what exactly is the difference? I suppose the brackets do something, but what is it that they do?
daerid@gmail.com
As far as I remember, you need brackets around the variable names in assembler because the variable names WITHOUT brackets correspond to their address, not to the variables themselves. Don't know if it is the same in inline assembler.
Also, sizeof gives you the number of bytes, wheras you are trying to write that much dwords. Perhaps that is the error.
is iSize in Bytes, or Words? if it is length in bytes try dividing it be 4 before clearing it, or use stosb instead (though stosd will be faster)
I'm not sure but I think you should give the size in quad words. You use sizeof which returns the number of bytes so for example if WNDCLASS is 32 bytes it'll clear 32*4(128) bytes and therefore you get an access violation (access 96 bytes beyond the object).
I'll try that after I'm done eating, but I believe that you're right.
im not that capable with x86 these days, but have you tried saving the ecx,edi,asx registers on the stack before using them and then restoring them before you return?

Cheers
-Danu
"I am a donut! Ask not how many tris/batch, but rather how many batches/frame!" -- Matthias Wloka & Richard Huddy, (GDC, DirectX 9 Performance)

http://www.silvermace.com/ -- My personal website
silvermace, most C++ compilers should do that for you.
Yes, that fixed it. Thank you good people!

PS: In the appendix of the book, he defines a function like so:
_asm{    mov edi, x;    mov ecx, 1000/4;    mov eax, 0;    rep stosd;}


But when I tried to '/ 4', I get an error. Is this just a typo in the book?

The error is:
c:\documents and settings\programmer16\my documents\projects\dragonforge technology\dftcommon.h(35) : error C2425: '/' : non-constant expression in 'second operand'


Again, thanks!
If you're getting a compiler error complaining about that assembly statement, with 1000/4 in it, then something's amiss. Did you say iSize/4? If so, then yes, you will get an error. However, you can accomplish this with:

mov ecx, iSize
shr ecx, 2

As for the compiler saving registers, eax, ecx, and edx are caller saved, which means you can use them as you please, but remember to save them (the stack is the standard place) before you call any other functions if you want to be guaranteed to get your old value back. However, edi is a callee save register. I'd push it before changing the value and then pop it before you return.

This topic is closed to new replies.

Advertisement