Peter Johnson
2007-09-19 05:44:11 UTC
In going through the new rip relative stuff in NASM, and noticed a few
things:
1. It seems ugly to make an exception for just FS and GS to have an
exception to default-RIP-rel (and the current wording in the NASM manual
is confusing too)... wouldn't it be better to just turn off
default-RIP-rel for ALL segment registers? Particularly seeing as an es
override is ignored with a warning. I would think that if a user is using
*any* segment register, having default RIP-relative would be a surprise.
2. It appears handling of 64-bit movoffs values in default rel mode is
broken in NASM:
default rel
mov rax, [123456789abcdef0h]
mov rax, [qword 123456789abcdef0h]
both mov's generate 32-bit RIP-relative values with no warning. This
feels like a bug... but see #3 for more on what's the *real* issue here.
3. I believe that due to 64-bit movoffs forms being "special" (in allowing
a 64-bit displacement), the use of qword in the [] should force the
displacement size, not the address size (and likewise for dword, which
should force a 32-bit displacement size). Note displacement size can be
different than address size in 64-bit mode (okay, only for the movoffs
form, but consistency is good across the board)! Is there a current way
in NASM's world to force either a 32-bit or 64-bit displacement size (NOT
address size!) for mov rax, [...]?
Note that the default in 64-bit mode should be NOT to use the movoffs
form, as this is 4 bytes longer than the modrm-version. Plus a number of
object formats much prefer 32-bit relative offsets rather than the 64-bit
one (win64 for example chokes heavily on 64-bit relocs in the linker
stage, so you'll end up with broken behavior with the current NASM
output).
mov rax, [dword foo] makes the displacement 4 bytes, but generates an a32
prefix on what is still a movoffs form instruction. Not exactly what we
want.
This is why in yasm I use [dword ...] and [qword ...] to force the
displacement size, and a32 and a64 to force the address size, to separate
these two concepts.
So the question is, what should the following example output? (yasm
behavior in comments). Run it through the current NASM and think about
what makes more sense. :)
bits 64
val:
default abs
mov rax, [val] ; 48 8b ... (32-bit disp)
mov rax, [dword val] ; 48 8b ... (32-bit disp)
mov rax, [qword val] ; 48 a1 ... (64-bit disp)
a32 mov rax, [val] ; 67 48 a1 ... (32-bit disp)
a32 mov rax, [dword val] ; 67 48 a1 ... (32-bit disp)
a32 mov rax, [qword val] ; 67 48 a1 ... (32-bit disp)
; [this one is debatable on correctness,
; I chose in yasm to make a32 override]
a64 mov rax, [val] ; 48 8b ... (32-bit disp)
a64 mov rax, [dword val] ; 48 8b ... (32-bit disp)
a64 mov rax, [qword val] ; 48 a1 ... (64-bit disp)
mov rbx, [val] ; 48 8b ... (32-bit disp)
mov rbx, [dword val] ; 48 8b ... (32-bit disp)
mov rbx, [qword val] ; illegal (can't have 64-bit disp)
a32 mov rbx, [val] ; 67 48 8b ... (32-bit disp)
a32 mov rbx, [dword val] ; 67 48 8b ... (32-bit disp)
a32 mov rbx, [qword val] ; illegal (can't have 64-bit disp)
a64 mov rbx, [val] ; 48 8b ... (32-bit disp)
a64 mov rbx, [dword val] ; 48 8b ... (32-bit disp)
a64 mov rbx, [qword val] ; illegal (can't have 64-bit disp)
default rel
; yasm doesn't do this yet, but this is what I think makes sense
mov rax, [val] ; 48 8b ... (32-bit disp, RIP-rel)
mov rax, [dword val] ; 48 8b ... (32-bit disp, RIP-rel)
mov rax, [qword val] ; 48 a1 ... (64-bit disp, ABS)
a32 mov rax, [val] ; 67 48 8b ... (32-bit disp, RIP-rel)
a32 mov rax, [dword val] ; 67 48 8b ... (32-bit disp, RIP-rel)
a32 mov rax, [qword val] ; 67 48 8b ... (32-bit disp, RIP-rel)
; [this one is debatable on correctness,
; I chose in yasm to make a32 override]
a64 mov rax, [val] ; 48 8b ... (32-bit disp, RIP-rel)
a64 mov rax, [dword val] ; 48 8b ... (32-bit disp, RIP-rel)
a64 mov rax, [qword val] ; 48 a1 ... (64-bit disp, ABS)
mov rbx, [val] ; 48 8b ... (32-bit disp, RIP-rel)
mov rbx, [dword val] ; 48 8b ... (32-bit disp, RIP-rel)
mov rbx, [qword val] ; illegal (can't have 64-bit disp)
a32 mov rbx, [val] ; 67 48 8b ... (32-bit disp, RIP-rel)
a32 mov rbx, [dword val] ; 67 48 8b ... (32-bit disp, RIP-rel)
a32 mov rbx, [qword val] ; illegal (can't have 64-bit disp)
a64 mov rbx, [val] ; 48 8b ... (32-bit disp, RIP-rel)
a64 mov rbx, [dword val] ; 48 8b ... (32-bit disp, RIP-rel)
a64 mov rbx, [qword val] ; illegal (can't have 64-bit disp)
Peter
things:
1. It seems ugly to make an exception for just FS and GS to have an
exception to default-RIP-rel (and the current wording in the NASM manual
is confusing too)... wouldn't it be better to just turn off
default-RIP-rel for ALL segment registers? Particularly seeing as an es
override is ignored with a warning. I would think that if a user is using
*any* segment register, having default RIP-relative would be a surprise.
2. It appears handling of 64-bit movoffs values in default rel mode is
broken in NASM:
default rel
mov rax, [123456789abcdef0h]
mov rax, [qword 123456789abcdef0h]
both mov's generate 32-bit RIP-relative values with no warning. This
feels like a bug... but see #3 for more on what's the *real* issue here.
3. I believe that due to 64-bit movoffs forms being "special" (in allowing
a 64-bit displacement), the use of qword in the [] should force the
displacement size, not the address size (and likewise for dword, which
should force a 32-bit displacement size). Note displacement size can be
different than address size in 64-bit mode (okay, only for the movoffs
form, but consistency is good across the board)! Is there a current way
in NASM's world to force either a 32-bit or 64-bit displacement size (NOT
address size!) for mov rax, [...]?
Note that the default in 64-bit mode should be NOT to use the movoffs
form, as this is 4 bytes longer than the modrm-version. Plus a number of
object formats much prefer 32-bit relative offsets rather than the 64-bit
one (win64 for example chokes heavily on 64-bit relocs in the linker
stage, so you'll end up with broken behavior with the current NASM
output).
mov rax, [dword foo] makes the displacement 4 bytes, but generates an a32
prefix on what is still a movoffs form instruction. Not exactly what we
want.
This is why in yasm I use [dword ...] and [qword ...] to force the
displacement size, and a32 and a64 to force the address size, to separate
these two concepts.
So the question is, what should the following example output? (yasm
behavior in comments). Run it through the current NASM and think about
what makes more sense. :)
bits 64
val:
default abs
mov rax, [val] ; 48 8b ... (32-bit disp)
mov rax, [dword val] ; 48 8b ... (32-bit disp)
mov rax, [qword val] ; 48 a1 ... (64-bit disp)
a32 mov rax, [val] ; 67 48 a1 ... (32-bit disp)
a32 mov rax, [dword val] ; 67 48 a1 ... (32-bit disp)
a32 mov rax, [qword val] ; 67 48 a1 ... (32-bit disp)
; [this one is debatable on correctness,
; I chose in yasm to make a32 override]
a64 mov rax, [val] ; 48 8b ... (32-bit disp)
a64 mov rax, [dword val] ; 48 8b ... (32-bit disp)
a64 mov rax, [qword val] ; 48 a1 ... (64-bit disp)
mov rbx, [val] ; 48 8b ... (32-bit disp)
mov rbx, [dword val] ; 48 8b ... (32-bit disp)
mov rbx, [qword val] ; illegal (can't have 64-bit disp)
a32 mov rbx, [val] ; 67 48 8b ... (32-bit disp)
a32 mov rbx, [dword val] ; 67 48 8b ... (32-bit disp)
a32 mov rbx, [qword val] ; illegal (can't have 64-bit disp)
a64 mov rbx, [val] ; 48 8b ... (32-bit disp)
a64 mov rbx, [dword val] ; 48 8b ... (32-bit disp)
a64 mov rbx, [qword val] ; illegal (can't have 64-bit disp)
default rel
; yasm doesn't do this yet, but this is what I think makes sense
mov rax, [val] ; 48 8b ... (32-bit disp, RIP-rel)
mov rax, [dword val] ; 48 8b ... (32-bit disp, RIP-rel)
mov rax, [qword val] ; 48 a1 ... (64-bit disp, ABS)
a32 mov rax, [val] ; 67 48 8b ... (32-bit disp, RIP-rel)
a32 mov rax, [dword val] ; 67 48 8b ... (32-bit disp, RIP-rel)
a32 mov rax, [qword val] ; 67 48 8b ... (32-bit disp, RIP-rel)
; [this one is debatable on correctness,
; I chose in yasm to make a32 override]
a64 mov rax, [val] ; 48 8b ... (32-bit disp, RIP-rel)
a64 mov rax, [dword val] ; 48 8b ... (32-bit disp, RIP-rel)
a64 mov rax, [qword val] ; 48 a1 ... (64-bit disp, ABS)
mov rbx, [val] ; 48 8b ... (32-bit disp, RIP-rel)
mov rbx, [dword val] ; 48 8b ... (32-bit disp, RIP-rel)
mov rbx, [qword val] ; illegal (can't have 64-bit disp)
a32 mov rbx, [val] ; 67 48 8b ... (32-bit disp, RIP-rel)
a32 mov rbx, [dword val] ; 67 48 8b ... (32-bit disp, RIP-rel)
a32 mov rbx, [qword val] ; illegal (can't have 64-bit disp)
a64 mov rbx, [val] ; 48 8b ... (32-bit disp, RIP-rel)
a64 mov rbx, [dword val] ; 48 8b ... (32-bit disp, RIP-rel)
a64 mov rbx, [qword val] ; illegal (can't have 64-bit disp)
Peter