A89: Re: placing data into C variables from ASM(" ") constructs


[Prev][Next][Index][Thread]

A89: Re: placing data into C variables from ASM(" ") constructs




>  > l can use the following code to put values into an ASM(" ") construct like
>  > this...
>  > function(x)
>  > int x;
>  > {
>  > move.w 8(%sp),%d0   // puts 'x' into d0
>  > }
>  >
>  > But how do l get values out of an asm construct? (like register d0 into
'x')
>
> It is advisable to read the gcc manual, gcc has some interesting ways
> to deal with assembly - C interaction.
>
> The following is *not* a detailed description and does not deal with
> all possible aspects of referencing variables from either side.
>
> Let us have a simple assembly code which (for the sake of simplicity)
> adds two numbers together.
>
> func()
> {
> int a, b, c;
>
>   /* This will add a and b, store the result in c */
>
>   asm volatile ( "

What does volatile mean when combined with asm() ?



> move.l %2,%0
> add.l  %1,%0
>
>     " : "=&d" (c) : "g" (a), "g" (b) );
> What does it do:
>
> In the move.l and add.l operands %0, %1 and %2 refer to the formal
> parameters to the assembly text. They will be substituted with the
> relevant register or memory references. The formal parameters are
> numbered from 0 to 9, left to right.
>
> The colon separates the assembly code from the formal parameter list
> section. This start with the output parameter description list.
> An assembly function may have none, one or more output parameters.
> The nature of the parameter is specified between the ""-s.
> The first symbol is the = which indicates an output parameter. The
> next symbol is an optional &, see later. The next is a letter or a
> series of letters indicating the type of the operand. The most often
> used ones are d, for a data register, a, for address register, m for
> memory and g for any of the above. Thus, in our example formal
> parameter 0 is qualified by "=&d", that is, it is an output operand
> which must be a data register. It also has the '&' qualifier, which
> will soon be discussed. Following this definition is the (c)
> part. This tells the compiler that after executing the routine it
> should assign the result in that data register to the C variable 'c'.
> Actually, anything can be in the parens which can be on the left hand
> side of an = operator, so you can have things like this:
>
> ... " : "=&da" (*(( long *) my_pointer)) : ...
>
> which will move the result of the assembly routine, which result
> should be in an address or in a data register, as a longword, to the
> location pointed by my_pointer.
>
> If you have more than one output, you simply list them, separated by
> commas, like this:
>
>    ... " : "=&d" (x), "=&a" (ptr) : ...
>
> This was the output specification section.
>
> The following : indicates the end of the description of the output
> operands and the start of the input operands. The input operand
> descriptors are similar to the output ones, with some differences. On
> one hand, they do not start with = for they are input operands. For
> that reason, the c expression in the parens can be anything that can
> be on the right hand side of an =, including constants, any complex
> expression, function calls and whatever.
>
> Now comes the interesting bit. Gcc treats the whole assembly issue in
> such a way that it assumes that the assembly stub consumes all of its
> input operands before producing its output. This means that gcc may
> allocate the same register for an output operand as an input one. In
> our example, if %0 and %1 are the same, then we are in trouble. This
> is what the '&' is for in the output specification. It tells gcc that
> the particular output operand can not be assignedto the same register
> as an input operand.
> Sometimes you want the opposite, you want to tell the compiler that
> an input operand must be allocated into the same register as a
> particular output operand. You do it by specifying the reference
> number of the output operand in the input section, as in the example
> below:
>
>    asm volatile ( "
>
>    add.l %1,%0
>
>    "=&d" (c) : "d" (a), "0" (b) );
>
> The only difference is from the previous version is that as you can
> see the type specifier for the (b) operand is "0". This means the 0-th
> formal parameter, that is the same place that will be allocated to
> (c). This way we could save the move.l %2,%0 since the compiler will
> know that these registers are the same.
>
> If your assembly routine destroys specific registers, you can list
> them after the input section. Again, a : should be put there then you
> just list the registers you destroy, each of them in ""-s, like this:
>
>    "=&d" (c) : "d" (a), "0" (b) " "d0", "d1", "a5" );

Forgot a colon here :-)

> if you destroy d0, d1 and a5. If you clobber memory, then list
> "memory" as well. It is guaranteed that gcc will not allocate these
> registers to input or output operands.

How does gcc deal with memory being changed?

> This leaves one more thing: what about destroying input operands. Gcc
> assumes, (unless you specifically assigned an input and an output
> parameter to the same formal parameter) that your routine does not
> change the input parameters. If you do change it, then you are in
> trouble - if the compiler later needs the value it stuffed into the
> regsiter, it vill assume that it's still there. If you changed it,
> then your code will blow.
>
> To avoid this, you can transfer the input operands which you wish to
> change into registers which then are listed in the clobbered section.

I thought you named your input operands as being clobbered by adding "0", "1"
a.s.o. to the clobbered list?

> There are other tips & tricks with regards to the C and asm
> interaction in gcc, but hopefully the above is enough to get you
> going. For anything more you should consult the gcc info file, which
> you should have received with the compiler package.

A good (but slow) place is also http://www.delorie.com/gnu/docs/gcc/
Are there any other (faster) places on the net that have the gcc docs online and
searchable?


 / Niklas Brunlid
Check out Prosit for the TI-89 / TI-92+ at http://prosit.ticalc.org
Random PQF Quote follows:

There seemed nowhere in it for him, but this wasn't a problem. There was
always room at the top.
        -- (Terry Pratchett, Moving Pictures)




Follow-Ups: References: