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.
what does "mov offset(%rip), %rax" do?
Asked Answered
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.
Interesting -- but what is RIP-relative addressing actually useful for? –
Caseate
@AlexD lots of things, typically all references to the data section and so on –
Ailee
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 dlls –
Ailee
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
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.
@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.
jmp
instruction is a displacement from the next instruction. – Cohbert