> 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