Inline ASM

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
Inline
Posts: 3
Joined: Sat Jan 19, 2008 7:55 pm

Inline ASM

Post by Inline »

Hi !

I'm playing with a C program which I want to move some parts to inline ASM.

I'm trying to call C functions from ASM, I've tried something like this :

Code: Select all

void doSomeStuff()
{
 	//.......;
}

void test()
{
	void (*pFunction)() = NULL;
	pFunction = &doSomeStuff;	

	asm __volatile__ (
		"jal %0 ;\n"
		:
		:"e"(pFunction)
	);
}
First of all, why it's not working (it may be really stupid sorry), and how can I make it works ?

In a second time I would like to use arguments and return value.
I found the r31 register for the return value, but how can I manage arguments ?

Thanks in advance.
Last edited by Inline on Sat Jan 19, 2008 8:32 pm, edited 1 time in total.
hlide
Posts: 739
Joined: Sun Sep 10, 2006 2:31 am

Post by hlide »

pFunction is a variable, not an constant immediate.

So it should be something like :

Code: Select all

   int ra;
   asm __volatile__ (
      "jalr %1 ;\n"
      "move %0, $ra ;\n"
      "move $ra,%0 ;\n"
      :"=r"(ra)
      :"r"(pFunction)
      :"v0", "v1", // a call can change them so clobber them!
       "a0", "a1", "a2", "a3",
       "t0", "t1", "t2", "t3", "t5", "t6", "t7", "t8", "t9",
       "memory" 
   ); 
but i would say : never do this way as it is cumbersome whereas doing "pFunction();" would be more efficient.


NOTE: jal or jalr move on ra register the return address and in C/C++ you must first save ra register before calling a target address
Inline
Posts: 3
Joined: Sat Jan 19, 2008 7:55 pm

Post by Inline »

Thank you for the answer hlide.
I now succeed to call my functions.

Do you have a idea for arguments ?
I looked at the disassembly (compiled with gcc). It seems random registers are used to pass arguments.
hlide
Posts: 739
Joined: Sun Sep 10, 2006 2:31 am

Post by hlide »

use of "branch and link" (that is, call to function) in an assembly line code should really avoided at all cost since you prevent gcc to be aware of it and let gcc generate broken code.

But to answer your question :

- if you function returns a 32-bit word, $v0 contains this return value
- if you function returns a 64-bit word, $v1-$v0 contains this return value (lower value is in $v0)
- if your function accepts one or several arguments, $a0 would be the first, $a1 the next one, up to 8 registers in this order : $a0, $a1, $a2, $a3, $t0, $t1, $t2, $t3

int f(int x, int y) should be called this way :

Code: Select all

   int ra, res;
   asm __volatile__ (
      "move $a0,%3" "\n" // unoptimal if %3 == $a0
      "move $a1,%4" "\n" // unoptimal if %4 == $a0
      "jalr  %2" "\n"
      "move %0, $ra" "\n"
      "move $ra,%0" "\n"
      "move %1,$v0" "\n" // unoptimal if %1 == $v0
      :"+r"(ra), "=r"(res)
      :"r"(pFunction), "r"(x), "r"(y)
      :"v0", "v1", // a call can change them so clobber them!
       "a0", "a1", "a2", "a3",
       "t0", "t1", "t2", "t3", "t5", "t6", "t7", "t8", "t9",
       "memory"
   );
but still this is very unoptimal this way.

instead of asking how to call a C function in inline asm function, why not just output your inline asm function which calls, so we can give you the best way to do so ?
Inline
Posts: 3
Joined: Sat Jan 19, 2008 7:55 pm

Post by Inline »

Thank you very much hlide,

It works as I want.(With just moving the "move %0, $ra" up to the "jal")

In fact it's just for learning and fun, a temporary situation, time for me to translate everything to ASM. I want be able to test before moving everything.

Thanks again for your advices.
Post Reply