what does "mov offset(%rip), %rax" do?
Asked Answered
S

2

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.

Sharondasharos answered 2/4, 2015 at 20:21 Comment(0)
A
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.

Ailee answered 2/4, 2015 at 22:24 Comment(8)
Pretty much everything in x86 works this way. For example, the immediate value of a jmp instruction is a displacement from the next instruction.Cohbert
Interesting -- but what is RIP-relative addressing actually useful for?Caseate
@AlexD lots of things, typically all references to the data section and so onAilee
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?Caseate
@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 dllsAilee
OK, I get it: if the .data and .text sections are relocated together, then references to global variables can be position independent! Cool.Caseate
@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?. But 32-bit absolute has possible uses for cases where a RIP-relative addressing mode can't micro-fuse, like cmpl $1, foo.Sawyer
@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.Sawyer
S
10

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.

Sawyer answered 22/1, 2019 at 17:19 Comment(3)
@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.)Sawyer
I used to do that all the time with the 8 bit computers and C/PM... Thems were the days!!! :)Sharondasharos
See How do RIP-relative variable references like "[RIP + _a]" in x86-64 GAS Intel-syntax work? for more details about the syntax in AT&T and Intel mode.Sawyer

© 2022 - 2024 — McMap. All rights reserved.