NO

Author Topic: inline asm procedure passing by ref  (Read 5316 times)

ko3lan

  • Guest
inline asm procedure passing by ref
« on: March 27, 2012, 01:59:18 AM »
Hi there

I am trying to pass a parameter by reference to some function with inline assembly code in it, but it has no effect.

void asm(int *arg)
{
   __asm
   {
      mov eax, arg;
      inc eax;
      mov arg, eax;
   }
}

int main(void)
{
   int i = 23;
   int *p = &i;

   asm(p);

   printf("%d\n", i);
}


It prints 23. What am I doing wrong?

Offline Bitbeisser

  • Global Moderator
  • Member
  • *****
  • Posts: 772
Re: inline asm procedure passing by ref
« Reply #1 on: March 27, 2012, 03:38:46 AM »
I know what's wrong but don't know right now how to fix it without spending a bit of time to experiment. The help file is here actually a but on the hazy side.

You are not properly loading the value of the argument variable arg, as it seems the stack isn't set up right. Therefor, the inc eax instruction is incrementing a different memory location, not the one *p is actually pointing too...

Ralf

Offline TimoVJL

  • Global Moderator
  • Member
  • *****
  • Posts: 2115
Re: inline asm procedure passing by ref
« Reply #2 on: March 27, 2012, 08:14:16 AM »
Code: [Select]
void asm(int *arg)
{
   __asm
   {
      mov eax, arg         ; pointer to arg
      inc dword ptr [eax] ; inc eax pointed mem location
   }
}
May the source be with you

CommonTater

  • Guest
Re: inline asm procedure passing by ref
« Reply #3 on: March 27, 2012, 12:19:01 PM »
From my limited ASM knowledge I'd say Timo has it right... you are passing in a pointer but your asm code treats it like a value whereas Timo correctly treats it as a pointer to a value.

It might also help you to understand that C has no actual "pass by reference" mechanism.  Everything that goes into a function is a value.  Even when passing a pointer you are passing it's value (the address it points to) not the pointer itself.  This is why changing a value inside a function is not reflected outside the function (which is a good thing).  It's also why you have to manually dereference pointers inside your functions to change a value at the pointer outside the function. 
 
Some other languages (like C++) do have a real pass by reference mechanism where a pointer is automatically dereferenced.  C, however has never had this feature.
 
« Last Edit: March 27, 2012, 12:25:47 PM by CommonTater »

Offline Bitbeisser

  • Global Moderator
  • Member
  • *****
  • Posts: 772
Re: inline asm procedure passing by ref
« Reply #4 on: March 27, 2012, 08:09:14 PM »
From my limited ASM knowledge I'd say Timo has it right... you are passing in a pointer but your asm code treats it like a value whereas Timo correctly treats it as a pointer to a value.
Haven't tried what Timo wrote (which looks like a reasonable solution for that test example), but I guess what the OP was trying to do would be something like this
Code: [Select]
void asm(int *arg)
{
   __asm
   {
      mov eax, DWord Ptr [arg]         ; load eax with the value pointed to by arg
      inc eax                          ; inc eax
      mov DWord Ptr [arg], eax         ; move the incremented value back into the place pointed to by arg
   }
}
However, when I did a quick test, Pelle's C didn't do/allow that, and in the end it might just come to (a possible restriction) in the (right) assembler syntax here

The memory address is actually known inside the function and assembler block, it seems to be rather an issue of "finding the right words" to tell POCC/POASM what exactly to do.

Ralf

ko3lan

  • Guest
Re: inline asm procedure passing by ref
« Reply #5 on: March 27, 2012, 11:56:47 PM »
Thank you all very much. This code does what I need:

void asm(int *p)
{
   __asm
   {
      mov eax, p;
      mov ebx, dword ptr [eax];
      inc ebx;
      mov dword ptr [eax], ebx;
   }
}

Offline Bitbeisser

  • Global Moderator
  • Member
  • *****
  • Posts: 772
Re: inline asm procedure passing by ref
« Reply #6 on: March 28, 2012, 02:22:23 AM »
Thank you all very much. This code does what I need:

Code: [Select]
void asm(int *p)
{
__asm
{
mov eax, p;
mov ebx, dword ptr [eax];
inc ebx;
mov dword ptr [eax], ebx;
}
}
Aaargh, of course, now I know what I did wrong, it won't resolve the use of the local variable right, trashing the EAX register.

On the same note however, the online help about the x86 inline assembler states that all registers but EAX, EDX and EDX need to be explicitly preserved by the assembler function, and as you are using EBX, you should either change that to ECX or explicitly PUSH EBX at the very beginning and the POP EBX as the end of the inline block...

Ralf

Offline AlexN

  • Global Moderator
  • Member
  • *****
  • Posts: 394
    • Alex's Link Sammlung
Re: inline asm procedure passing by ref
« Reply #7 on: March 28, 2012, 10:37:58 AM »
Why don't you use Timo's example? It is shorter and as I assume faster and I think it does the same.
best regards
 Alex ;)

Offline Bitbeisser

  • Global Moderator
  • Member
  • *****
  • Posts: 772
Re: inline asm procedure passing by ref
« Reply #8 on: March 28, 2012, 04:38:45 PM »
Why don't you use Timo's example? It is shorter and as I assume faster and I think it does the same.
Maybe because it is only that, and example of what he wants to do?

Ralf

ko3lan

  • Guest
Re: inline asm procedure passing by ref
« Reply #9 on: March 28, 2012, 05:22:42 PM »
Thanks for useful hints, Bitbeisser

And yes, I just wanted to ensure, that I can load something into a register from a pointer. Maybe increment example wasn't as apparent..