Officially deprecate implicit DEFAULT ABS, add DEFAULT [FS|GS]:[ABS|REL]

Making DEFAULT ABS the default for 64-bit mode was a real
mistake. Issue a warning so we can eventually change it.

Support making FS: and GS: references also be REL by default.

Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
This commit is contained in:
H. Peter Anvin 2025-09-13 23:15:47 -07:00
parent 014ca9fdb3
commit c719835357
25 changed files with 1080 additions and 5396 deletions

View file

@ -554,30 +554,71 @@ bool process_directives(char *directive)
break;
case D_DEFAULT: /* [DEFAULT] */
{
enum ea_flags relabs_applies = EAF_NOTFSGS;
bool eat_colon = false;
stdscan_reset(value);
tokval.t_type = TOKEN_INVALID;
if (stdscan(NULL, &tokval) != TOKEN_INVALID) {
switch (tokval.t_integer) {
case S_REL:
globl.rel = 1;
while (!bad_param) {
enum token_type type = stdscan(NULL, &tokval);
if (type <= 0)
break;
case S_ABS:
globl.rel = 0;
switch (tokval.t_type) {
case TOKEN_REG:
case TOKEN_SPECIAL:
case TOKEN_PREFIX:
switch (tokval.t_integer) {
case R_FS:
relabs_applies = EAF_FS;
eat_colon = true;
goto next_token;
case R_GS:
relabs_applies = EAF_GS;
eat_colon = true;
goto next_token;
case S_REL:
globl.rel |= relabs_applies;
globl.reldef |= relabs_applies;
break;
case S_ABS:
globl.rel &= ~relabs_applies;
globl.reldef |= relabs_applies;
break;
case P_BND:
globl.bnd = 1;
break;
case P_NOBND:
globl.bnd = 0;
break;
default:
bad_param = true;
break;
}
break;
case P_BND:
globl.bnd = 1;
break;
case P_NOBND:
globl.bnd = 0;
case ',':
break;
case ':':
if (eat_colon) {
eat_colon = false;
goto next_token;
}
/* else fall through */
default:
bad_param = true;
break;
}
} else {
bad_param = true;
eat_colon = false;
relabs_applies = EAF_NOTFSGS;
next_token:
;
}
break;
}
case D_FLOAT:
if (float_option(value)) {

View file

@ -1660,9 +1660,10 @@ static void assemble_file(const char *fname, struct strlist *depend_list)
if (!pass_final())
errflags_never |= ERR_PASS2;
globl.bits = cmd_sb; /* set 'bits' to command line default */
globl.bnd = false;
globl.rel = false;
globl.bits = cmd_sb; /* set 'bits' to command line default */
globl.bnd = false;
globl.rel = 0;
globl.reldef = EAF_FS|EAF_GS; /* For now, don't warn on fs:/gs: absolute */
globl.dollarhex = true;
cpu = cmd_cpu;

View file

@ -312,17 +312,41 @@ static void mref_set_optype(operand *op)
nasm_assert(i == -1 || s > 0);
if (!(op->eaflags & (EAF_FS|EAF_GS)))
op->eaflags |= EAF_NOTFSGS;
if (b != -1) {
opflags_t bclass = nasm_reg_flags[b];
op->type &= bclass | ~RN_L16;
} else if (i == -1) {
int is_rel = globl.bits == 64 &&
!(op->eaflags & EAF_ABS) &&
((globl.rel &&
!(op->eaflags & EAF_FSGS)) ||
(op->eaflags & EAF_REL));
op->type |= is_rel ? IP_REL : MEM_OFFS;
opflags_t flag = MEM_OFFS;
if (globl.bits == 64) {
if (op->eaflags & EAF_ABS) {
/* Do nothing */
} else if (op->eaflags & EAF_REL) {
flag = IP_REL;
} else {
if (globl.rel & op->eaflags)
flag = IP_REL;
if (!(globl.reldef & op->eaflags)) {
static int64_t pass_last_seen;
/*!
*!implicit-abs-deprecated [on] implicit DEFAULT ABS is deprecated
*!
*! warns that in a subsequent version of NASM, the 64-bit default
*! addressing form is likely to change from \c{DEFAULT ABS} to
*! \c{DEFAULT REL}. If absolute addressing is indeed intended, it is
*! strongly recommended to specify \c{DEFAULT ABS} explicitly.
*/
if (pass_count() != pass_last_seen) {
nasm_warn(WARN_IMPLICIT_ABS_DEPRECATED,
"implicit DEFAULT ABS is deprecated");
pass_last_seen = pass_count();
}
}
}
}
op->type |= flag;
}
if (i != -1) {
@ -1130,8 +1154,16 @@ restart_parse:
nasm_nonfatal("instruction has conflicting segment overrides");
} else {
result->prefixes[PPS_SEG] = value->type;
if (IS_FSGS(value->type))
op->eaflags |= EAF_FSGS;
switch (value->type) {
case R_FS:
op->eaflags |= EAF_FS;
break;
case R_GS:
op->eaflags |= EAF_GS;
break;
default:
break;
}
}
i = stdscan(NULL, &tokval); /* then skip the colon */
@ -1157,7 +1189,6 @@ restart_parse:
init_operand(&o2, 0);
if (parse_mref(&o2, value))
goto fail;
if (o2.basereg != -1 && o2.indexreg == -1) {
o2.indexreg = o2.basereg;
o2.scale = 1;

View file

@ -52,6 +52,14 @@ It is the production version of NASM since 2025.
individual topics, as the previous output was just too verbose to be
practical as a quick reference.
\b The implicit \c{DEFAULT ABS} in 64-bit mode is deprecated and may
be changed to \c{REL} in the future. See \k{default}. A warning
is now emitted for this condition.
\b It is now possible to set the \c{REL}/\c{ABS} default for memory
accesses using \c{FS:} or \c{GS:}, see \k{default}.
\H{cl-2.xx} NASM 2 Series
The NASM 2 series added support for x86-64, and was the production

View file

@ -99,18 +99,28 @@ Currently, \c{DEFAULT} can set \c{REL} & \c{ABS} and \c{BND} & \c{NOBND}.
\S{REL & ABS} \i\c{REL} & \i\c{ABS}: RIP-relative addressing
This sets whether registerless instructions in 64-bit mode are \c{RIP}-relative
or not. By default, they are absolute unless overridden with the \i\c{REL}
specifier (see \k{effaddr}). However, if \c{DEFAULT REL} is
specified, \c{REL} is default, unless overridden with the \c{ABS}
specifier, \e{except when used with an FS or GS segment override}.
This sets whether registerless instructions in 64-bit mode are
\c{RIP}-relative or not. By default, they are absolute unless
overridden with the \i\c{REL} specifier (see \k{effaddr}). However,
if \c{DEFAULT REL} is specified, \c{REL} is default, unless overridden
with the \c{ABS} specifier, \e{except when used with an FS or GS
segment override}.
\c{DEFAULT REL} is disabled with \c{DEFAULT ABS}.
The special handling of \c{FS} and \c{GS} overrides are due to the
fact that these registers are generally used as thread pointers or
other special functions in 64-bit mode, and generating
\c{RIP}-relative addresses would be extremely confusing.
\c{RIP}-relative addresses is not desired on most platforms.
\c{DEFAULT REL} is disabled with \c{DEFAULT ABS}.
To specify that \c{FS}- or \c{GS}-relative addresses \e{should} also
be generated as \c{RIP}-relative, specify the \c{ABS} or \c{REL}
keyword with an \c{FS:} or \c{GS:} prefix:
\c DEFAULT REL, FS:ABS, GS:REL
... will make \c{FS}-relative references default to absolute, but all
others, including \c{GS}-relative references, \c{RIP}-relative.
\c{DEFAULT REL} is likely to become the default setting in a future
version of NASM. Specify \c{DEFAULT ABS} explicitly if you need your

View file

@ -224,6 +224,7 @@ enum token_type { /* token types, other than chars */
TOKEN_EQ = '=', /* = or == */
TOKEN_GT = '>',
TOKEN_LT = '<',
TOKEN_COLON = ':',
/* Multi-character operators */
TOKEN_SHL = 256, /* << or <<< */
@ -695,9 +696,11 @@ enum ea_flags { /* special EA flags */
EAF_TIMESTWO = 4, /* really do EAX*2 not EAX+EAX */
EAF_REL = 8, /* IP-relative addressing */
EAF_ABS = 16, /* non-IP-relative addressing */
EAF_FSGS = 32, /* fs/gs segment override present */
EAF_MIB = 64, /* mib operand */
EAF_SIB = 128 /* SIB encoding obligatory */
EAF_MIB = 32, /* mib operand */
EAF_SIB = 64, /* SIB encoding obligatory */
EAF_NOTFSGS = 128, /* no fs: or gs: */
EAF_FS = 256, /* fs segment override present */
EAF_GS = 512 /* gs segment override present */
};
enum eval_hint { /* values for `hinttype' */
@ -1583,7 +1586,8 @@ extern enum optimization optimizing;
/* Pass-wide state; reset on top of each pass */
struct globalopt {
int bits; /* 16, 32 or 64-bit mode */
bool rel; /* default to relative addressing? */
enum ea_flags rel; /* default to relative addressing? */
enum ea_flags reldef; /* default rel/abs explicitly defined? */
bool bnd; /* default to using bnd prefix? */
bool dollarhex; /* $-prefixed hexadecimal numbers? */
};

File diff suppressed because it is too large Load diff

View file

@ -3,9 +3,20 @@
bits 64
default rel
default rel, fs:abs, gs:rel
mov dword [foo],12345678h
mov qword [foo],12345678h
mov [foo],rax
mov dword [foo],12345678h
mov dword [es:foo],12345678h
mov qword [es:foo],12345678h
mov [es:foo],rax
mov dword [fs:foo],12345678h
mov qword [fs:foo],12345678h
mov [fs:foo],rax
mov dword [gs:foo],12345678h
mov qword [gs:foo],12345678h
mov [gs:foo],rax
foo:

View file

@ -6,7 +6,8 @@
"source": "br2030823.asm",
"option": "-Ox",
"target": [
{ "output": "br2030823.bin" }
{ "output": "br2030823.bin" },
{ "stderr": "br2030823.stderr" }
]
}
]

View file

@ -0,0 +1 @@
./travis/test/br2030823.asm:2: warning: implicit DEFAULT ABS is deprecated [-w+implicit-abs-deprecated]

View file

@ -5,7 +5,8 @@
"format": "bin",
"source": "lar_lsl.asm",
"target": [
{ "output": "lar_lsl.bin" }
{ "output": "lar_lsl.bin" },
{ "stderr": "lar_lsl.stderr" }
]
}
]

View file

@ -0,0 +1,2 @@
./travis/test/lar_lsl.asm:98: warning: implicit DEFAULT ABS is deprecated [-w+implicit-abs-deprecated]
./travis/test/lar_lsl.asm:81: ... from macro `m' defined here

View file

@ -6,7 +6,8 @@
"source": "mmxsize.asm",
"option": "-Ox",
"target": [
{ "output": "mmxsize.bin" }
{ "output": "mmxsize.bin" },
{ "stderr": "mmxsize.stderr" }
]
},
{

View file

@ -0,0 +1 @@
./travis/test/mmxsize.asm:19: warning: implicit DEFAULT ABS is deprecated [-w+implicit-abs-deprecated]

View file

@ -6,7 +6,8 @@
"source": "mpx-64.asm",
"option": "-O0",
"target": [
{ "output": "mpx-64.o" }
{ "output": "mpx-64.o" },
{ "stderr": "mpx-64.stderr" }
]
}
]

View file

@ -0,0 +1 @@
./travis/test/mpx-64.asm:5: warning: implicit DEFAULT ABS is deprecated [-w+implicit-abs-deprecated]

View file

@ -6,7 +6,8 @@
"source": "ssesize.asm",
"option": "-Ox",
"target": [
{ "output": "ssesize.o" }
{ "output": "ssesize.o" },
{ "stderr": "ssesize.stderr" }
]
}
]

View file

@ -0,0 +1 @@
./travis/test/ssesize.asm:3: warning: implicit DEFAULT ABS is deprecated [-w+implicit-abs-deprecated]

View file

@ -6,7 +6,8 @@
"source": "test67.asm",
"option": "-Ox",
"target": [
{ "output": "test67.bin" }
{ "output": "test67.bin" },
{ "stderr": "test67.stderr" }
]
},
{

View file

@ -0,0 +1 @@
./travis/test/test67.asm:27: warning: implicit DEFAULT ABS is deprecated [-w+implicit-abs-deprecated]

View file

@ -1,3 +1,4 @@
./travis/test/vmread.asm:8: warning: implicit DEFAULT ABS is deprecated [-w+implicit-abs-deprecated]
./travis/test/vmread.asm:15: error: invalid operand sizes for instruction
./travis/test/vmread.asm:16: error: invalid operand sizes for instruction
./travis/test/vmread.asm:19: error: instruction not supported in 64-bit mode

View file

@ -5,7 +5,8 @@
"format": "bin",
"source": "vmread.asm",
"target": [
{ "output": "vmread.bin" }
{ "output": "vmread.bin" },
{ "stderr": "vmread.ok.stderr" }
]
},
{
@ -13,7 +14,7 @@
"ref": "vmread",
"option": "-DERROR",
"target": [
{ "stderr": "vmread.stderr" }
{ "stderr": "vmread.err.stderr" }
],
"error": "expected"
}

View file

@ -0,0 +1 @@
./travis/test/vmread.asm:8: warning: implicit DEFAULT ABS is deprecated [-w+implicit-abs-deprecated]

View file

@ -6,7 +6,8 @@
"source": "vmx.asm",
"option": "-Ox",
"target": [
{ "output": "vmx.o" }
{ "output": "vmx.o" },
{ "stderr": "vmx.stderr" }
]
}
]

1
travis/test/vmx.stderr Normal file
View file

@ -0,0 +1 @@
./travis/test/vmx.asm:6: warning: implicit DEFAULT ABS is deprecated [-w+implicit-abs-deprecated]