Sign in to follow this  

x86 inline assembly question

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

Code is from visual studio 2005 I'm having a hard time with x86 syntax. I'm trying to get the value of a dereferenced pointer into a register instead of the pointer address:
static inline unsigned long __cmpxchg(volatile void *dest, unsigned long oldVal, unsigned long newVal, int size = 4)
{
	__asm
	{
		mov eax, dest
		mov ebx, [dest]
	}
}

obviously not the actual logic that i'm trying to go for. However, with this unit test, at the end of the asm execution, both eax and ebx contain the pointer's memory address, rather than the value pointed at by dest. Everything I'm finding online suggests that the bracket operators should signal a pointer dereference... What am I missing? -me

Share this post


Link to post
Share on other sites
I am not sure, but I guess you can only use brackets an a register. So try this instead.

static inline unsigned long __cmpxchg(volatile void *dest, unsigned long oldVal, unsigned long newVal, int size = 4)
{
__asm
{
mov eax, dest
mov ebx, [eax]
}
}


/Klarre

Share this post


Link to post
Share on other sites
Basically, when you want the value from a variable, the compiler has information that you need, such as where that variable is on the stack. What the compiler is doing when you say:

mov eax, dest

is really:

mov eax, [esp-X]

Where X is the relative location to that variable on the stack. Therefor, if you were to do:

mov eax, [dest]

you'd really be doing:

mov eax, [[esp-X]]

Which of course is not valid. The correct answer is what Klarre said:


__asm
{
mov eax, dest ; moves the address contained in the dest pointer into register eax.
mov ebx, [eax] ; moves the value at the address pointed to by the dest pointer (which is now in eax).
}

I hope my explanation yields some clarity about why things are this way. =)

Kevin B

Share this post


Link to post
Share on other sites
hrm. well then that complicates things. as you can probably see from the function header i'm trying to use the atomic compare and exchange primitive. so the assembly code I'm trying to get to work is:


static inline unsigned long __cmpxchg(volatile void *dest, unsigned long oldVal, unsigned long newVal, int size = 4)
{
unsigned long prev = 0;

__asm
{
mov eax, oldVal
mov edx, newVal

//this line is the problem. it's pulling in
//the pointer address for it's compare operation
lock cmpxchg dword ptr [dest], edx

mov prev, eax
}

return prev;
}



the cmpxchg op has to be done atomically so as far as i understand it, having a seperate move instruction to get the dereferenced value of the pointer won't work. The docs for the cmpxchg instruction say the first argument can either be a register or a memory location. I'm looking for the latter, just unsure of the syntax.

[EDIT: gah nevermind... i think i understand it now. I do actually need the extra mov statement...]

I think this should work....


static inline unsigned long __cmpxchg(volatile void *dest, unsigned long oldVal, unsigned long newVal, int size = 4)
{
unsigned long prev = 0;

__asm
{
mov eax, oldVal
mov edx, newVal

mov ecx, dest
lock cmpxchg [ecx], edx

mov prev, eax
}

return prev;
}



or a friend from work suggests:


static inline unsigned long __cmpxchg(volatile void *dest, unsigned long oldVal, unsigned long newVal, int size = 4)
{
unsigned long prev = 0;

__asm
{
mov eax, oldVal
mov edx, newVal

lock cmpxchg [ebp-16], edx

mov prev, eax
}

return prev;
}

Share this post


Link to post
Share on other sites
Quote:
Original post by Extrarius
Alternately, if you're targetting windows, you could just use InterlockedCompareExchange.


Oh nice, hadn't come across that; I'll eventually convert over to using that for my windows builds.

For now, however, part of what I'm doing is just learning how this stuff all works at a low level so I'll just try to get my assembly version working before switching over.

-me

Share this post


Link to post
Share on other sites
If you're going to try to touch the stack manually like "lock cmpxchg [ebp-16], edx" make sure you specify the calling convention of the function so you actually know what the stack looks like.


Also, I think the Interlocked functions are really compiler intrinsics, which means you should be able to put it in your code and have the compiler output assembly and you'll be able to see the actual implementation of the function.

Share this post


Link to post
Share on other sites
Maybe inline asm just cant handle it. I tried it directly in asm and it works fine.

I just put

40100C MOV EBX,50
401011 MOV EAX,5A
401016 MOV ECX,app.00403000
40101B LOCK CMPXCHG DWORD PTR DS:[ECX],EBX

And it worked exactly as expected, and a direct pointer dereference did the same thing, so your interpretation of the instruction is correct at least..
Now I'm confused.

Share this post


Link to post
Share on other sites

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

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this