mirror of
https://github.com/netwide-assembler/nasm.git
synced 2025-03-31 18:20:22 +08:00
Allow relative references to external symbols in data
Allow constructs like: dd foo - $ ... where foo is an external symbol. Currently this is only implemented for extops, i.e. dx opcodes. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
This commit is contained in:
parent
6600eb1188
commit
472a7c1d17
@ -322,12 +322,15 @@ static void out(struct out_data *data)
|
||||
if (!data->size)
|
||||
return; /* Nothing to do */
|
||||
|
||||
/*
|
||||
* Convert addresses to RAWDATA if possible
|
||||
* XXX: not all backends want this for global symbols!!!!
|
||||
*/
|
||||
switch (data->type) {
|
||||
case OUT_ADDRESS:
|
||||
asize = data->size;
|
||||
nasm_assert(asize <= 8);
|
||||
if (data->tsegment == NO_SEG && data->twrt == NO_SEG) {
|
||||
/* Convert to RAWDATA */
|
||||
/* XXX: check for overflow */
|
||||
uint8_t *q = xdata.b;
|
||||
|
||||
@ -342,7 +345,6 @@ static void out(struct out_data *data)
|
||||
asize = data->size;
|
||||
nasm_assert(asize <= 8);
|
||||
if (data->tsegment == data->segment && data->twrt == NO_SEG) {
|
||||
/* Convert to RAWDATA */
|
||||
uint8_t *q = xdata.b;
|
||||
int64_t delta = data->toffset - data->offset
|
||||
- (data->inslen - data->insoffs);
|
||||
@ -535,7 +537,7 @@ int64_t assemble(int32_t segment, int64_t start, int bits, iflag_t cp,
|
||||
" instruction");
|
||||
} else {
|
||||
data.insoffs = 0;
|
||||
data.type = OUT_ADDRESS;
|
||||
data.type = e->relative ? OUT_RELADDR : OUT_ADDRESS;
|
||||
data.inslen = data.size = wsize;
|
||||
data.toffset = e->offset;
|
||||
data.tsegment = e->segment;
|
||||
|
72
asm/parser.c
72
asm/parser.c
@ -1,6 +1,6 @@
|
||||
/* ----------------------------------------------------------------------- *
|
||||
*
|
||||
* Copyright 1996-2013 The NASM Authors - All Rights Reserved
|
||||
* Copyright 1996-2016 The NASM Authors - All Rights Reserved
|
||||
* See the file AUTHORS included with the NASM distribution for
|
||||
* the specific copyright holders.
|
||||
*
|
||||
@ -254,7 +254,7 @@ static int parse_mref(operand *op, const expr *e)
|
||||
|
||||
if (is_gpr && e->value == 1)
|
||||
b = e->type; /* It can be basereg */
|
||||
else /* No, it has to be indexreg */
|
||||
else /* No, it has to be indexreg */
|
||||
i = e->type, s = e->value;
|
||||
e++;
|
||||
}
|
||||
@ -375,6 +375,59 @@ static void mref_set_optype(operand *op)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an expression vector returned from evaluate() into an
|
||||
* extop structure. Return zero on success.
|
||||
*/
|
||||
static int value_to_extop(expr * vect, extop *eop, int32_t myseg)
|
||||
{
|
||||
eop->type = EOT_DB_NUMBER;
|
||||
eop->offset = 0;
|
||||
eop->segment = eop->wrt = NO_SEG;
|
||||
eop->relative = false;
|
||||
|
||||
for (; vect->type; vect++) {
|
||||
if (!vect->value) /* zero term, safe to ignore */
|
||||
continue;
|
||||
|
||||
if (vect->type < EXPR_SIMPLE) /* false if a register is present */
|
||||
return -1;
|
||||
|
||||
if (vect->type == EXPR_UNKNOWN) /* something we can't resolve yet */
|
||||
return 0;
|
||||
|
||||
if (vect->type == EXPR_SIMPLE) {
|
||||
/* Simple number expression */
|
||||
eop->offset += vect->value;
|
||||
continue;
|
||||
}
|
||||
if (eop->wrt == NO_SEG && !eop->relative && vect->type == EXPR_WRT) {
|
||||
/* WRT term */
|
||||
eop->wrt = vect->value;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (eop->wrt == NO_SEG && !eop->relative &&
|
||||
vect->type == EXPR_SEGBASE + myseg && vect->value == -1) {
|
||||
/* Expression of the form: foo - $ */
|
||||
eop->relative = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (eop->segment == NO_SEG && vect->type >= EXPR_SEGBASE &&
|
||||
vect->value == 1) {
|
||||
eop->segment = vect->type - EXPR_SEGBASE;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Otherwise, badness */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* We got to the end and it was all okay */
|
||||
return 0;
|
||||
}
|
||||
|
||||
insn *parse_line(int pass, char *buffer, insn *result, ldfunc ldef)
|
||||
{
|
||||
bool insn_is_label = false;
|
||||
@ -652,19 +705,10 @@ is_expression:
|
||||
i = tokval.t_type;
|
||||
if (!value) /* Error in evaluator */
|
||||
goto fail;
|
||||
if (is_unknown(value)) {
|
||||
eop->type = EOT_DB_NUMBER;
|
||||
eop->offset = 0; /* doesn't matter what we put */
|
||||
eop->segment = eop->wrt = NO_SEG; /* likewise */
|
||||
} else if (is_reloc(value)) {
|
||||
eop->type = EOT_DB_NUMBER;
|
||||
eop->offset = reloc_value(value);
|
||||
eop->segment = reloc_seg(value);
|
||||
eop->wrt = reloc_wrt(value);
|
||||
} else {
|
||||
if (value_to_extop(value, eop, location.segment)) {
|
||||
nasm_error(ERR_NONFATAL,
|
||||
"operand %d: expression is not simple"
|
||||
" or relocatable", oper_num);
|
||||
"operand %d: expression is not simple or relocatable",
|
||||
oper_num);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ----------------------------------------------------------------------- *
|
||||
*
|
||||
*
|
||||
* Copyright 1996-2016 The NASM Authors - All Rights Reserved
|
||||
* See the file AUTHORS included with the NASM distribution for
|
||||
* the specific copyright holders.
|
||||
@ -14,7 +14,7 @@
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
@ -31,7 +31,7 @@
|
||||
*
|
||||
* ----------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
/*
|
||||
* nasm.h main header file for the Netwide Assembler: inter-module interface
|
||||
*/
|
||||
|
||||
@ -575,6 +575,7 @@ typedef struct operand { /* operand to an instruction */
|
||||
int32_t segment; /* immediate segment, if needed */
|
||||
int64_t offset; /* any immediate number */
|
||||
int32_t wrt; /* segment base it's relative to */
|
||||
bool relative; /* self-relative expression */
|
||||
int eaflags; /* special EA flags */
|
||||
int opflags; /* see OPFLAG_* defines below */
|
||||
decoflags_t decoflags; /* decorator flags such as {...} */
|
||||
@ -582,7 +583,7 @@ typedef struct operand { /* operand to an instruction */
|
||||
|
||||
#define OPFLAG_FORWARD 1 /* operand is a forward reference */
|
||||
#define OPFLAG_EXTERN 2 /* operand is an external reference */
|
||||
#define OPFLAG_UNKNOWN 4 /* operand is an unknown reference
|
||||
#define OPFLAG_UNKNOWN 4 /* operand is an unknown reference
|
||||
* (always a forward reference also)
|
||||
*/
|
||||
|
||||
@ -593,6 +594,7 @@ typedef struct extop { /* extended operand */
|
||||
int64_t offset; /* ... it's given here ... */
|
||||
int32_t segment; /* if it's a number/address, then... */
|
||||
int32_t wrt; /* ... and here */
|
||||
bool relative; /* self-relative expression */
|
||||
enum extop_type type; /* defined above */
|
||||
} extop;
|
||||
|
||||
@ -707,7 +709,7 @@ struct ofmt {
|
||||
/*
|
||||
* Output format flags.
|
||||
*/
|
||||
#define OFMT_TEXT 1 /* Text file format */
|
||||
#define OFMT_TEXT 1 /* Text file format */
|
||||
unsigned int flags;
|
||||
|
||||
int maxbits; /* Maximum segment bits supported */
|
||||
|
11
test/imm.asm
Normal file
11
test/imm.asm
Normal file
@ -0,0 +1,11 @@
|
||||
bits 64
|
||||
|
||||
mov eax,1
|
||||
mov eax,-1
|
||||
mov eax,0x11111111
|
||||
mov ecx,2
|
||||
add ecx,-6
|
||||
add ecx,strict dword -6
|
||||
add ecx,4
|
||||
add ecx,strict dword 4
|
||||
add ecx,10000
|
9
test/reldef.asm
Normal file
9
test/reldef.asm
Normal file
@ -0,0 +1,9 @@
|
||||
bits 64
|
||||
|
||||
extern bar
|
||||
|
||||
section .data
|
||||
foo: dd bar
|
||||
dd foo - $
|
||||
; dd foo*2
|
||||
dd bar - $
|
Loading…
x
Reference in New Issue
Block a user