Subject:
[rip+expr] with a non-absolute displacement — suggestion to reject at the instruction.
I ran into this producing MS COFF objects (COMDAT/`/OPT:REF` work). Writing this by mistake:
format MS64 COFF
section '.data' data readable writeable
v dq 0
section '.text' code readable executable
public f
f: mov rax,[rip+v]
ret
assembles silently to a RIP-relative encoding carrying an
IMAGE_REL_AMD64_ADDR32 relocation on the displacement:
0: 48 8b 05 00 00 00 00 mov rax,[rip]
3: IMAGE_REL_AMD64_ADDR32 .data
Both link.exe and lld-link accept it without a peep, and at run time the EA is
next_instruction + VA(v) — garbage. fasm 1.73.32 produces the identical object, so this is not a fasm2 regression; it follows directly from the documented semantics (
mov [rip+3],sil ; manual RIP-relative addressing): the expression after
rip+ is the displacement. The correct spellings are
[v] (automatic) or
{rip} /
use rip to force the encoding — I'm not proposing any change to that.
The suggestion: a manual RIP displacement that is not an absolute quantity has no meaningful encoding in any output format, so reject it at the instruction instead of letting it become a bogus relocation (object formats) or a late cryptic error. In
include/x86-2.inc:
--- a/include/x86-2.inc
+++ b/include/x86-2.inc
@@ -604,10 +604,15 @@
rip_relative_address:
+ check displacement relativeto 0
+ jno invalid_rip_displacement
compute mode, 0 scaleof (1 metadataof address_registers) shl 3
compute mod, 0
compute rm, 5
compute displacement_size, 4
exit
+ invalid_rip_displacement:
+ err 'displacement in manual RIP-relative addressing must be absolute'
+ exit
What I verified changes and doesn't change (fasm2 g.l7xm, all cases tested):
- Unchanged: [rip+3], [rip], [rip-7], [rip+b-a] (label differences), and [rip+label] under a numeric org (labels are plain numbers there — bit-for-bit fasm 1 compatible). The automatic [sym] path and use norip absolute addressing (legitimate ADDR32) go through direct_address, not this path, and are untouched.
- New error: [rip+sym] in relocatable outputs (COFF/ELF), which today emits the silent bad relocation; and [rip+label] with an element-based org (PIC-style), which today fails anyway but with Error: variable term used where not expected. at the data-emission layer instead of at the instruction.
- Not caught (deliberately): fixed-base PE, where labels reduce to plain numbers — same literal-VA displacement fasm 1 produces. The check only fires where the displacement cannot reduce to a number at all.
The caveat I can't rule out alone: this is a strictness increase over fasm 1, not parity — fasm 1 also emits the ADDR32-on-RIP combination for COFF. I can't construct a program where
EA = next_instruction + relocated_VA is what anyone wants, but if there's a legitimate pattern relying on it (some loader-delta trick?), the check would break it. That's the question, really: is there any intended use of a relocatable term in a manual RIP displacement, or is it safe to call it an error?