Re: Inline asm (x86): How to use offsettable addresses?

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

 



Frank Heckenbach <f.heckenbach@xxxxxxxxxx> writes:

> in gcc's inline assembler, the constraint "o" means "A memory
> operand is allowed, but only if the address is offsettable. This
> means that adding a small integer (actually, the width in bytes of
> the operand, as determined by its machine mode) may be added to the
> address and the result is also a valid memory address."
>
> So far, so good, but how can one actually do the offsetting? E.g.,
> on x86 such an operand may expand to "(%esp)" or "4(%esp)". If you
> wanted to add 42 to this address, in the former case you'd need to
> write "42%0" (to produce "42(%esp)"), in the latter case, you'd need
> to write "42+%0" to get "42+4(%esp)". A mismatch results in
> incorrect asm syntax ("42+(%esp)" or "42 4%(esp)" or even
> "424%(esp)").
>
> But one doesn't know in advance which form the compiler will produce
> (of course, this is basically the point of those constraints, to let
> the compiler choose what's best). It may depend on unrelated code
> changes and even on the gcc version. (Which is actually how I found
> out about the issue -- previous versions would always give me ebp
> with an offset, but gcc-4.6, probably due to better optimizations,
> actually gave me plain "(%esp)" in one case.)
>
> So is there a syntax that will work with both forms, or some trick
> to make it work? (My current work-around is to modify declarations,
> so it's virtually guaranteed there will be an offset and I can use
> the "+" form, but I'm not too happy with it.)

If you want to add an offset, then you should either do it in the value
passed to the asm, or you should not use the 'o' constraint.  The 'o'
constraint tells gcc that it can use a small offset in the address that
it passes into the asm.  That is appropriate when the asm is just going
to use it as a pure memory address.  It is not appropriate when the asm
wants to add its own offset.  For that, you usually want your asm to use
the address as the value and use an 'r' constraint to put the address in
a register.

To say this another way, you may be thinking that you are supposed to
use an 'o' constraint if your asm wants to build an offset from the
address.  The poorly-documented truth is that 'o' is almost entirely for
gcc's internal use in machine description files.  The 'o' constraint is
used for cases like a double-word load that is split into two
single-word loads.  This kind of splitting is not available for gcc's
extended asm expressions.

Ian


[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux