11

Does rax get offset plus the address of this instruction, or the next? From a microcode point of view it might be easier if the answer was the next instruction.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Bing Bang
  • 524
  • 7
  • 16

2 Answers2

13

The next. That's a general rule on x86 (see also branches).

In Intel's manual volume 2 section 2.2.1.6 RIP-Relative Addressing:

A new addressing form, RIP-relative (relative instruction-pointer) addressing, is implemented in 64-bit mode. An effective address is formed by adding displacement to the 64-bit RIP of the next instruction.

harold
  • 61,398
  • 6
  • 86
  • 164
  • 1
    Pretty much everything in x86 works this way. For example, the immediate value of a `jmp` instruction is a displacement from the next instruction. – Jonathon Reinhart Apr 02 '15 at 22:26
  • Interesting -- but what is RIP-relative addressing actually useful for? – Alex D Apr 06 '15 at 11:50
  • @AlexD lots of things, typically all references to the data section and so on – harold Apr 06 '15 at 12:37
  • Global variables, in other words? But why would you want to access a global using an address relative to RIP? Why not just use a constant address? – Alex D Apr 06 '15 at 13:09
  • @AlexD would work, but then you'd better keep things (mostly) in the low 2GB (or else the constants have to be 64bit), and then you also have the relocation problem for dlls – harold Apr 06 '15 at 13:23
  • OK, I get it: if the `.data` and `.text` sections are relocated *together*, then references to global variables can be position independent! Cool. – Alex D Apr 06 '15 at 18:59
  • 1
    @AlexD: because RIP-relative addressing modes are shorter than 32-bit absolute addressing modes. 32-bit mode had 2 redundant ways to encode `[disp32]`. x86-64 repurposes the non-SIB version as `[rip + rel32]`, while leaving the ModRM+SIB encoding with no base or index as `[disp32]`. Mainly a disp32 absolute address is only useful for indexing a static array: [32-bit absolute addresses no longer allowed in x86-64 Linux?](https://stackoverflow.com/q/43367427). But 32-bit absolute has possible uses for cases where a RIP-relative addressing mode can't micro-fuse, like `cmpl $1, foo`. – Peter Cordes Jan 22 '19 at 17:21
  • @AlexD: As for why it's designed so that RIP-relative is more efficient: because having a lot of code in libraries was becoming common when AMD64 was being designed on paper. Position-independent code doesn't need runtime fixups. And it lets an executable or library up to 2GiB be loaded anywhere in 64-bit address space and still reach its own static storage with only 4-byte displacements. – Peter Cordes Dec 12 '22 at 05:56
9

Note that symbol_name(%rip) calculates the offset required to reach symbol_name from here, rather than adding the absolute address of symbol_name to RIP as an offset.

But yes, for numeric offsets like mov 4(%rip), %rax, that will load 8 bytes starting at 4 bytes past the end of this instruction.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • @BingBang: yes, of course you can, if your code is in a page that's writeable + executable. Same as always. It doesn't mean you *should*, SMC performance is horrible on modern x86. (Pipeline nuke every time a store to an address that's already in the pipeline is detected.) So you can JIT once and run many times. There's no short-form `RIP+rel8` encoding for small displacements relative to RIP, only rel32, so there's zero benefit to keeping data next to code either. (Except that you might get an L2 cache hit from code-fetch bringing it into unified levels of cache.) – Peter Cordes Jan 29 '19 at 19:31
  • I used to do that all the time with the 8 bit computers and C/PM... Thems were the days!!! :) – Bing Bang Feb 04 '19 at 19:25
  • See [How do RIP-relative variable references like "\[RIP + \_a\]" in x86-64 GAS Intel-syntax work?](//stackoverflow.com/q/54745872) for more details about the syntax in AT&T and Intel mode. – Peter Cordes Jul 25 '19 at 16:06