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,

When possble that's easier, of course. In my case, however, I need
different (constant) offsets within the asm block.

> The 'o'
> constraint tells gcc that it can use a small offset in the address that
> it passes into the asm.

Alright. But I thought (and still think ;-) that if gcc can add a
small offset, I should be able to add another one, since the sum of
two small offsets is still a small offset. (And it almost works,
except for this little syntactic issue whether or not to put a "+".)

> 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.

Sure, that's an option. But as we all know, registers aren't exactly
copious on poor old x86. In fact, I have all available registers
used up -- gcc gives me an error ("can't find register ...") when I
try to use one more "r" operand. Of course, I could move some
variable to the stack, but that would make the code slower (and it
is performance-critical code, otherwise I wouldn't be using asm in
the first place), especially if there's no fundamental reason (just
a syntactical one) why I can't just use the existing esp/ebp-based
addresses with constant offsets.

So I suppose, I'll keep my current work-around ("forcing" an offset
and always using "+") until it breaks. At least, it will give a
compile-time error when it fails, and not silently produce wrong
code. (At least I don't see a way how it could result it wrong code,
or do you?)

Regards,
Frank
 
-- 
Dipl.-Math. Frank Heckenbach <f.heckenbach@xxxxxxxxxx>
Systemprogrammierung, EDV-Beratung
Stubenlohstr. 6, 91052 Erlangen, Deutschland
Tel.: +49-9131-21359


[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