4

I need GCC to produce a consistent set of instructions for inline asm, but one of the instructions I'm using is sometimes compiled two different ways:

__asm__ ("mov %1,%%rax;" \
         : \
         : "m"(ref) \
         : "%rax");

Compile #1:

mov 0x200894(%rip),%rax

Compile #2:

mov 0x200894(%rip),%rdx
mov (%rdx),%rax

I'm not sure what the reason is for the second version, but I don't want it. Is there a constraint to specify that a memory reference should only be direct, i.e., not via register?


Update:

This variation always produces the exact same instruction:

    __asm__ ("mov ref@GOTPCREL(%rip),%rax");

Compiles to:

mov 0x200910(%rip),%rax
5
  • 2
    The two sequences of instructions are not equivalent. In the first 0x200894(%rip) contains the result directly, in the second 0x200894(%rip) contains a pointer to the result. What is ref? Does it have the same type in both instances? Is it pointer to a function or object that's exported from a DLL (which sometimes might have to be an indirect reference through a 'GOT')? Commented Jun 12, 2014 at 18:19
  • It's extern const char *ref, and the second version does only occur in a shared library--so it must have a GOT reference even though the variable is defined inside the library. Can I avoid that somehow? Commented Jun 12, 2014 at 18:27
  • 1
    I'm not sure. There's a good description of the GOT mechanism here: eli.thegreenplace.net/2011/11/03/… If there is a way to do what you want, that article might give you a clue (or a starting point) for how. Commented Jun 12, 2014 at 19:10
  • @MichaelBurr: thanks, I found a way (see update). Commented Jun 12, 2014 at 22:16
  • Byron, you should post your solution as an answer to your own question. That was an interesting one. Commented Jun 12, 2014 at 22:17

1 Answer 1

3

Answering my own question:

This variation always produces the exact same instruction:

__asm__ ("mov ref@GOTPCREL(%rip),%rax");

Compiles to:

mov 0x200910(%rip),%rax

For x86 where RIP-relative is not available, it takes two instructions:

__asm__ ("mov $_GLOBAL_OFFSET_TABLE_,%%eax; \
          add ref@GOT,%%eax;");

Compiles to:

mov $0x2ff7,%eax
add 0xfffffff0,%eax

Two more instructions are required to make %eax RIP-relative, but I'm working in a binary translator where that's easier to do internally.

Sign up to request clarification or add additional context in comments.

1 Comment

Just for the record, these "Basic Asm" statements with no constraints aren't safe to use inside functions. You need asm("..." ::: "eax"). gcc.gnu.org/wiki/ConvertBasicAsmToExtended

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.