NASM 0.98p3

This commit is contained in:
H. Peter Anvin 2002-04-30 20:53:55 +00:00
parent 87bc61964c
commit eba20a73f2
34 changed files with 7251 additions and 2433 deletions

94
Changes
View File

@ -442,3 +442,97 @@ corruption at ends of long PUBDEF records.
Separated DOS archives into main-program and documentation to reduce
download size.
0.98 not released yet
---------------------
Fixed a bug whereby STRUC didn't work at all in RDF.
Fixed a problem with group specification in PUBDEFs in OBJ.
Improved ease of adding new output formats. Contribution due to
Fox Cutter.
Fixed a bug in relocations in the `bin' format: was showing up when
a relocatable reference crossed an 8192-byte boundary in any output
section.
Fixed a bug in local labels: local-label lookups were inconsistent
between passes one and two if an EQU occurred between the definition
of a global label and the subsequent use of a local label local to
that global.
Fixed a seg-fault in the preprocessor (again) which happened when
you use a blank line as the first line of a multi-line macro
definition and then defined a label on the same line as a call to
that macro.
Fixed a stale-pointer bug in the handling of the NASM environment
variable. Thanks to Thomas McWilliams.
ELF had a hard limit on the number of sections which caused
segfaults when transgressed. Fixed.
Added ability for ndisasm to read from stdin by using `-' as the
filename.
ndisasm wasn't outputting the TO keyword. Fixed.
Fixed error cascade on bogus expression in %if - an error in
evaluation was causing the entire %if to be discarded, thus creating
trouble later when the %else or %endif was encountered.
Forward reference tracking was instruction-granular not operand-
granular, which was causing 286-specific code to be generated
needlessly on code of the form `shr word [forwardref],1'. Thanks to
Jim Hague for sending a patch.
All messages now appear on stdout, as sending them to stderr serves
no useful purpose other than to make redirection difficult.
Fixed the problem with EQUs pointing to an external symbol - this
now generates an error message.
Allowed multiple size prefixes to an operand, of which only the first
is taken into account.
Incorporated John Fine's changes, including fixes of a large number
of preprocessor bugs, some small problems in OBJ, and a reworking of
label handling to define labels before their line is assembled, rather
than after.
Reformatted a lot of the source code to be more readable. Included
'coding.txt' as a guideline for how to format code for contributors.
Stopped nested %reps causing a panic - they now cause a slightly more
friendly error message instead.
Fixed floating point constant problems (patch by Pedro Gimeno)
Fixed the return value of insn_size() not being checked for -1, indicating
an error.
Incorporated 3D now instructions.
Fixed the 'mov eax, eax + ebx' bug.
Fixed the GLOBAL EQU bug in ELF. Released developers release 3.
Incorporated John Fine's command line parsing changes
Incorporated David Lindauer's OMF debug support
Made changes for LCC 4.0 support (__NASM_CDecl__, removed register size
specification warning when sizes agree).
Released NASM 0.98 Pre-release 1
fixed bug in outcoff.c to do with truncating section names longer
than 8 characters, referencing beyond end of string; 0.98 pre-release 2
added response file support, improved command line handling, new layout
help screen
fixed limit checking bug, 'OUT byte nn, reg' bug, and a couple of rdoff
related bugs, updated Wishlist; 0.98 Prerelease 3.

225
Wishlist
View File

@ -1,23 +1,168 @@
NASM Wishlist
=============
- forward-reference tracking is instruction-granular not operand-
granular. Bummer.
Numbers on right hand side are version numbers that it would be nice to
have this done by. ? means I haven't looked at it yet.
- see if BITS can be made to do anything sensible in obj (eg set the
- Create a binary RDF tools distribution. Should probably be distributed 0.98
seperately.
- Check misc/ide.cfg into RCS as Watcom IDE enhancement thingy. 0.98
(nop@dlc.fi)
- Package the Linux Assembler HOWTO. 0.98
- AMD 3dNow extensions need documenting. 0.98
- prototypes of lrotate don't match in test/*. Fix. 0.98
- Build djgpp binaries for 0.98 onwards. Look into PMODE/W as a stub 0.98
- it might be a lot better than CWSDPMI. It's in PMW133.ZIP.
- Fix `%error' giving error messages twice. 0.99
Not especially important, as changes planned for 1.1x below will make
the preprocessor be only called once.
- Sort out problems with OBJ: 0.99
* TLINK32 doesn't seem to like SEGDEF32 et al. So for that, we
should avoid xxx32 records wherever we can.
* However, didn't we change _to_ using xxx32 at some stage? Try
to remember why and when.
* Apparently Delphi's linker has trouble with two or more
globals being defined inside a PUBDEF32. Don't even know if it
_can_ cope with a PUBDEF16.
* Might need extra flags. *sigh*
- Symbol table output may possibly be useful. 0.99
Ken Martwick (kenm@efn.org) wants the following format:
labelname type offset(hex) repetition count
Possibly include xref addresses after repetition count?
- There are various other bugs in outelf.c that make certain kinds 0.99
of relocation not work. See zbrown.asm. Looks like we may have to do
a major rewrite of parts of it. Compare some NASM code output with
equivalent GAS code output. Look at the ELF spec. Generally fix things.
- NASM is currently using a kludge in ELF that involves defining 0.99
a symbol at a zero absolute offset. This isn't needed, as the
documented solution to the problem that this solves is to use
SHN_UNDEF.
- Debug information, in all formats it can be usefully done in. 0.99
* including line-number record support.
* "George C. Lindauer" <gclind01@starbase.spd.louisville.edu>
wants to have some say in how this goes through.
* Andrew Crabtree <andrewc@rosemail.rose.hp.com> wants to help out.
- Think about a line-continuation character. 0.99
- Consider allowing declaration of two labels on the same line,
syntax 'label1[:] label2[:] ... instruction'. Need to investigate
feasibility. 0.99
- Quoting of quotes by doubling them, in string and char constants. 0.99
- Two-operand syntax for SEGMENT/SECTION macro to avoid warnings 0.99
of ignored section parameters on reissue of __SECT__.
Or maybe skip the warning if the given parameters are identical to
what was actually stored. Investigate.
- Apparently we are not missing a PSRAQ instruction, because it
doesn't exist. Check that it doesn't exist as an undocumented
instruction, or something stupid like that. 0.99
- Any assembled form starting 0x80 can also start 0x82. ndisasm 1.00
should know this. New special code in instruction encodings,
probably.
- Pointing an EQU at an external symbol now generates an error. There 1.05
may be a better way of handling this; we should look into it.
Ideally, the label mechanism should be changed to cope with one
label being declared relative to another - that may work, but could be
a pain to implement (or is it? it may be easy enough that you just
need to declare a new offset in the same segment...) This should be done
before v1.0 is released. There is a comment regarding this in labels.c,
towards the end of the file, which discusses ways of fixing this.
- nested %rep used to cause a panic. Now a more informative error 1.10
message is produced. This problem whould be fixed before v1.0.
See comment in switch() statement block for PP_REP in do_directive()
in preproc.c (line 1585, or thereabouts)
- Contribution: zgraeme.tar contains improved hash table routines ?
contributed by Graeme Defty <graeme@HK.Super.NET> for use in the
label manager.
- Contribution: zsyntax.zip contains a syntax-highlighting mode for ?
NASM, for use with the Aurora text editor (??).
- Contribution: zvim.zip contains a syntax-highlighting mode for ?
NASM, for use with vim.
- Contribution: zkendal1.zip and zkendal2.zip contain Kendall ?
Bennett's (<KendallB@scitechsoft.com>) alternative syntax stuff,
providing an alternative syntax mode for NASM which allows a macro
set to be written that allows the same source files to be
assembled with NASM and TASM.
- Add the UD2 instruction. ?
- Add the four instructions documented in 24368901.pdf (Intel's own ?
document).
- Some means of avoiding MOV memoffs,EAX which apparently the 1.10?
Pentium pairing detector thinks modifies EAX. Similar means of
choosing instruction encodings where necessary.
- The example of ..@ makes it clear that a ..@ label isn't just ?
local, but doesn't make it clear that it isn't just global either.
- hpa wants an evaluator operator for ceil(log2(x)). ?
- Extra reloc types in ELF: R_386_16 type 20, PC16 is 21, 8 is 22, PC8 is 23.
Add support for the 16s at least. ?
- Lazy section creation or selective section output, in COFF/win32 ?
at least and probably other formats: don't bother to emit a section
if it contains no data. Particularly the default auto-created
section. We believe zero-length sections crash at least WLINK (in
win32).
- Make the flags field in `struct itemplate' in insns.h a long ?
instead of an int.
- Implement %ifref to check whether a single-line macro has ever been ?
expanded since (last re) definition. Or maybe not. We'll see.
- add pointer to \k{insLEAVE} and \k{insENTER} in chapters about ?
mixed-language programming.
- Some equivalent to TASM's GLOBAL directive, ie something which ?
defines a symbol as external if it doesn't end up being defined
but defines it as public if it does end up being defined.
- Documentation doesn't explain about C++ name mangling. ?
- see if BITS can be made to do anything sensible in obj (eg set the ?
default new-segment property to Use32).
- __DATE__, __TIME__, and text variants of __NASM_MAJOR__ and
- OBJ: coalesce consecutive offset and segment fixups for the same ?
location into full-32bit-pointer fixups. This is apparently
necessary because some twazzock in the PowerBASIC development
team didn't deign to support the OMF spec the way the rest of the
world sees it.
- Allow % to be separated from the rest of a preproc directive, for ?
alternative directive indentation styles.
- __DATE__, __TIME__, and text variants of __NASM_MAJOR__ and ?
__NASM_MINOR__.
- Warn on TIMES combined with multi-line macros. TIMES gets applied
- Warn on TIMES combined with multi-line macros. TIMES gets applied 1.00
to first line only - should bring to users' attention.
- Add support for lcc 4.0.
* If-when this happens, remember to bump the `supported lcc
version' number in Readme.
- Re-work the evaluator, again, with a per-object-format fixup
- Re-work the evaluator, again, with a per-object-format fixup 1.10
routine, so as to be able to cope with section offsets "really"
being pure numbers; should be able to allow at _least_ the two
common idioms
@ -28,17 +173,33 @@ NASM Wishlist
had to. (_Always_ returning UNKNOWN on pass one, though a lovely
clean design, breaks the first of the above examples.)
- Preprocessor identifier concatenation?
- Preprocessor identifier concatenation? 1.10
- Arbitrary section names in `bin'.
- Arbitrary section names in `bin'. ?
Is this necessary? Is it even desirable?
- Ability to read from a pipe. Obviously not useful under dos, so
- Ability to read from a pipe. Obviously not useful under dos, so 1.10
memory problems with storing entire input file aren't a problem
either.
- Subsection support?
Related topic: file caching under DOS/32 bit... 1.10?
maybe even implement discardable buffers that get thrown away
when we get a NULL returned from malloc(). Only really useful under
DOS. Think about it.
- A good ALIGN mechanism, similar to GAS's. GAS pads out space by
Another related topic: possibly spool out the pre-processed 1.10?
stuff to a file, to avoid having to re-process it. Possible problems
with preprocessor values not known on pass 1? Have a look...
Or maybe we can spool out a pre-parsed version...? 1.10
Need to investigate feasibility. Does the results from the parser
change from pass 1 to pass 2? Would it be feasible to alter it so that
the parser returns an invariant result, and this is then processed
afterwards to resolve label references, etc?
- Subsection support? ?
- A good ALIGN mechanism, similar to GAS's. GAS pads out space by 1.10?
means of the following (32-bit) instructions:
8DB42600000000 lea esi,[esi+0x0]
8DB600000000 lea esi,[esi+0x0]
@ -55,7 +216,7 @@ NASM Wishlist
Also re-work the macro form so that when given one argument in a
code section it calls this feature.
- Possibly a means whereby FP constants can be specified as
- Possibly a means whereby FP constants can be specified as ?
immediate operands to non-FP instructions.
* Possible syntax: MOV EAX,FLOAT 1.2 to get a single-precision FP
constant. Then maybe MOV EAX,HI_FLOAT 1.2 and MOV EAX,LO_FLOAT
@ -67,37 +228,41 @@ NASM Wishlist
chunks, one-byte chunks, even stranger chunks, and pieces of
ten-byte reals to be bandied around as well.
- A UNION macro might be quite cool, now that ABSOLUTE is sane
- A UNION macro might be quite cool, now that ABSOLUTE is sane ?
enough to be able to handle it.
- An equivalent to gcc's ## stringify operator, plus string
- An equivalent to gcc's ## stringify operator, plus string ?
concatenation, somehow implemented without undue ugliness, so as
to be able to do `%include "/my/path/%1"' in a macro, or something
similar...
- Actually _do_ something with the processor, privileged and
undocumented flags in the instruction table.
- Actually _do_ something with the processor, privileged and 1.10
undocumented flags in the instruction table. When this happens,
consider allowing PMULHRW to map to either of the Cyrix or AMD
versions?
- Maybe NEC V20/V30 instructions?
- Maybe NEC V20/V30 instructions? ?
- Yet more object formats.
* Possibly direct support for .EXE files?
* Possibly direct support for .EXE files? 1.10
- Debug information, in all formats it can be usefully done in.
* including line-number record support.
- Symbol map in binary format. Format-specific options... 1.10?
- Symbol map in binary format. Format-specific options...
- REDESIGN: Think about EQU dependency, and about start-point
- REDESIGN: Think about EQU dependency, and about start-point 1.20?
specification in OBJ. Possibly re-think directive support.
- Think about a wrapper program like gcc? Possibly invent a _patch_
- Think about a wrapper program like gcc? Possibly invent a _patch_ 2.00?
for gcc so that it can take .asm files on the command line?
- If a wrapper happens, think about adding an option to cause the
- If a wrapper happens, think about adding an option to cause the ?
resulting executable file to be executed immediately, thus
allowing NASM source files to have #!... (probably silly)
- Multi-platform support? If so: definitely Alpha; possibly Java
- Multi-platform support? If so: definitely Alpha; possibly Java ?
byte code; probably ARM/StrongARM; maybe Sparc; maybe Mips; maybe
Vax. Perhaps Z80 and 6502, just for a laugh?
- Consider a 'verbose' option that prints information about the resulting ?
object file onto stdout.

File diff suppressed because it is too large Load Diff

View File

@ -33,7 +33,8 @@ extern struct itemplate **itable[];
#define SEG_NODISP 64
#define SEG_SIGNED 128
static int whichreg(long regflags, int regval) {
static int whichreg(long regflags, int regval)
{
static int reg32[] = {
R_EAX, R_ECX, R_EDX, R_EBX, R_ESP, R_EBP, R_ESI, R_EDI };
static int reg16[] = {
@ -98,7 +99,8 @@ static int whichreg(long regflags, int regval) {
return 0;
}
static char *whichcond(int condval) {
static char *whichcond(int condval)
{
static int conds[] = {
C_O, C_NO, C_C, C_NC, C_Z, C_NZ, C_NA, C_A,
C_S, C_NS, C_PE, C_PO, C_L, C_NL, C_NG, C_G
@ -110,7 +112,8 @@ static char *whichcond(int condval) {
* Process an effective address (ModRM) specification.
*/
static unsigned char *do_ea (unsigned char *data, int modrm, int asize,
int segsize, operand *op) {
int segsize, operand *op)
{
int mod, rm, scale, index, base;
mod = (modrm >> 6) & 03;
@ -249,11 +252,13 @@ static unsigned char *do_ea (unsigned char *data, int modrm, int asize,
* stream in data. Return the number of bytes matched if so.
*/
static int matches (unsigned char *r, unsigned char *data, int asize,
int osize, int segsize, insn *ins) {
unsigned char *origdata = data;
int a_used = FALSE, o_used = FALSE;
int osize, int segsize, insn *ins)
{
unsigned char * origdata = data;
int a_used = FALSE, o_used = FALSE;
while (*r) {
while (*r)
{
int c = *r++;
if (c >= 01 && c <= 03) {
while (c--)
@ -440,7 +445,8 @@ static int matches (unsigned char *r, unsigned char *data, int asize,
}
long disasm (unsigned char *data, char *output, int segsize, long offset,
int autosync) {
int autosync)
{
struct itemplate **p;
int length = 0;
char *segover;
@ -486,7 +492,8 @@ long disasm (unsigned char *data, char *output, int segsize, long offset,
works = TRUE;
for (p = itable[*data]; *p; p++)
if ( (length = matches((unsigned char *)((*p)->code), data,
asize, osize, segsize, &ins)) ) {
asize, osize, segsize, &ins)) )
{
works = TRUE;
/*
* Final check to make sure the types of r/m match up.
@ -507,11 +514,17 @@ long disasm (unsigned char *data, char *output, int segsize, long offset,
((((*p)->opd[i] & (REGISTER | FPUREG)) ||
(ins.oprs[i].segment & SEG_RMREG)) &&
!whichreg ((*p)->opd[i], ins.oprs[i].basereg)))
{
works = FALSE;
/*
* FIXME: can we do a break here?
*/
}
if (works)
break;
}
if (!length || !works)
return 0; /* no instruction was matched */
@ -570,9 +583,12 @@ long disasm (unsigned char *data, char *output, int segsize, long offset,
colon = FALSE;
if (((*p)->opd[i] & (REGISTER | FPUREG)) ||
(ins.oprs[i].segment & SEG_RMREG)) {
(ins.oprs[i].segment & SEG_RMREG))
{
ins.oprs[i].basereg = whichreg ((*p)->opd[i],
ins.oprs[i].basereg);
if ( (*p)->opd[i] & TO )
slen += sprintf(output+slen, "to ");
slen += sprintf(output+slen, "%s",
reg_names[ins.oprs[i].basereg-EXPR_REG_START]);
} else if (!(UNITY & ~(*p)->opd[i])) {
@ -680,7 +696,8 @@ long disasm (unsigned char *data, char *output, int segsize, long offset,
return length;
}
long eatbyte (unsigned char *data, char *output) {
long eatbyte (unsigned char *data, char *output)
{
sprintf(output, "db 0x%02X", *data);
return 1;
}

241
eval.c
View File

@ -17,37 +17,56 @@
#include "nasm.h"
#include "nasmlib.h"
#include "eval.h"
#include "labels.h"
static expr **tempexprs = NULL;
static int ntempexprs, tempexprs_size = 0;
#define TEMPEXPRS_DELTA 128
static expr *tempexpr;
static int ntempexpr, tempexpr_size;
#define TEMPEXPR_DELTA 8
static scanner scan;
static scanner scan; /* Address of scanner routine */
static efunc error; /* Address of error reporting routine */
static lfunc labelfunc; /* Address of label routine */
static struct ofmt *outfmt; /* Structure of addresses of output routines */
static expr **tempexprs = NULL;
static int ntempexprs;
static int tempexprs_size = 0;
static expr *tempexpr;
static int ntempexpr;
static int tempexpr_size;
static struct tokenval *tokval; /* The current token */
static int i; /* The t_type of tokval */
static void *scpriv;
static struct tokenval *tokval;
static efunc error;
static int i;
static int seg, ofs;
static char *label = NULL, special_empty_string[] = "";
static lfunc labelfunc;
static struct ofmt *outfmt;
static int *forward;
static loc_t *location; /* Pointer to current line's segment,offset */
static int *opflags;
static struct eval_hints *hint;
/*
* Unimportant cleanup is done to avoid confusing people who are trying
* to debug real memory leaks
*/
void eval_cleanup(void)
{
while (ntempexprs)
nasm_free (tempexprs[--ntempexprs]);
nasm_free (tempexprs);
}
/*
* Construct a temporary expression.
*/
static void begintemp(void) {
static void begintemp(void)
{
tempexpr = NULL;
tempexpr_size = ntempexpr = 0;
}
static void addtotemp(long type, long value) {
static void addtotemp(long type, long value)
{
while (ntempexpr >= tempexpr_size) {
tempexpr_size += TEMPEXPR_DELTA;
tempexpr = nasm_realloc(tempexpr,
@ -57,7 +76,8 @@ static void addtotemp(long type, long value) {
tempexpr[ntempexpr++].value = value;
}
static expr *finishtemp(void) {
static expr *finishtemp(void)
{
addtotemp (0L, 0L); /* terminate */
while (ntempexprs >= tempexprs_size) {
tempexprs_size += TEMPEXPRS_DELTA;
@ -72,7 +92,8 @@ static expr *finishtemp(void) {
* absolute segment types: we preserve them during addition _only_
* if one of the segments is a truly pure scalar.
*/
static expr *add_vectors(expr *p, expr *q) {
static expr *add_vectors(expr *p, expr *q)
{
int preserve;
preserve = is_really_simple(p) || is_really_simple(q);
@ -81,7 +102,8 @@ static expr *add_vectors(expr *p, expr *q) {
while (p->type && q->type &&
p->type < EXPR_SEGBASE+SEG_ABS &&
q->type < EXPR_SEGBASE+SEG_ABS) {
q->type < EXPR_SEGBASE+SEG_ABS)
{
int lasttype;
if (p->type > q->type) {
@ -91,7 +113,9 @@ static expr *add_vectors(expr *p, expr *q) {
addtotemp(p->type, p->value);
lasttype = p++->type;
} else { /* *p and *q have same type */
addtotemp(p->type, p->value + q->value);
long sum = p->value + q->value;
if (sum)
addtotemp(p->type, sum);
lasttype = p->type;
p++, q++;
}
@ -100,12 +124,14 @@ static expr *add_vectors(expr *p, expr *q) {
}
}
while (p->type &&
(preserve || p->type < EXPR_SEGBASE+SEG_ABS)) {
(preserve || p->type < EXPR_SEGBASE+SEG_ABS))
{
addtotemp(p->type, p->value);
p++;
}
while (q->type &&
(preserve || q->type < EXPR_SEGBASE+SEG_ABS)) {
(preserve || q->type < EXPR_SEGBASE+SEG_ABS))
{
addtotemp(q->type, q->value);
q++;
}
@ -125,7 +151,8 @@ static expr *add_vectors(expr *p, expr *q) {
* multiplied. This allows [eax*1+ebx] to hint EBX rather than EAX
* as the base register.
*/
static expr *scalar_mult(expr *vect, long scalar, int affect_hints) {
static expr *scalar_mult(expr *vect, long scalar, int affect_hints)
{
expr *p = vect;
while (p->type && p->type < EXPR_SEGBASE+SEG_ABS) {
@ -140,13 +167,15 @@ static expr *scalar_mult(expr *vect, long scalar, int affect_hints) {
return vect;
}
static expr *scalarvect (long scalar) {
static expr *scalarvect (long scalar)
{
begintemp();
addtotemp(EXPR_SIMPLE, scalar);
return finishtemp();
}
static expr *unknown_expr (void) {
static expr *unknown_expr (void)
{
begintemp();
addtotemp(EXPR_UNKNOWN, 1L);
return finishtemp();
@ -157,7 +186,8 @@ static expr *unknown_expr (void) {
* value. Return NULL, as usual, if an error occurs. Report the
* error too.
*/
static expr *segment_part (expr *e) {
static expr *segment_part (expr *e)
{
long seg;
if (is_unknown(e))
@ -228,22 +258,27 @@ static expr *expr4(int), *expr5(int), *expr6(int);
static expr *(*bexpr)(int);
static expr *rexp0(int critical) {
static expr *rexp0(int critical)
{
expr *e, *f;
e = rexp1(critical);
if (!e)
return NULL;
while (i == TOKEN_DBL_OR) {
while (i == TOKEN_DBL_OR)
{
i = scan(scpriv, tokval);
f = rexp1(critical);
if (!f)
return NULL;
if (!(is_simple(e) || is_just_unknown(e)) ||
!(is_simple(f) || is_just_unknown(f))) {
error(ERR_NONFATAL, "`|' operator may only be applied to"
" scalar values");
}
!(is_simple(f) || is_just_unknown(f)))
{
error(ERR_NONFATAL, "`|' operator may only be applied to"
" scalar values");
}
if (is_just_unknown(e) || is_just_unknown(f))
e = unknown_expr();
else
@ -252,22 +287,27 @@ static expr *rexp0(int critical) {
return e;
}
static expr *rexp1(int critical) {
static expr *rexp1(int critical)
{
expr *e, *f;
e = rexp2(critical);
if (!e)
return NULL;
while (i == TOKEN_DBL_XOR) {
while (i == TOKEN_DBL_XOR)
{
i = scan(scpriv, tokval);
f = rexp2(critical);
if (!f)
return NULL;
if (!(is_simple(e) || is_just_unknown(e)) ||
!(is_simple(f) || is_just_unknown(f))) {
!(is_simple(f) || is_just_unknown(f)))
{
error(ERR_NONFATAL, "`^' operator may only be applied to"
" scalar values");
}
if (is_just_unknown(e) || is_just_unknown(f))
e = unknown_expr();
else
@ -276,19 +316,22 @@ static expr *rexp1(int critical) {
return e;
}
static expr *rexp2(int critical) {
static expr *rexp2(int critical)
{
expr *e, *f;
e = rexp3(critical);
if (!e)
return NULL;
while (i == TOKEN_DBL_AND) {
while (i == TOKEN_DBL_AND)
{
i = scan(scpriv, tokval);
f = rexp3(critical);
if (!f)
return NULL;
if (!(is_simple(e) || is_just_unknown(e)) ||
!(is_simple(f) || is_just_unknown(f))) {
!(is_simple(f) || is_just_unknown(f)))
{
error(ERR_NONFATAL, "`&' operator may only be applied to"
" scalar values");
}
@ -300,22 +343,28 @@ static expr *rexp2(int critical) {
return e;
}
static expr *rexp3(int critical) {
static expr *rexp3(int critical)
{
expr *e, *f;
long v;
e = expr0(critical);
if (!e)
return NULL;
while (i == TOKEN_EQ || i == TOKEN_LT || i == TOKEN_GT ||
i == TOKEN_NE || i == TOKEN_LE || i == TOKEN_GE) {
i == TOKEN_NE || i == TOKEN_LE || i == TOKEN_GE)
{
int j = i;
i = scan(scpriv, tokval);
f = expr0(critical);
if (!f)
return NULL;
e = add_vectors (e, scalar_mult(f, -1L, FALSE));
switch (j) {
switch (j)
{
case TOKEN_EQ: case TOKEN_NE:
if (is_unknown(e))
v = -1; /* means unknown */
@ -343,6 +392,7 @@ static expr *rexp3(int critical) {
}
break;
}
if (v == -1)
e = unknown_expr();
else
@ -351,22 +401,26 @@ static expr *rexp3(int critical) {
return e;
}
static expr *expr0(int critical) {
static expr *expr0(int critical)
{
expr *e, *f;
e = expr1(critical);
if (!e)
return NULL;
while (i == '|') {
while (i == '|')
{
i = scan(scpriv, tokval);
f = expr1(critical);
if (!f)
return NULL;
if (!(is_simple(e) || is_just_unknown(e)) ||
!(is_simple(f) || is_just_unknown(f))) {
error(ERR_NONFATAL, "`|' operator may only be applied to"
" scalar values");
}
!(is_simple(f) || is_just_unknown(f)))
{
error(ERR_NONFATAL, "`|' operator may only be applied to"
" scalar values");
}
if (is_just_unknown(e) || is_just_unknown(f))
e = unknown_expr();
else
@ -375,19 +429,22 @@ static expr *expr0(int critical) {
return e;
}
static expr *expr1(int critical) {
static expr *expr1(int critical)
{
expr *e, *f;
e = expr2(critical);
if (!e)
return NULL;
while (i == '^') {
i = scan(scpriv, tokval);
f = expr2(critical);
if (!f)
return NULL;
if (!(is_simple(e) || is_just_unknown(e)) ||
!(is_simple(f) || is_just_unknown(f))) {
!(is_simple(f) || is_just_unknown(f)))
{
error(ERR_NONFATAL, "`^' operator may only be applied to"
" scalar values");
}
@ -399,19 +456,22 @@ static expr *expr1(int critical) {
return e;
}
static expr *expr2(int critical) {
static expr *expr2(int critical)
{
expr *e, *f;
e = expr3(critical);
if (!e)
return NULL;
while (i == '&') {
i = scan(scpriv, tokval);
f = expr3(critical);
if (!f)
return NULL;
if (!(is_simple(e) || is_just_unknown(e)) ||
!(is_simple(f) || is_just_unknown(f))) {
!(is_simple(f) || is_just_unknown(f)))
{
error(ERR_NONFATAL, "`&' operator may only be applied to"
" scalar values");
}
@ -423,20 +483,24 @@ static expr *expr2(int critical) {
return e;
}
static expr *expr3(int critical) {
static expr *expr3(int critical)
{
expr *e, *f;
e = expr4(critical);
if (!e)
return NULL;
while (i == TOKEN_SHL || i == TOKEN_SHR) {
while (i == TOKEN_SHL || i == TOKEN_SHR)
{
int j = i;
i = scan(scpriv, tokval);
f = expr4(critical);
if (!f)
return NULL;
if (!(is_simple(e) || is_just_unknown(e)) ||
!(is_simple(f) || is_just_unknown(f))) {
!(is_simple(f) || is_just_unknown(f)))
{
error(ERR_NONFATAL, "shift operator may only be applied to"
" scalar values");
} else if (is_just_unknown(e) || is_just_unknown(f)) {
@ -454,13 +518,15 @@ static expr *expr3(int critical) {
return e;
}
static expr *expr4(int critical) {
static expr *expr4(int critical)
{
expr *e, *f;
e = expr5(critical);
if (!e)
return NULL;
while (i == '+' || i == '-') {
while (i == '+' || i == '-')
{
int j = i;
i = scan(scpriv, tokval);
f = expr5(critical);
@ -478,21 +544,24 @@ static expr *expr4(int critical) {
return e;
}
static expr *expr5(int critical) {
static expr *expr5(int critical)
{
expr *e, *f;
e = expr6(critical);
if (!e)
return NULL;
while (i == '*' || i == '/' || i == '%' ||
i == TOKEN_SDIV || i == TOKEN_SMOD) {
i == TOKEN_SDIV || i == TOKEN_SMOD)
{
int j = i;
i = scan(scpriv, tokval);
f = expr6(critical);
if (!f)
return NULL;
if (j != '*' && (!(is_simple(e) || is_just_unknown(e)) ||
!(is_simple(f) || is_just_unknown(f)))) {
!(is_simple(f) || is_just_unknown(f))))
{
error(ERR_NONFATAL, "division operator may only be applied to"
" scalar values");
return NULL;
@ -548,7 +617,8 @@ static expr *expr5(int critical) {
return e;
}
static expr *expr6(int critical) {
static expr *expr6(int critical)
{
long type;
expr *e;
long label_seg, label_ofs;
@ -597,8 +667,10 @@ static expr *expr6(int critical) {
}
i = scan(scpriv, tokval);
return e;
} else if (i == TOKEN_NUM || i == TOKEN_REG || i == TOKEN_ID ||
i == TOKEN_HERE || i == TOKEN_BASE) {
}
else if (i == TOKEN_NUM || i == TOKEN_REG || i == TOKEN_ID ||
i == TOKEN_HERE || i == TOKEN_BASE)
{
begintemp();
switch (i) {
case TOKEN_NUM:
@ -613,11 +685,11 @@ static expr *expr6(int critical) {
case TOKEN_HERE:
case TOKEN_BASE:
/*
* If "label" begins with "%", this indicates that no
* If !location->known, this indicates that no
* symbol, Here or Base references are valid because we
* are in preprocess-only mode.
*/
if (*label == '%') {
if (!location->known) {
error(ERR_NONFATAL,
"%s not supported in preprocess-only mode",
(i == TOKEN_ID ? "symbol references" :
@ -641,11 +713,11 @@ static expr *expr6(int critical) {
*/
type = EXPR_SIMPLE; /* might get overridden by UNKNOWN */
if (i == TOKEN_BASE) {
label_seg = seg;
label_seg = location->segment;
label_ofs = 0;
} else if (i == TOKEN_HERE || !strcmp(tokval->t_charptr, label)) {
label_seg = seg;
label_ofs = ofs;
} else if (i == TOKEN_HERE) {
label_seg = location->segment;
label_ofs = location->offset;
} else if (!labelfunc(tokval->t_charptr,&label_seg,&label_ofs)) {
if (critical == 2) {
error (ERR_NONFATAL, "symbol `%s' undefined",
@ -656,16 +728,19 @@ static expr *expr6(int critical) {
tokval->t_charptr);
return NULL;
} else {
if (forward)
*forward = TRUE;
if (opflags)
*opflags |= 1;
type = EXPR_UNKNOWN;
label_seg = NO_SEG;
label_ofs = 1;
}
}
addtotemp(type, label_ofs);
if (label_seg!=NO_SEG)
if (label_seg!=NO_SEG) {
addtotemp(EXPR_SEGBASE + label_seg, 1L);
if (opflags && is_extern (tokval->t_charptr))
*opflags |= OPFLAG_EXTERN;
}
break;
}
i = scan(scpriv, tokval);
@ -676,26 +751,17 @@ static expr *expr6(int critical) {
}
}
void eval_global_info (struct ofmt *output, lfunc lookup_label) {
void eval_global_info (struct ofmt *output, lfunc lookup_label, loc_t *locp)
{
outfmt = output;
labelfunc = lookup_label;
}
void eval_info (char *labelname, long segment, long offset) {
if (label != special_empty_string)
nasm_free (label);
if (labelname)
label = nasm_strdup(labelname);
else {
label = special_empty_string;
seg = segment;
ofs = offset;
}
location = locp;
}
expr *evaluate (scanner sc, void *scprivate, struct tokenval *tv,
int *fwref, int critical, efunc report_error,
struct eval_hints *hints) {
struct eval_hints *hints)
{
expr *e;
expr *f = NULL;
@ -713,7 +779,7 @@ expr *evaluate (scanner sc, void *scprivate, struct tokenval *tv,
scpriv = scprivate;
tokval = tv;
error = report_error;
forward = fwref;
opflags = fwref;
if (tokval->t_type == TOKEN_INVALID)
i = scan(scpriv, tokval);
@ -748,7 +814,8 @@ expr *evaluate (scanner sc, void *scprivate, struct tokenval *tv,
value = reloc_seg(f);
if (value == NO_SEG)
value = reloc_value(f) | SEG_ABS;
else if (!(value & SEG_ABS) && !(value % 2) && critical) {
else if (!(value & SEG_ABS) && !(value % 2) && critical)
{
error(ERR_NONFATAL, "invalid right-hand operand to WRT");
return NULL;
}

12
eval.h
View File

@ -14,15 +14,7 @@
* providing segment-base details, and what function can be used to
* look labels up.
*/
void eval_global_info (struct ofmt *output, lfunc lookup_label);
/*
* Called to set the information the evaluator needs: the value of
* $ is set from `segment' and `offset' if `labelname' is NULL, and
* otherwise the name of the current line's label is set from
* `labelname' instead.
*/
void eval_info (char *labelname, long segment, long offset);
void eval_global_info (struct ofmt *output, lfunc lookup_label, loc_t *locp);
/*
* The evaluator itself.
@ -31,4 +23,6 @@ expr *evaluate (scanner sc, void *scprivate, struct tokenval *tv,
int *fwref, int critical, efunc report_error,
struct eval_hints *hints);
void eval_cleanup(void);
#endif

38
float.c
View File

@ -25,9 +25,10 @@
* => we only have to worry about _one_ bit shift to the left
*/
static int multiply(unsigned short *to, unsigned short *from) {
static int multiply(unsigned short *to, unsigned short *from)
{
unsigned long temp[MANT_WORDS*2];
int i, j;
int i, j;
for (i=0; i<MANT_WORDS*2; i++)
temp[i] = 0;
@ -56,11 +57,14 @@ static int multiply(unsigned short *to, unsigned short *from) {
}
static void flconvert(char *string, unsigned short *mant, long *exponent,
efunc error) {
char digits[MANT_DIGITS], *p, *q, *r;
unsigned short mult[MANT_WORDS], *m, bit;
long tenpwr, twopwr;
int extratwos, started, seendot;
efunc error)
{
char digits[MANT_DIGITS];
char *p, *q, *r;
unsigned short mult[MANT_WORDS], bit;
unsigned short * m;
long tenpwr, twopwr;
int extratwos, started, seendot;
p = digits;
tenpwr = 0;
@ -179,9 +183,10 @@ static void flconvert(char *string, unsigned short *mant, long *exponent,
/*
* Shift a mantissa to the right by i (i < 16) bits.
*/
static void shr(unsigned short *mant, int i) {
static void shr(unsigned short *mant, int i)
{
unsigned short n = 0, m;
int j;
int j;
for (j=0; j<MANT_WORDS; j++) {
m = (mant[j] << (16-i)) & 0xFFFF;
@ -193,7 +198,8 @@ static void shr(unsigned short *mant, int i) {
/*
* Round a mantissa off after i words.
*/
static int round(unsigned short *mant, int i) {
static int round(unsigned short *mant, int i)
{
if (mant[i] & 0x8000) {
do {
++mant[--i];
@ -207,7 +213,8 @@ static int round(unsigned short *mant, int i) {
#define put(a,b) ( (*(a)=(b)), ((a)[1]=(b)>>8) )
static int to_double(char *str, long sign, unsigned char *result,
efunc error) {
efunc error)
{
unsigned short mant[MANT_WORDS];
long exponent;
@ -267,7 +274,8 @@ static int to_double(char *str, long sign, unsigned char *result,
}
static int to_float(char *str, long sign, unsigned char *result,
efunc error) {
efunc error)
{
unsigned short mant[MANT_WORDS];
long exponent;
@ -320,7 +328,8 @@ static int to_float(char *str, long sign, unsigned char *result,
}
static int to_ldoub(char *str, long sign, unsigned char *result,
efunc error) {
efunc error)
{
unsigned short mant[MANT_WORDS];
long exponent;
@ -379,7 +388,8 @@ static int to_ldoub(char *str, long sign, unsigned char *result,
}
int float_const (char *number, long sign, unsigned char *result, int bytes,
efunc error) {
efunc error)
{
if (bytes == 4)
return to_float (number, sign, result, error);
else if (bytes == 8)

View File

@ -125,6 +125,7 @@ BTS reg32,reg32 \321\300\2\x0F\xAB\101 386
BTS rm16,imm \320\300\2\x0F\xBA\205\25 386
BTS rm32,imm \321\300\2\x0F\xBA\205\25 386
CALL imm \322\1\xE8\64 8086
CALL imm|near \322\1\xE8\64 8086
CALL imm|far \322\1\x9A\34\37 8086,ND
CALL imm:imm \322\1\x9A\35\30 8086
CALL imm16:imm \320\1\x9A\31\30 8086
@ -274,6 +275,7 @@ FDIVR fpureg \1\xD8\10\xF8 8086,FPU
FDIVR fpu0,fpureg \1\xD8\11\xF8 8086,FPU
FDIVRP fpureg \1\xDE\10\xF0 8086,FPU
FDIVRP fpureg,fpu0 \1\xDE\10\xF0 8086,FPU
FEMMS void \2\x0F\x0E PENT,MMX,FPU
FENI void \3\x9B\xDB\xE0 8086,FPU
FFREE fpureg \1\xDD\10\xC0 8086,FPU
FIADD mem32 \300\1\xDA\200 8086,FPU
@ -447,6 +449,7 @@ JCXZ imm \320\1\xE3\50 8086
JECXZ imm \321\1\xE3\50 386
JMP imm|short \1\xEB\50 8086
JMP imm \322\1\xE9\64 8086
JMP imm|near \322\1\xE9\64 8086
JMP imm|far \322\1\xEA\34\37 8086,ND
JMP imm:imm \322\1\xEA\35\30 8086
JMP imm16:imm \320\1\xEA\31\30 8086
@ -619,9 +622,9 @@ OR rm32,imm \321\300\1\x81\201\41 386,SM
OR mem,imm8 \300\1\x80\201\21 8086,SM
OR mem,imm16 \320\300\1\x81\201\31 8086,SM
OR mem,imm32 \321\300\1\x81\201\41 386,SM
OUT imm,reg_al \1\xE6\24 8086
OUT imm,reg_ax \320\1\xE7\24 8086
OUT imm,reg_eax \321\1\xE7\24 386
OUT imm,reg_al \1\xE6\24 8086,SB
OUT imm,reg_ax \320\1\xE7\24 8086,SB
OUT imm,reg_eax \321\1\xE7\24 386,SB
OUT reg_dx,reg_al \1\xEE 8086
OUT reg_dx,reg_ax \320\1\xEF 8086
OUT reg_dx,reg_eax \321\1\xEF 386
@ -656,6 +659,8 @@ PANDN mmxreg,mem \301\2\x0F\xDF\110 PENT,MMX,SM
PANDN mmxreg,mmxreg \2\x0F\xDF\110 PENT,MMX
PAVEB mmxreg,mem \301\2\x0F\x50\110 PENT,MMX,SM,CYRIX
PAVEB mmxreg,mmxreg \2\x0F\x50\110 PENT,MMX,CYRIX
PAVGUSB mmxreg,mem \301\2\x0F\x0F\110\01\xBF PENT,MMX,SM,FPU
PAVGUSB mmxreg,mmxreg \2\x0F\x0F\110\01\xBF PENT,MMX,FPU
PCMPEQB mmxreg,mem \301\2\x0F\x74\110 PENT,MMX,SM
PCMPEQB mmxreg,mmxreg \2\x0F\x74\110 PENT,MMX
PCMPEQD mmxreg,mem \301\2\x0F\x76\110 PENT,MMX,SM
@ -669,15 +674,51 @@ PCMPGTD mmxreg,mmxreg \2\x0F\x66\110 PENT,MMX
PCMPGTW mmxreg,mem \301\2\x0F\x65\110 PENT,MMX,SM
PCMPGTW mmxreg,mmxreg \2\x0F\x65\110 PENT,MMX
PDISTIB mmxreg,mem \301\2\x0F\x54\110 PENT,MMX,SM,CYRIX
PF2ID mmxreg,mem \301\2\x0F\x0F\110\01\x1D PENT,MMX,SM,FPU
PF2ID mmxreg,mmxreg \2\x0F\x0F\110\01\x1D PENT,MMX,FPU
PFACC mmxreg,mem \301\2\x0F\x0F\110\01\xAE PENT,MMX,SM,FPU
PFACC mmxreg,mmxreg \2\x0F\x0F\110\01\xAE PENT,MMX,FPU
PFADD mmxreg,mem \301\2\x0F\x0F\110\01\x9E PENT,MMX,SM,FPU
PFADD mmxreg,mmxreg \2\x0F\x0F\110\01\x9E PENT,MMX,FPU
PFCMPEQ mmxreg,mem \301\2\x0F\x0F\110\01\xB0 PENT,MMX,SM,FPU
PFCMPEQ mmxreg,mmxreg \2\x0F\x0F\110\01\xB0 PENT,MMX,FPU
PFCMPGE mmxreg,mem \301\2\x0F\x0F\110\01\x90 PENT,MMX,SM,FPU
PFCMPGE mmxreg,mmxreg \2\x0F\x0F\110\01\x90 PENT,MMX,FPU
PFCMPGT mmxreg,mem \301\2\x0F\x0F\110\01\xA0 PENT,MMX,SM,FPU
PFCMPGT mmxreg,mmxreg \2\x0F\x0F\110\01\xA0 PENT,MMX,FPU
PFMAX mmxreg,mem \301\2\x0F\x0F\110\01\xA4 PENT,MMX,SM,FPU
PFMAX mmxreg,mmxreg \2\x0F\x0F\110\01\xA4 PENT,MMX,FPU
PFMIN mmxreg,mem \301\2\x0F\x0F\110\01\x94 PENT,MMX,SM,FPU
PFMIN mmxreg,mmxreg \2\x0F\x0F\110\01\x94 PENT,MMX,FPU
PFMUL mmxreg,mem \301\2\x0F\x0F\110\01\xB4 PENT,MMX,SM,FPU
PFMUL mmxreg,mmxreg \2\x0F\x0F\110\01\xB4 PENT,MMX,FPU
PFRCP mmxreg,mem \301\2\x0F\x0F\110\01\x96 PENT,MMX,SM,FPU
PFRCP mmxreg,mmxreg \2\x0F\x0F\110\01\x96 PENT,MMX,FPU
PFRCPIT1 mmxreg,mem \301\2\x0F\x0F\110\01\xA6 PENT,MMX,SM,FPU
PFRCPIT1 mmxreg,mmxreg \2\x0F\x0F\110\01\xA6 PENT,MMX,FPU
PFRCPIT2 mmxreg,mem \301\2\x0F\x0F\110\01\xB6 PENT,MMX,SM,FPU
PFRCPIT2 mmxreg,mmxreg \2\x0F\x0F\110\01\xB6 PENT,MMX,FPU
PFRSQIT1 mmxreg,mem \301\2\x0F\x0F\110\01\xA7 PENT,MMX,SM,FPU
PFRSQIT1 mmxreg,mmxreg \2\x0F\x0F\110\01\xA7 PENT,MMX,FPU
PFRSQRT mmxreg,mem \301\2\x0F\x0F\110\01\x97 PENT,MMX,SM,FPU
PFRSQRT mmxreg,mmxreg \2\x0F\x0F\110\01\x97 PENT,MMX,FPU
PFSUB mmxreg,mem \301\2\x0F\x0F\110\01\x9A PENT,MMX,SM,FPU
PFSUB mmxreg,mmxreg \2\x0F\x0F\110\01\x9A PENT,MMX,FPU
PFSUBR mmxreg,mem \301\2\x0F\x0F\110\01\xAA PENT,MMX,SM,FPU
PFSUBR mmxreg,mmxreg \2\x0F\x0F\110\01\xAA PENT,MMX,FPU
PI2FD mmxreg,mem \301\2\x0F\x0F\110\01\x0D PENT,MMX,SM,FPU
PI2FD mmxreg,mmxreg \2\x0F\x0F\110\01\x0D PENT,MMX,FPU
PMACHRIW mmxreg,mem \301\2\x0F\x5E\110 PENT,MMX,SM,CYRIX
PMADDWD mmxreg,mem \301\2\x0F\xF5\110 PENT,MMX,SM
PMADDWD mmxreg,mmxreg \2\x0F\xF5\110 PENT,MMX
PMAGW mmxreg,mem \301\2\x0F\x52\110 PENT,MMX,SM,CYRIX
PMAGW mmxreg,mmxreg \2\x0F\x52\110 PENT,MMX,CYRIX
PMULHRW mmxreg,mem \301\2\x0F\x59\110 PENT,MMX,SM,CYRIX
PMULHRW mmxreg,mmxreg \2\x0F\x59\110 PENT,MMX,CYRIX
PMULHRIW mmxreg,mem \301\2\x0F\x5D\110 PENT,MMX,SM,CYRIX
PMULHRIW mmxreg,mmxreg \2\x0F\x5D\110 PENT,MMX,CYRIX
PMULHRWA mmxreg,mem \301\2\x0F\x0F\110\1\xB7 PENT,MMX,SM,FPU
PMULHRWA mmxreg,mmxreg \2\x0F\x0F\110\1\xB7 PENT,MMX,FPU
PMULHRWC mmxreg,mem \301\2\x0F\x59\110 PENT,MMX,SM,CYRIX
PMULHRWC mmxreg,mmxreg \2\x0F\x59\110 PENT,MMX,CYRIX
PMULHW mmxreg,mem \301\2\x0F\xE5\110 PENT,MMX,SM
PMULHW mmxreg,mmxreg \2\x0F\xE5\110 PENT,MMX
PMULLW mmxreg,mem \301\2\x0F\xD5\110 PENT,MMX,SM
@ -701,6 +742,8 @@ POPFD void \321\1\x9D 386
POPFW void \320\1\x9D 186
POR mmxreg,mem \301\2\x0F\xEB\110 PENT,MMX,SM
POR mmxreg,mmxreg \2\x0F\xEB\110 PENT,MMX
PREFETCH mem \2\x0F\x0D\200 PENT,MMX,SM,FPU
PREFETCHW mem \2\x0F\x0D\201 PENT,MMX,SM,FPU
PSLLD mmxreg,mem \301\2\x0F\xF2\110 PENT,MMX,SM
PSLLD mmxreg,mmxreg \2\x0F\xF2\110 PENT,MMX
PSLLD mmxreg,imm \2\x0F\x72\206\25 PENT,MMX
@ -772,19 +815,19 @@ PXOR mmxreg,mem \301\2\x0F\xEF\110 PENT,MMX,SM
PXOR mmxreg,mmxreg \2\x0F\xEF\110 PENT,MMX
RCL rm8,unity \300\1\xD0\202 8086
RCL rm8,reg_cl \300\1\xD2\202 8086
RCL rm8,imm \300\1\xC0\202\25 286,SB
RCL rm8,imm \300\1\xC0\202\25 186,SB
RCL rm16,unity \320\300\1\xD1\202 8086
RCL rm16,reg_cl \320\300\1\xD3\202 8086
RCL rm16,imm \320\300\1\xC1\202\25 286,SB
RCL rm16,imm \320\300\1\xC1\202\25 186,SB
RCL rm32,unity \321\300\1\xD1\202 386
RCL rm32,reg_cl \321\300\1\xD3\202 386
RCL rm32,imm \321\300\1\xC1\202\25 386,SB
RCR rm8,unity \300\1\xD0\203 8086
RCR rm8,reg_cl \300\1\xD2\203 8086
RCR rm8,imm \300\1\xC0\203\25 286,SB
RCR rm8,imm \300\1\xC0\203\25 186,SB
RCR rm16,unity \320\300\1\xD1\203 8086
RCR rm16,reg_cl \320\300\1\xD3\203 8086
RCR rm16,imm \320\300\1\xC1\203\25 286,SB
RCR rm16,imm \320\300\1\xC1\203\25 186,SB
RCR rm32,unity \321\300\1\xD1\203 386
RCR rm32,reg_cl \321\300\1\xD3\203 386
RCR rm32,imm \321\300\1\xC1\203\25 386,SB
@ -804,19 +847,19 @@ RETN void \1\xC3 8086
RETN imm \1\xC2\30 8086
ROL rm8,unity \300\1\xD0\200 8086
ROL rm8,reg_cl \300\1\xD2\200 8086
ROL rm8,imm \300\1\xC0\200\25 286,SB
ROL rm8,imm \300\1\xC0\200\25 186,SB
ROL rm16,unity \320\300\1\xD1\200 8086
ROL rm16,reg_cl \320\300\1\xD3\200 8086
ROL rm16,imm \320\300\1\xC1\200\25 286,SB
ROL rm16,imm \320\300\1\xC1\200\25 186,SB
ROL rm32,unity \321\300\1\xD1\200 386
ROL rm32,reg_cl \321\300\1\xD3\200 386
ROL rm32,imm \321\300\1\xC1\200\25 386,SB
ROR rm8,unity \300\1\xD0\201 8086
ROR rm8,reg_cl \300\1\xD2\201 8086
ROR rm8,imm \300\1\xC0\201\25 286,SB
ROR rm8,imm \300\1\xC0\201\25 186,SB
ROR rm16,unity \320\300\1\xD1\201 8086
ROR rm16,reg_cl \320\300\1\xD3\201 8086
ROR rm16,imm \320\300\1\xC1\201\25 286,SB
ROR rm16,imm \320\300\1\xC1\201\25 186,SB
ROR rm32,unity \321\300\1\xD1\201 386
ROR rm32,reg_cl \321\300\1\xD3\201 386
ROR rm32,imm \321\300\1\xC1\201\25 386,SB
@ -824,20 +867,20 @@ RSM void \2\x0F\xAA PENT
SAHF void \1\x9E 8086
SAL rm8,unity \300\1\xD0\204 8086,ND
SAL rm8,reg_cl \300\1\xD2\204 8086,ND
SAL rm8,imm \300\1\xC0\204\25 286,ND,SB
SAL rm8,imm \300\1\xC0\204\25 186,ND,SB
SAL rm16,unity \320\300\1\xD1\204 8086,ND
SAL rm16,reg_cl \320\300\1\xD3\204 8086,ND
SAL rm16,imm \320\300\1\xC1\204\25 286,ND,SB
SAL rm16,imm \320\300\1\xC1\204\25 186,ND,SB
SAL rm32,unity \321\300\1\xD1\204 386,ND
SAL rm32,reg_cl \321\300\1\xD3\204 386,ND
SAL rm32,imm \321\300\1\xC1\204\25 386,ND,SB
SALC void \1\xD6 8086,UNDOC
SAR rm8,unity \300\1\xD0\207 8086
SAR rm8,reg_cl \300\1\xD2\207 8086
SAR rm8,imm \300\1\xC0\207\25 286,SB
SAR rm8,imm \300\1\xC0\207\25 186,SB
SAR rm16,unity \320\300\1\xD1\207 8086
SAR rm16,reg_cl \320\300\1\xD3\207 8086
SAR rm16,imm \320\300\1\xC1\207\25 286,SB
SAR rm16,imm \320\300\1\xC1\207\25 186,SB
SAR rm32,unity \321\300\1\xD1\207 386
SAR rm32,reg_cl \321\300\1\xD3\207 386
SAR rm32,imm \321\300\1\xC1\207\25 386,SB
@ -870,10 +913,10 @@ SCASW void \320\1\xAF 8086
SGDT mem \300\2\x0F\x01\200 286,PRIV
SHL rm8,unity \300\1\xD0\204 8086
SHL rm8,reg_cl \300\1\xD2\204 8086
SHL rm8,imm \300\1\xC0\204\25 286,SB
SHL rm8,imm \300\1\xC0\204\25 186,SB
SHL rm16,unity \320\300\1\xD1\204 8086
SHL rm16,reg_cl \320\300\1\xD3\204 8086
SHL rm16,imm \320\300\1\xC1\204\25 286,SB
SHL rm16,imm \320\300\1\xC1\204\25 186,SB
SHL rm32,unity \321\300\1\xD1\204 386
SHL rm32,reg_cl \321\300\1\xD3\204 386
SHL rm32,imm \321\300\1\xC1\204\25 386,SB
@ -887,10 +930,10 @@ SHLD mem,reg32,reg_cl \300\321\2\x0F\xA5\101 386,SM
SHLD reg32,reg32,reg_cl \300\321\2\x0F\xA5\101 386
SHR rm8,unity \300\1\xD0\205 8086
SHR rm8,reg_cl \300\1\xD2\205 8086
SHR rm8,imm \300\1\xC0\205\25 286,SB
SHR rm8,imm \300\1\xC0\205\25 186,SB
SHR rm16,unity \320\300\1\xD1\205 8086
SHR rm16,reg_cl \320\300\1\xD3\205 8086
SHR rm16,imm \320\300\1\xC1\205\25 286,SB
SHR rm16,imm \320\300\1\xC1\205\25 186,SB
SHR rm32,unity \321\300\1\xD1\205 386
SHR rm32,reg_cl \321\300\1\xD3\205 386
SHR rm32,imm \321\300\1\xC1\205\25 386,SB
@ -948,6 +991,9 @@ TEST mem,reg16 \320\300\1\x85\101 8086,SM
TEST reg16,reg16 \320\300\1\x85\101 8086
TEST mem,reg32 \321\300\1\x85\101 386,SM
TEST reg32,reg32 \321\300\1\x85\101 386
TEST reg8,mem \301\1\x84\110 8086,SM
TEST reg16,mem \320\301\1\x85\110 8086,SM
TEST reg32,mem \321\301\1\x85\110 386,SM
TEST reg_al,imm \1\xA8\21 8086,SM
TEST reg_ax,imm \320\1\xA9\31 8086,SM
TEST reg_eax,imm \321\1\xA9\41 386,SM

117
labels.c
View File

@ -43,7 +43,7 @@ union label { /* actual label structures */
struct {
long segment, offset;
char *label, *special;
int is_global;
int is_global, is_norm;
} defn;
struct {
long movingon, dummy;
@ -74,7 +74,8 @@ static int initialised = FALSE;
* given label name. Creates a new one, if it isn't found, and if
* `create' is TRUE.
*/
static union label *find_label (char *label, int create) {
static union label *find_label (char *label, int create)
{
int hash = 0;
char *p, *prev;
int prevlen;
@ -117,11 +118,13 @@ static union label *find_label (char *label, int create) {
lfree[hash]->defn.special = NULL;
lfree[hash]->defn.is_global = NOT_DEFINED_YET;
return lfree[hash]++;
} else
}
else
return NULL;
}
int lookup_label (char *label, long *segment, long *offset) {
int lookup_label (char *label, long *segment, long *offset)
{
union label *lptr;
if (!initialised)
@ -132,11 +135,13 @@ int lookup_label (char *label, long *segment, long *offset) {
*segment = lptr->defn.segment;
*offset = lptr->defn.offset;
return 1;
} else
}
else
return 0;
}
int is_extern (char *label) {
int is_extern (char *label)
{
union label *lptr;
if (!initialised)
@ -149,22 +154,48 @@ int is_extern (char *label) {
return 0;
}
void define_label_stub (char *label, efunc error) {
void redefine_label (char *label, long segment, long offset, char *special,
int is_norm, int isextrn, struct ofmt *ofmt, efunc error)
{
union label *lptr;
/* This routine possibly ought to check for phase errors. Most assemblers
* check for phase errors at this point. I don't know whether phase errors
* are even possible, nor whether they are checked somewhere else
*/
(void) segment; /* Don't warn that this parameter is unused */
(void) offset; /* Don't warn that this parameter is unused */
(void) special; /* Don't warn that this parameter is unused */
(void) is_norm; /* Don't warn that this parameter is unused */
(void) isextrn; /* Don't warn that this parameter is unused */
(void) ofmt; /* Don't warn that this parameter is unused */
#ifdef DEBUG
if (!strncmp(label, "debugdump", 9))
fprintf(stderr, "debug: redefine_label (%s, %ld, %08lx, %s, %d, %d)\n",
label, segment, offset, special, is_norm, isextrn);
#endif
if (!islocal(label)) {
lptr = find_label (label, 1);
if (!lptr)
error (ERR_PANIC, "can't find label `%s' on pass two", label);
if (*label != '.')
if (*label != '.' && lptr->defn.is_norm)
prevlabel = lptr->defn.label;
}
}
void define_label (char *label, long segment, long offset, char *special,
int is_norm, int isextrn, struct ofmt *ofmt, efunc error) {
int is_norm, int isextrn, struct ofmt *ofmt, efunc error)
{
union label *lptr;
#ifdef DEBUG
if (!strncmp(label, "debugdump", 9))
fprintf(stderr, "debug: define_label (%s, %ld, %08lx, %s, %d, %d)\n",
label, segment, offset, special, is_norm, isextrn);
#endif
lptr = find_label (label, 1);
if (lptr->defn.is_global & DEFINED_BIT) {
error(ERR_NONFATAL, "symbol `%s' redefined", label);
@ -182,14 +213,19 @@ void define_label (char *label, long segment, long offset, char *special,
lptr->defn.segment = segment;
lptr->defn.offset = offset;
lptr->defn.is_norm = (label[0] != '.' && is_norm);
ofmt->symdef (lptr->defn.label, segment, offset,
!!(lptr->defn.is_global & GLOBAL_BIT),
special ? special : lptr->defn.special);
ofmt->current_dfmt->debug_deflabel (label, segment, offset,
!!(lptr->defn.is_global & GLOBAL_BIT),
special ? special : lptr->defn.special);
}
void define_common (char *label, long segment, long size, char *special,
struct ofmt *ofmt, efunc error) {
struct ofmt *ofmt, efunc error)
{
union label *lptr;
lptr = find_label (label, 1);
@ -210,9 +246,12 @@ void define_common (char *label, long segment, long size, char *special,
ofmt->symdef (lptr->defn.label, segment, size, 2,
special ? special : lptr->defn.special);
ofmt->current_dfmt->debug_deflabel(lptr->defn.label, segment, size, 2,
special ? special : lptr->defn.special);
}
void declare_as_global (char *label, char *special, efunc error) {
void declare_as_global (char *label, char *special, efunc error)
{
union label *lptr;
if (islocal(label)) {
@ -237,7 +276,8 @@ void declare_as_global (char *label, char *special, efunc error) {
}
}
int init_labels (void) {
int init_labels (void)
{
int i;
for (i=0; i<LABEL_HASHES; i++) {
@ -248,7 +288,9 @@ int init_labels (void) {
lfree[i] = ltab[i];
}
perm_head = perm_tail = (struct permts *) nasm_malloc (sizeof(struct permts));
perm_head =
perm_tail = (struct permts *) nasm_malloc (sizeof(struct permts));
if (!perm_head)
return -1;
@ -263,7 +305,8 @@ int init_labels (void) {
return 0;
}
void cleanup_labels (void) {
void cleanup_labels (void)
{
int i;
initialised = FALSE;
@ -288,7 +331,8 @@ void cleanup_labels (void) {
}
}
static void init_block (union label *blk) {
static void init_block (union label *blk)
{
int j;
for (j=0; j<LABEL_BLOCK-1; j++)
@ -297,7 +341,8 @@ static void init_block (union label *blk) {
blk[LABEL_BLOCK-1].admin.next = NULL;
}
static char *perm_copy (char *string1, char *string2) {
static char *perm_copy (char *string1, char *string2)
{
char *p, *q;
int len = strlen(string1)+strlen(string2)+1;
@ -310,8 +355,46 @@ static char *perm_copy (char *string1, char *string2) {
}
p = q = perm_tail->data + perm_tail->usage;
while ( (*q = *string1++) ) q++;
while ( (*q++ = *string2++) );
while ( (*q++ = *string2++) ) ;
perm_tail->usage = q - perm_tail->data;
return p;
}
/*
* Notes regarding bug involving redefinition of external segments.
*
* Up to and including v0.97, the following code didn't work. From 0.97
* developers release 2 onwards, it will generate an error.
*
* EXTERN extlabel
* newlabel EQU extlabel + 1
*
* The results of allowing this code through are that two import records
* are generated, one for 'extlabel' and one for 'newlabel'.
*
* The reason for this is an inadequacy in the defined interface between
* the label manager and the output formats. The problem lies in how the
* output format driver tells that a label is an external label for which
* a label import record must be produced. Most (all except bin?) produce
* the record if the segment number of the label is not one of the internal
* segments that the output driver is producing.
*
* A simple fix to this would be to make the output formats keep track of
* which symbols they've produced import records for, and make them not
* produce import records for segments that are already defined.
*
* The best way, which is slightly harder but reduces duplication of code
* and should therefore make the entire system smaller and more stable is
* to change the interface between assembler, define_label(), and
* the output module. The changes that are needed are:
*
* The semantics of the 'isextern' flag passed to define_label() need
* examining. This information may or may not tell us what we need to
* know (ie should we be generating an import record at this point for this
* label). If these aren't the semantics, the semantics should be changed
* to this.
*
* The output module interface needs changing, so that the `isextern' flag
* is passed to the module, so that it can be easily tested for.
*/

View File

@ -10,9 +10,10 @@ int lookup_label (char *label, long *segment, long *offset);
int is_extern (char *label);
void define_label (char *label, long segment, long offset, char *special,
int is_norm, int isextrn, struct ofmt *ofmt, efunc error);
void redefine_label (char *label, long segment, long offset, char *special,
int is_norm, int isextrn, struct ofmt *ofmt, efunc error);
void define_common (char *label, long segment, long size, char *special,
struct ofmt *ofmt, efunc error);
void define_label_stub (char *label, efunc error);
void declare_as_global (char *label, char *special, efunc error);
int init_labels (void);
void cleanup_labels (void);

View File

@ -50,31 +50,39 @@ static int listlevel, listlevel_e;
static FILE *listfp;
static void list_emit (void) {
static void list_emit (void)
{
if (!listlinep && !listdata[0])
return;
fprintf(listfp, "%6ld ", ++listlineno);
if (listdata[0])
fprintf(listfp, "%08lX %-*s", listoffset, LIST_HEXBIT+1, listdata);
else
fprintf(listfp, "%*s", LIST_HEXBIT+10, "");
if (listlevel_e)
fprintf(listfp, "%s<%d>", (listlevel < 10 ? " " : ""), listlevel_e);
else if (listlinep)
fprintf(listfp, " ");
if (listlinep)
fprintf(listfp, " %s", listline);
fputc('\n', listfp);
listlinep = FALSE;
listdata[0] = '\0';
}
static void list_init (char *fname, efunc error) {
static void list_init (char *fname, efunc error)
{
listfp = fopen (fname, "w");
if (!listfp) {
error (ERR_NONFATAL, "unable to open listing file `%s'", fname);
return;
}
*listline = '\0';
listlineno = 0;
listp = TRUE;
@ -86,19 +94,23 @@ static void list_init (char *fname, efunc error) {
mistack->inhibiting = TRUE;
}
static void list_cleanup (void) {
static void list_cleanup (void)
{
if (!listp)
return;
while (mistack) {
MacroInhibit *temp = mistack;
mistack = temp->next;
nasm_free (temp);
}
list_emit();
fclose (listfp);
}
static void list_out (long offset, char *str) {
static void list_out (long offset, char *str)
{
if (strlen(listdata) + strlen(str) > LIST_HEXBIT) {
strcat(listdata, "-");
list_emit();
@ -108,7 +120,8 @@ static void list_out (long offset, char *str) {
strcat(listdata, str);
}
static void list_output (long offset, void *data, unsigned long type) {
static void list_output (long offset, void *data, unsigned long type)
{
long typ, size;
if (!listp || suppress)
@ -117,20 +130,25 @@ static void list_output (long offset, void *data, unsigned long type) {
typ = type & OUT_TYPMASK;
size = type & OUT_SIZMASK;
if (typ == OUT_RAWDATA) {
if (typ == OUT_RAWDATA)
{
unsigned char *p = data;
char q[3];
while (size--) {
while (size--)
{
HEX (q, *p);
q[2] = '\0';
list_out (offset++, q);
p++;
}
} else if (typ == OUT_ADDRESS) {
}
else if (typ == OUT_ADDRESS)
{
unsigned long d = *(long *)data;
char q[11];
unsigned char p[4], *r = p;
if (size == 4) {
if (size == 4)
{
q[0] = '['; q[9] = ']'; q[10] = '\0';
WRITELONG (r, d);
HEX (q+1, p[0]);
@ -138,14 +156,17 @@ static void list_output (long offset, void *data, unsigned long type) {
HEX (q+5, p[2]);
HEX (q+7, p[3]);
list_out (offset, q);
} else {
}
else {
q[0] = '['; q[5] = ']'; q[6] = '\0';
WRITESHORT (r, d);
HEX (q+1, p[0]);
HEX (q+3, p[1]);
list_out (offset, q);
}
} else if (typ == OUT_REL2ADR) {
}
else if (typ == OUT_REL2ADR)
{
unsigned long d = *(long *)data;
char q[11];
unsigned char p[4], *r = p;
@ -154,7 +175,9 @@ static void list_output (long offset, void *data, unsigned long type) {
HEX (q+1, p[0]);
HEX (q+3, p[1]);
list_out (offset, q);
} else if (typ == OUT_REL4ADR) {
}
else if (typ == OUT_REL4ADR)
{
unsigned long d = *(long *)data;
char q[11];
unsigned char p[4], *r = p;
@ -165,17 +188,22 @@ static void list_output (long offset, void *data, unsigned long type) {
HEX (q+5, p[2]);
HEX (q+7, p[3]);
list_out (offset, q);
} else if (typ == OUT_RESERVE) {
}
else if (typ == OUT_RESERVE)
{
char q[20];
sprintf(q, "<res %08lX>", size);
list_out (offset, q);
}
}
static void list_line (int type, char *line) {
static void list_line (int type, char *line)
{
if (!listp)
return;
if (mistack && mistack->inhibiting) {
if (mistack && mistack->inhibiting)
{
if (type == LIST_MACRO)
return;
else { /* pop the m i stack */
@ -191,22 +219,29 @@ static void list_line (int type, char *line) {
listlevel_e = listlevel;
}
static void list_uplevel (int type) {
static void list_uplevel (int type)
{
if (!listp)
return;
if (type == LIST_INCBIN || type == LIST_TIMES) {
if (type == LIST_INCBIN || type == LIST_TIMES)
{
suppress |= (type == LIST_INCBIN ? 1 : 2);
list_out (listoffset, type == LIST_INCBIN ? "<incbin>" : "<rept>");
return;
}
listlevel++;
if (mistack && mistack->inhibiting && type == LIST_INCLUDE) {
if (mistack && mistack->inhibiting && type == LIST_INCLUDE)
{
MacroInhibit *temp = nasm_malloc(sizeof(MacroInhibit));
temp->next = mistack;
temp->level = listlevel;
temp->inhibiting = FALSE;
mistack = temp;
} else if (type == LIST_MACRO_NOLIST) {
}
else if (type == LIST_MACRO_NOLIST)
{
MacroInhibit *temp = nasm_malloc(sizeof(MacroInhibit));
temp->next = mistack;
temp->level = listlevel;
@ -215,15 +250,20 @@ static void list_uplevel (int type) {
}
}
static void list_downlevel (int type) {
static void list_downlevel (int type)
{
if (!listp)
return;
if (type == LIST_INCBIN || type == LIST_TIMES) {
if (type == LIST_INCBIN || type == LIST_TIMES)
{
suppress &= ~(type == LIST_INCBIN ? 1 : 2);
return;
}
listlevel--;
while (mistack && mistack->level > listlevel) {
while (mistack && mistack->level > listlevel)
{
MacroInhibit *temp = mistack;
mistack = temp->next;
nasm_free (temp);

20
names.c
View File

@ -28,7 +28,9 @@ static char *insn_names[] = { /* instruction names, as strings */
"fcmovbe", "fcmove", "fcmovnb", "fcmovnbe", "fcmovne",
"fcmovnu", "fcmovu", "fcom", "fcomi", "fcomip", "fcomp",
"fcompp", "fcos", "fdecstp", "fdisi", "fdiv", "fdivp", "fdivr",
"fdivrp", "feni", "ffree", "fiadd", "ficom", "ficomp", "fidiv",
"fdivrp",
"femms",
"feni", "ffree", "fiadd", "ficom", "ficomp", "fidiv",
"fidivr", "fild", "fimul", "fincstp", "finit", "fist", "fistp",
"fisub", "fisubr", "fld", "fld1", "fldcw", "fldenv", "fldl2e",
"fldl2t", "fldlg2", "fldln2", "fldpi", "fldz", "fmul", "fmulp",
@ -40,7 +42,7 @@ static char *insn_names[] = { /* instruction names, as strings */
"fucomi", "fucomip", "fucomp", "fucompp", "fxam", "fxch",
"fxtract", "fyl2x", "fyl2xp1", "hlt", "ibts", "icebp", "idiv",
"imul", "in", "inc", "incbin", "insb", "insd", "insw", "int",
"int1", "int01", "int3", "into", "invd", "invlpg", "iret",
"int01", "int1", "int3", "into", "invd", "invlpg", "iret",
"iretd", "iretw", "jcxz", "jecxz", "jmp", "lahf", "lar", "lds",
"lea", "leave", "les", "lfs", "lgdt", "lgs", "lidt", "lldt",
"lmsw", "loadall", "loadall286", "lodsb", "lodsd", "lodsw",
@ -49,12 +51,18 @@ static char *insn_names[] = { /* instruction names, as strings */
"movsx", "movzx", "mul", "neg", "nop", "not", "or", "out",
"outsb", "outsd", "outsw", "packssdw", "packsswb", "packuswb",
"paddb", "paddd", "paddsb", "paddsiw", "paddsw", "paddusb",
"paddusw", "paddw", "pand", "pandn", "paveb", "pcmpeqb",
"paddusw", "paddw", "pand", "pandn", "paveb",
"pavgusb", "pcmpeqb",
"pcmpeqd", "pcmpeqw", "pcmpgtb", "pcmpgtd", "pcmpgtw",
"pdistib", "pmachriw", "pmaddwd", "pmagw", "pmulhrw",
"pmulhriw", "pmulhw", "pmullw", "pmvgezb", "pmvlzb", "pmvnzb",
"pdistib",
"pf2id", "pfacc", "pfadd", "pfcmpeq", "pfcmpge", "pfcmpgt",
"pfmax", "pfmin", "pfmul", "pfrcp", "pfrcpit1", "pfrcpit2",
"pfrsqit1", "pfrsqrt", "pfsub", "pfsubr", "pi2fd",
"pmachriw", "pmaddwd", "pmagw", "pmulhriw", "pmulhrwa", "pmulhrwc",
"pmulhw", "pmullw", "pmvgezb", "pmvlzb", "pmvnzb",
"pmvzb", "pop", "popa", "popad", "popaw", "popf", "popfd",
"popfw", "por", "pslld", "psllq", "psllw", "psrad", "psraw",
"popfw", "por",
"prefetch", "prefetchw", "pslld", "psllq", "psllw", "psrad", "psraw",
"psrld", "psrlq", "psrlw", "psubb", "psubd", "psubsb",
"psubsiw", "psubsw", "psubusb", "psubusw", "psubw", "punpckhbw",
"punpckhdq", "punpckhwd", "punpcklbw", "punpckldq", "punpcklwd",

901
nasm.c

File diff suppressed because it is too large Load Diff

186
nasm.h
View File

@ -12,8 +12,8 @@
#define NASM_NASM_H
#define NASM_MAJOR_VER 0
#define NASM_MINOR_VER 97
#define NASM_VER "0.97"
#define NASM_MINOR_VER 98
#define NASM_VER "0.98 pre-release 3"
#ifndef NULL
#define NULL 0
@ -72,9 +72,6 @@ typedef void (*efunc) (int severity, char *fmt, ...);
#define ERR_MASK 0x0F /* mask off the above codes */
#define ERR_NOFILE 0x10 /* don't give source file name/line */
#define ERR_USAGE 0x20 /* print a usage message */
#define ERR_OFFBY1 0x40 /* report error as being on the line
* we're just _about_ to read, not
* the one we've just read */
#define ERR_PASS1 0x80 /* only print this error on pass one */
/*
@ -205,6 +202,12 @@ enum { /* token types, other than chars */
TOKEN_FLOAT /* floating-point constant */
};
typedef struct {
long segment;
long offset;
int known;
} loc_t;
/*
* Expression-evaluator datatype. Expressions, within the
* evaluator, are stored as an array of these beasts, terminated by
@ -260,13 +263,6 @@ typedef expr *(*evalfunc) (scanner sc, void *scprivate, struct tokenval *tv,
int *fwref, int critical, efunc error,
struct eval_hints *hints);
/*
* There's also an auxiliary routine through which the evaluator
* needs to hear about the value of $ and the label (if any)
* defined on the current line.
*/
typedef void (*evalinfofunc) (char *labelname, long segment, long offset);
/*
* Special values for expr->type. ASSUMPTION MADE HERE: the number
* of distinct register names (i.e. possible "type" fields for an
@ -311,11 +307,13 @@ typedef struct {
* ----------------------------------------------------------------
*/
/* isidstart matches any character that may start an identifier, and isidchar
/*
* isidstart matches any character that may start an identifier, and isidchar
* matches any character that may appear at places other than the start of an
* identifier. E.g. a period may only appear at the start of an identifier
* (for local labels), whereas a number may appear anywhere *but* at the
* start. */
* start.
*/
#define isidstart(c) ( isalpha(c) || (c)=='_' || (c)=='.' || (c)=='?' \
|| (c)=='@' )
@ -439,7 +437,9 @@ enum { /* instruction names */
I_FCMOVBE, I_FCMOVE, I_FCMOVNB, I_FCMOVNBE, I_FCMOVNE,
I_FCMOVNU, I_FCMOVU, I_FCOM, I_FCOMI, I_FCOMIP, I_FCOMP,
I_FCOMPP, I_FCOS, I_FDECSTP, I_FDISI, I_FDIV, I_FDIVP, I_FDIVR,
I_FDIVRP, I_FENI, I_FFREE, I_FIADD, I_FICOM, I_FICOMP, I_FIDIV,
I_FDIVRP,
I_FEMMS,
I_FENI, I_FFREE, I_FIADD, I_FICOM, I_FICOMP, I_FIDIV,
I_FIDIVR, I_FILD, I_FIMUL, I_FINCSTP, I_FINIT, I_FIST, I_FISTP,
I_FISUB, I_FISUBR, I_FLD, I_FLD1, I_FLDCW, I_FLDENV, I_FLDL2E,
I_FLDL2T, I_FLDLG2, I_FLDLN2, I_FLDPI, I_FLDZ, I_FMUL, I_FMULP,
@ -451,7 +451,7 @@ enum { /* instruction names */
I_FUCOMI, I_FUCOMIP, I_FUCOMP, I_FUCOMPP, I_FXAM, I_FXCH,
I_FXTRACT, I_FYL2X, I_FYL2XP1, I_HLT, I_IBTS, I_ICEBP, I_IDIV,
I_IMUL, I_IN, I_INC, I_INCBIN, I_INSB, I_INSD, I_INSW, I_INT,
I_INT1, I_INT01, I_INT3, I_INTO, I_INVD, I_INVLPG, I_IRET,
I_INT01, I_INT1, I_INT3, I_INTO, I_INVD, I_INVLPG, I_IRET,
I_IRETD, I_IRETW, I_JCXZ, I_JECXZ, I_JMP, I_LAHF, I_LAR, I_LDS,
I_LEA, I_LEAVE, I_LES, I_LFS, I_LGDT, I_LGS, I_LIDT, I_LLDT,
I_LMSW, I_LOADALL, I_LOADALL286, I_LODSB, I_LODSD, I_LODSW,
@ -460,12 +460,18 @@ enum { /* instruction names */
I_MOVSX, I_MOVZX, I_MUL, I_NEG, I_NOP, I_NOT, I_OR, I_OUT,
I_OUTSB, I_OUTSD, I_OUTSW, I_PACKSSDW, I_PACKSSWB, I_PACKUSWB,
I_PADDB, I_PADDD, I_PADDSB, I_PADDSIW, I_PADDSW, I_PADDUSB,
I_PADDUSW, I_PADDW, I_PAND, I_PANDN, I_PAVEB, I_PCMPEQB,
I_PADDUSW, I_PADDW, I_PAND, I_PANDN, I_PAVEB,
I_PAVGUSB, I_PCMPEQB,
I_PCMPEQD, I_PCMPEQW, I_PCMPGTB, I_PCMPGTD, I_PCMPGTW,
I_PDISTIB, I_PMACHRIW, I_PMADDWD, I_PMAGW, I_PMULHRW,
I_PMULHRIW, I_PMULHW, I_PMULLW, I_PMVGEZB, I_PMVLZB, I_PMVNZB,
I_PDISTIB,
I_PF2ID, I_PFACC, I_PFADD, I_PFCMPEQ, I_PFCMPGE, I_PFCMPGT,
I_PFMAX, I_PFMIN, I_PFMUL, I_PFRCP, I_PFRCPIT1, I_PFRCPIT2,
I_PFRSQIT1, I_PFRSQRT, I_PFSUB, I_PFSUBR, I_PI2FD,
I_PMACHRIW, I_PMADDWD, I_PMAGW, I_PMULHRIW, I_PMULHRWA,
I_PMULHRWC, I_PMULHW, I_PMULLW, I_PMVGEZB, I_PMVLZB, I_PMVNZB,
I_PMVZB, I_POP, I_POPA, I_POPAD, I_POPAW, I_POPF, I_POPFD,
I_POPFW, I_POR, I_PSLLD, I_PSLLQ, I_PSLLW, I_PSRAD, I_PSRAW,
I_POPFW, I_POR, I_PREFETCH, I_PREFETCHW,
I_PSLLD, I_PSLLQ, I_PSLLW, I_PSRAD, I_PSRAW,
I_PSRLD, I_PSRLQ, I_PSRLW, I_PSUBB, I_PSUBD, I_PSUBSB,
I_PSUBSIW, I_PSUBSW, I_PSUBUSB, I_PSUBUSW, I_PSUBW, I_PUNPCKHBW,
I_PUNPCKHDQ, I_PUNPCKHWD, I_PUNPCKLBW, I_PUNPCKLDQ, I_PUNPCKLWD,
@ -480,6 +486,8 @@ enum { /* instruction names */
I_XOR, I_CMOVcc, I_Jcc, I_SETcc
};
#define MAX_KEYWORD 9 /* max length of any instruction, register name etc. */
enum { /* condition code names */
C_A, C_AE, C_B, C_BE, C_C, C_E, C_G, C_GE, C_L, C_LE, C_NA, C_NAE,
C_NB, C_NBE, C_NC, C_NE, C_NG, C_NGE, C_NL, C_NLE, C_NO, C_NP,
@ -522,8 +530,12 @@ typedef struct { /* operand to an instruction */
long offset; /* any immediate number */
long wrt; /* segment base it's relative to */
int eaflags; /* special EA flags */
int opflags; /* see OPFLAG_* defines below */
} operand;
#define OPFLAG_FORWARD 1 /* operand is a forward reference */
#define OPFLAG_EXTERN 2 /* operand is an external reference */
typedef struct extop { /* extended operand */
struct extop *next; /* linked list */
long type; /* defined above */
@ -542,13 +554,16 @@ typedef struct { /* an instruction itself */
int nprefix; /* number of entries in above */
int opcode; /* the opcode - not just the string */
int condition; /* the condition code, if Jcc/SETcc */
int operands; /* how many operands? 0-3 */
int operands; /* how many operands? 0-3
* (more if db et al) */
operand oprs[3]; /* the operands, defined as above */
extop *eops; /* extended operands */
int eops_float; /* true if DD and floating */
long times; /* repeat count (TIMES prefix) */
int forw_ref; /* is there a forward reference? */
} insn;
enum geninfo { GI_SWITCH };
/*
* ------------------------------------------------------------
* The data structure defining an output format driver, and the
@ -568,6 +583,27 @@ struct ofmt {
*/
char *shortname;
/*
* this is reserved for out module specific help.
* It is set to NULL in all the out modules but is not implemented
* in the main program
*/
char *helpstring;
/*
* this is a pointer to the first element of the debug information
*/
struct dfmt **debug_formats;
/*
* and a pointer to the element that is being used
* note: this is set to the default at compile time and changed if the
* -F option is selected. If developing a set of new debug formats for
* an output format, be sure to set this to whatever default you want
*
*/
struct dfmt *current_dfmt;
/*
* This, if non-NULL, is a NULL-terminated list of `char *'s
* pointing to extra standard macros supplied by the object
@ -586,6 +622,15 @@ struct ofmt {
*/
void (*init) (FILE *fp, efunc error, ldfunc ldef, evalfunc eval);
/*
* This procedure is called to pass generic information to the
* object file. The first parameter gives the information type
* (currently only command line switches)
* and the second parameter gives the value. This function returns
* 1 if recognized, 0 if unrecognized
*/
int (*setinfo)(enum geninfo type, char **string);
/*
* This procedure is called by assemble() to write actual
* generated code or data to the object file. Typically it
@ -705,7 +750,7 @@ struct ofmt {
* One thing the cleanup routine should always do is to close
* the output file pointer.
*/
void (*cleanup) (void);
void (*cleanup) (int debuginfo);
};
/*
@ -734,6 +779,103 @@ struct ofmt {
#define OUT_TYPMASK 0xF0000000UL
#define OUT_SIZMASK 0x0FFFFFFFUL
/*
* ------------------------------------------------------------
* The data structure defining a debug format driver, and the
* interfaces to the functions therein.
* ------------------------------------------------------------
*/
struct dfmt {
/*
* This is a short (one-liner) description of the type of
* output generated by the driver.
*/
char *fullname;
/*
* This is a single keyword used to select the driver.
*/
char *shortname;
/*
* init - called initially to set up local pointer to object format,
* void pointer to implementation defined data, file pointer (which
* probably won't be used, but who knows?), and error function.
*/
void (*init) (struct ofmt * of, void * id, FILE * fp, efunc error);
/*
* linenum - called any time there is output with a change of
* line number or file.
*/
void (*linenum) (const char * filename, long linenumber, long segto);
/*
* debug_deflabel - called whenever a label is defined. Parameters
* are the same as to 'symdef()' in the output format. This function
* would be called before the output format version.
*/
void (*debug_deflabel) (char * name, long segment, long offset,
int is_global, char * special);
/*
* debug_directive - called whenever a DEBUG directive other than 'LINE'
* is encountered. 'directive' contains the first parameter to the
* DEBUG directive, and params contains the rest. For example,
* 'DEBUG VAR _somevar:int' would translate to a call to this
* function with 'directive' equal to "VAR" and 'params' equal to
* "_somevar:int".
*/
void (*debug_directive) (const char * directive, const char * params);
/*
* typevalue - called whenever the assembler wishes to register a type
* for the last defined label. This routine MUST detect if a type was
* already registered and not re-register it.
*/
void (*debug_typevalue) (long type);
/*
* debug_output - called whenever output is required
* 'type' is the type of info required, and this is format-specific
*/
void (*debug_output) (int type, void *param);
/*
* cleanup - called after processing of file is complete
*/
void (*cleanup) (void);
};
/*
* The type definition macros
* for debugging
*
* low 3 bits: reserved
* next 5 bits: type
* next 24 bits: number of elements for arrays (0 for labels)
*/
#define TY_UNKNOWN 0x00
#define TY_LABEL 0x08
#define TY_BYTE 0x10
#define TY_WORD 0x18
#define TY_DWORD 0x20
#define TY_FLOAT 0x28
#define TY_QWORD 0x30
#define TY_TBYTE 0x38
#define TY_COMMON 0xE0
#define TY_SEG 0xE8
#define TY_EXTERN 0xF0
#define TY_EQU 0xF8
#define TYM_TYPE(x) ((x) & 0xF8)
#define TYM_ELEMENTS(x) (((x) & 0xFFFFFF00) >> 8)
#define TYS_ELEMENTS(x) ((x) << 8)
/*
* -----
* Other

360
nasmlib.c
View File

@ -20,7 +20,8 @@ static efunc nasm_malloc_error;
static FILE *logfp;
#endif
void nasm_set_malloc_error (efunc error) {
void nasm_set_malloc_error (efunc error)
{
nasm_malloc_error = error;
#ifdef LOGALLOC
logfp = fopen ("malloc.log", "w");
@ -124,7 +125,8 @@ char *nasm_strndup (char *s, size_t len)
return p;
}
int nasm_stricmp (char *s1, char *s2) {
int nasm_stricmp (const char *s1, const char *s2)
{
while (*s1 && toupper(*s1) == toupper(*s2))
s1++, s2++;
if (!*s1 && !*s2)
@ -135,7 +137,8 @@ int nasm_stricmp (char *s1, char *s2) {
return 1;
}
int nasm_strnicmp (char *s1, char *s2, int n) {
int nasm_strnicmp (const char *s1, const char *s2, int n)
{
while (n > 0 && *s1 && toupper(*s1) == toupper(*s2))
s1++, s2++, n--;
if ((!*s1 && !*s2) || n==0)
@ -149,15 +152,29 @@ int nasm_strnicmp (char *s1, char *s2, int n) {
#define lib_isnumchar(c) ( isalnum(c) || (c) == '$')
#define numvalue(c) ((c)>='a' ? (c)-'a'+10 : (c)>='A' ? (c)-'A'+10 : (c)-'0')
long readnum (char *str, int *error) {
long readnum (char *str, int *error)
{
char *r = str, *q;
long radix;
unsigned long result, checklimit;
int digit, last;
int warn = FALSE;
int sign = 1;
*error = FALSE;
while (isspace(*r)) r++; /* find start of number */
/*
* If the number came from make_tok_num (as a result of an %assign), it
* might have a '-' built into it (rather than in a preceeding token).
*/
if (*r == '-')
{
r++;
sign = -1;
}
q = r;
while (lib_isnumchar(*q)) q++; /* find end of number */
@ -199,15 +216,26 @@ long readnum (char *str, int *error) {
*/
checklimit = 0x80000000UL / (radix>>1);
/*
* Calculate the highest allowable value for the last digit
* of a 32 bit constant... in radix 10, it is 6, otherwise it is 0
*/
last = (radix == 10 ? 6 : 0);
result = 0;
while (*r && r < q) {
if (*r<'0' || (*r>'9' && *r<'A') || numvalue(*r)>=radix) {
if (*r<'0' || (*r>'9' && *r<'A') || (digit = numvalue(*r)) >= radix)
{
*error = TRUE;
return 0;
}
if (result >= checklimit)
if (result > checklimit ||
(result == checklimit && digit >= last))
{
warn = TRUE;
result = radix * result + numvalue(*r);
}
result = radix * result + digit;
r++;
}
@ -216,25 +244,46 @@ long readnum (char *str, int *error) {
"numeric constant %s does not fit in 32 bits",
str);
return result;
return result*sign;
}
long readstrnum (char *str, int length, int *warn)
{
long charconst = 0;
int i;
*warn = FALSE;
str += length;
for (i=0; i<length; i++) {
if (charconst & 0xff000000UL) {
*warn = TRUE;
}
charconst = (charconst<<8) + (unsigned char) *--str;
}
return charconst;
}
static long next_seg;
void seg_init(void) {
void seg_init(void)
{
next_seg = 0;
}
long seg_alloc(void) {
long seg_alloc(void)
{
return (next_seg += 2) - 2;
}
void fwriteshort (int data, FILE *fp) {
void fwriteshort (int data, FILE *fp)
{
fputc ((int) (data & 255), fp);
fputc ((int) ((data >> 8) & 255), fp);
}
void fwritelong (long data, FILE *fp) {
void fwritelong (long data, FILE *fp)
{
fputc ((int) (data & 255), fp);
fputc ((int) ((data >> 8) & 255), fp);
fputc ((int) ((data >> 16) & 255), fp);
@ -242,7 +291,8 @@ void fwritelong (long data, FILE *fp) {
}
void standard_extension (char *inname, char *outname, char *extension,
efunc error) {
efunc error)
{
char *p, *q;
if (*outname) /* file name already exists, */
@ -268,47 +318,13 @@ void standard_extension (char *inname, char *outname, char *extension,
strcpy(p, extension);
}
#define RAA_BLKSIZE 4096 /* this many longs allocated at once */
#define RAA_LAYERSIZE 1024 /* this many _pointers_ allocated */
typedef struct RAA RAA;
typedef union RAA_UNION RAA_UNION;
typedef struct RAA_LEAF RAA_LEAF;
typedef struct RAA_BRANCH RAA_BRANCH;
struct RAA {
/*
* Number of layers below this one to get to the real data. 0
* means this structure is a leaf, holding RAA_BLKSIZE real
* data items; 1 and above mean it's a branch, holding
* RAA_LAYERSIZE pointers to the next level branch or leaf
* structures.
*/
int layers;
/*
* Number of real data items spanned by one position in the
* `data' array at this level. This number is 1, trivially, for
* a leaf (level 0): for a level 1 branch it should be
* RAA_BLKSIZE, and for a level 2 branch it's
* RAA_LAYERSIZE*RAA_BLKSIZE.
*/
long stepsize;
union RAA_UNION {
struct RAA_LEAF {
long data[RAA_BLKSIZE];
} l;
struct RAA_BRANCH {
struct RAA *data[RAA_LAYERSIZE];
} b;
} u;
};
#define LEAFSIZ (sizeof(RAA)-sizeof(RAA_UNION)+sizeof(RAA_LEAF))
#define BRANCHSIZ (sizeof(RAA)-sizeof(RAA_UNION)+sizeof(RAA_BRANCH))
#define LAYERSIZ(r) ( (r)->layers==0 ? RAA_BLKSIZE : RAA_LAYERSIZE )
static struct RAA *real_raa_init (int layers) {
static struct RAA *real_raa_init (int layers)
{
struct RAA *r;
if (layers == 0) {
@ -327,11 +343,13 @@ static struct RAA *real_raa_init (int layers) {
return r;
}
struct RAA *raa_init (void) {
struct RAA *raa_init (void)
{
return real_raa_init (0);
}
void raa_free (struct RAA *r) {
void raa_free (struct RAA *r)
{
if (r->layers == 0)
nasm_free (r);
else {
@ -342,7 +360,8 @@ void raa_free (struct RAA *r) {
}
}
long raa_read (struct RAA *r, long posn) {
long raa_read (struct RAA *r, long posn)
{
if (posn > r->stepsize * LAYERSIZ(r))
return 0L;
while (r->layers > 0) {
@ -356,7 +375,8 @@ long raa_read (struct RAA *r, long posn) {
return r->u.l.data[posn];
}
struct RAA *raa_write (struct RAA *r, long posn, long value) {
struct RAA *raa_write (struct RAA *r, long posn, long value)
{
struct RAA *result;
if (posn < 0)
@ -396,17 +416,8 @@ struct RAA *raa_write (struct RAA *r, long posn, long value) {
#define SAA_MAXLEN 8192
struct SAA {
/*
* members `end' and `elem_len' are only valid in first link in
* list; `rptr' and `rpos' are used for reading
*/
struct SAA *next, *end, *rptr;
long elem_len, length, posn, start, rpos;
char *data;
};
struct SAA *saa_init (long elem_len) {
struct SAA *saa_init (long elem_len)
{
struct SAA *s;
if (elem_len > SAA_MAXLEN)
@ -423,7 +434,8 @@ struct SAA *saa_init (long elem_len) {
return s;
}
void saa_free (struct SAA *s) {
void saa_free (struct SAA *s)
{
struct SAA *t;
while (s) {
@ -434,7 +446,8 @@ void saa_free (struct SAA *s) {
}
}
void *saa_wstruct (struct SAA *s) {
void *saa_wstruct (struct SAA *s)
{
void *p;
if (s->end->length - s->end->posn < s->elem_len) {
@ -452,7 +465,8 @@ void *saa_wstruct (struct SAA *s) {
return p;
}
void saa_wbytes (struct SAA *s, void *data, long len) {
void saa_wbytes (struct SAA *s, void *data, long len)
{
char *d = data;
while (len > 0) {
@ -480,12 +494,14 @@ void saa_wbytes (struct SAA *s, void *data, long len) {
}
}
void saa_rewind (struct SAA *s) {
void saa_rewind (struct SAA *s)
{
s->rptr = s;
s->rpos = 0L;
}
void *saa_rstruct (struct SAA *s) {
void *saa_rstruct (struct SAA *s)
{
void *p;
if (!s->rptr)
@ -503,7 +519,8 @@ void *saa_rstruct (struct SAA *s) {
return p;
}
void *saa_rbytes (struct SAA *s, long *len) {
void *saa_rbytes (struct SAA *s, long *len)
{
void *p;
if (!s->rptr)
@ -516,7 +533,8 @@ void *saa_rbytes (struct SAA *s, long *len) {
return p;
}
void saa_rnbytes (struct SAA *s, void *data, long len) {
void saa_rnbytes (struct SAA *s, void *data, long len)
{
char *d = data;
while (len > 0) {
@ -541,26 +559,27 @@ void saa_rnbytes (struct SAA *s, void *data, long len) {
}
}
void saa_fread (struct SAA *s, long posn, void *data, long len) {
void saa_fread (struct SAA *s, long posn, void *data, long len)
{
struct SAA *p;
long pos;
char *cdata = data;
if (!s->rptr || posn > s->rptr->start + s->rpos)
if (!s->rptr || posn < s->rptr->start)
saa_rewind (s);
while (posn >= s->rptr->start + s->rptr->posn) {
s->rptr = s->rptr->next;
if (!s->rptr)
p = s->rptr;
while (posn >= p->start + p->posn) {
p = p->next;
if (!p)
return; /* what else can we do?! */
}
p = s->rptr;
pos = posn - s->rptr->start;
pos = posn - p->start;
while (len) {
long l = s->rptr->posn - pos;
long l = p->posn - pos;
if (l > len)
l = len;
memcpy (cdata, s->rptr->data+pos, l);
memcpy (cdata, p->data+pos, l);
len -= l;
cdata += l;
p = p->next;
@ -568,28 +587,30 @@ void saa_fread (struct SAA *s, long posn, void *data, long len) {
return;
pos = 0L;
}
s->rptr = p;
}
void saa_fwrite (struct SAA *s, long posn, void *data, long len) {
void saa_fwrite (struct SAA *s, long posn, void *data, long len)
{
struct SAA *p;
long pos;
char *cdata = data;
if (!s->rptr || posn > s->rptr->start + s->rpos)
if (!s->rptr || posn < s->rptr->start)
saa_rewind (s);
while (posn >= s->rptr->start + s->rptr->posn) {
s->rptr = s->rptr->next;
if (!s->rptr)
p = s->rptr;
while (posn >= p->start + p->posn) {
p = p->next;
if (!p)
return; /* what else can we do?! */
}
p = s->rptr;
pos = posn - s->rptr->start;
pos = posn - p->start;
while (len) {
long l = s->rptr->posn - pos;
long l = p->posn - pos;
if (l > len)
l = len;
memcpy (s->rptr->data+pos, cdata, l);
memcpy (p->data+pos, cdata, l);
len -= l;
cdata += l;
p = p->next;
@ -597,9 +618,11 @@ void saa_fwrite (struct SAA *s, long posn, void *data, long len) {
return;
pos = 0L;
}
s->rptr = p;
}
void saa_fpwrite (struct SAA *s, FILE *fp) {
void saa_fpwrite (struct SAA *s, FILE *fp)
{
char *data;
long len;
@ -632,16 +655,29 @@ static char **stdscan_tempstorage = NULL;
static int stdscan_tempsize = 0, stdscan_templen = 0;
#define STDSCAN_TEMP_DELTA 256
static void stdscan_pop(void) {
static void stdscan_pop(void)
{
nasm_free (stdscan_tempstorage[--stdscan_templen]);
}
void stdscan_reset(void) {
void stdscan_reset(void)
{
while (stdscan_templen > 0)
stdscan_pop();
}
static char *stdscan_copy(char *p, int len) {
/*
* Unimportant cleanup is done to avoid confusing people who are trying
* to debug real memory leaks
*/
void nasmlib_cleanup (void)
{
stdscan_reset();
nasm_free (stdscan_tempstorage);
}
static char *stdscan_copy(char *p, int len)
{
char *text;
text = nasm_malloc(len+1);
@ -659,8 +695,11 @@ static char *stdscan_copy(char *p, int len) {
}
char *stdscan_bufptr = NULL;
int stdscan (void *private_data, struct tokenval *tv) {
char ourcopy[256], *r, *s;
int stdscan (void *private_data, struct tokenval *tv)
{
char ourcopy[MAX_KEYWORD+1], *r, *s;
(void) private_data; /* Don't warn that this parameter is unused */
while (isspace(*stdscan_bufptr)) stdscan_bufptr++;
if (!*stdscan_bufptr)
@ -682,11 +721,12 @@ int stdscan (void *private_data, struct tokenval *tv) {
while (isidchar(*stdscan_bufptr)) stdscan_bufptr++;
tv->t_charptr = stdscan_copy(r, stdscan_bufptr - r);
if (is_sym || stdscan_bufptr-r > MAX_KEYWORD)
return tv->t_type = TOKEN_ID;/* bypass all other checks */
for (s=tv->t_charptr, r=ourcopy; *s; s++)
*r++ = tolower (*s);
*r = '\0';
if (is_sym)
return tv->t_type = TOKEN_ID;/* bypass all other checks */
/* right, so we have an identifier sitting in temp storage. now,
* is it actually a register or instruction name, or what? */
if ((tv->t_integer=bsi(ourcopy, reg_names,
@ -743,7 +783,10 @@ int stdscan (void *private_data, struct tokenval *tv) {
* a floating point constant
*/
stdscan_bufptr++;
while (isnumchar(*stdscan_bufptr)) {
while (isnumchar(*stdscan_bufptr) ||
((stdscan_bufptr[-1] == 'e' || stdscan_bufptr[-1] == 'E')
&& (*stdscan_bufptr == '-' || *stdscan_bufptr == '+')) )
{
stdscan_bufptr++;
}
tv->t_charptr = stdscan_copy(r, stdscan_bufptr - r);
@ -759,16 +802,15 @@ int stdscan (void *private_data, struct tokenval *tv) {
} else if (*stdscan_bufptr == '\'' ||
*stdscan_bufptr == '"') {/* a char constant */
char quote = *stdscan_bufptr++, *r;
int rn_warn;
r = tv->t_charptr = stdscan_bufptr;
while (*stdscan_bufptr && *stdscan_bufptr != quote) stdscan_bufptr++;
tv->t_inttwo = stdscan_bufptr - r; /* store full version */
if (!*stdscan_bufptr)
return tv->t_type = TOKEN_ERRNUM; /* unmatched quotes */
tv->t_integer = 0;
r = stdscan_bufptr++; /* skip over final quote */
while (quote != *--r) {
tv->t_integer = (tv->t_integer<<8) + (unsigned char) *r;
}
stdscan_bufptr++; /* skip over final quote */
tv->t_integer = readstrnum(r, tv->t_inttwo, &rn_warn);
/* FIXME: rn_warn is not checked! */
return tv->t_type = TOKEN_NUM;
} else if (*stdscan_bufptr == ';') { /* a comment has happened - stay */
return tv->t_type = 0;
@ -816,7 +858,8 @@ int stdscan (void *private_data, struct tokenval *tv) {
* Return TRUE if the argument is a simple scalar. (Or a far-
* absolute, which counts.)
*/
int is_simple (expr *vect) {
int is_simple (expr *vect)
{
while (vect->type && !vect->value)
vect++;
if (!vect->type)
@ -834,7 +877,8 @@ int is_simple (expr *vect) {
* Return TRUE if the argument is a simple scalar, _NOT_ a far-
* absolute.
*/
int is_really_simple (expr *vect) {
int is_really_simple (expr *vect)
{
while (vect->type && !vect->value)
vect++;
if (!vect->type)
@ -852,7 +896,8 @@ int is_really_simple (expr *vect) {
* Return TRUE if the argument is relocatable (i.e. a simple
* scalar, plus at most one segment-base, plus possibly a WRT).
*/
int is_reloc (expr *vect) {
int is_reloc (expr *vect)
{
while (vect->type && !vect->value) /* skip initial value-0 terms */
vect++;
if (!vect->type) /* trivially return TRUE if nothing */
@ -886,7 +931,8 @@ int is_reloc (expr *vect) {
/*
* Return TRUE if the argument contains an `unknown' part.
*/
int is_unknown(expr *vect) {
int is_unknown(expr *vect)
{
while (vect->type && vect->type < EXPR_UNKNOWN)
vect++;
return (vect->type == EXPR_UNKNOWN);
@ -896,7 +942,8 @@ int is_unknown(expr *vect) {
* Return TRUE if the argument contains nothing but an `unknown'
* part.
*/
int is_just_unknown(expr *vect) {
int is_just_unknown(expr *vect)
{
while (vect->type && !vect->value)
vect++;
return (vect->type == EXPR_UNKNOWN);
@ -906,7 +953,8 @@ int is_just_unknown(expr *vect) {
* Return the scalar part of a relocatable vector. (Including
* simple scalar vectors - those qualify as relocatable.)
*/
long reloc_value (expr *vect) {
long reloc_value (expr *vect)
{
while (vect->type && !vect->value)
vect++;
if (!vect->type) return 0;
@ -920,7 +968,8 @@ long reloc_value (expr *vect) {
* Return the segment number of a relocatable vector, or NO_SEG for
* simple scalars.
*/
long reloc_seg (expr *vect) {
long reloc_seg (expr *vect)
{
while (vect->type && (vect->type == EXPR_WRT || !vect->value))
vect++;
if (vect->type == EXPR_SIMPLE) {
@ -938,7 +987,8 @@ long reloc_seg (expr *vect) {
* Return the WRT segment number of a relocatable vector, or NO_SEG
* if no WRT part is present.
*/
long reloc_wrt (expr *vect) {
long reloc_wrt (expr *vect)
{
while (vect->type && vect->type < EXPR_WRT)
vect++;
if (vect->type == EXPR_WRT) {
@ -950,7 +1000,8 @@ long reloc_wrt (expr *vect) {
/*
* Binary search.
*/
int bsi (char *string, char **array, int size) {
int bsi (char *string, char **array, int size)
{
int i = -1, j = size; /* always, i < index < j */
while (j-i >= 2) {
int k = (i+j)/2;
@ -964,3 +1015,88 @@ int bsi (char *string, char **array, int size) {
}
return -1; /* we haven't got it :( */
}
static char *file_name = NULL;
static long line_number = 0;
char *src_set_fname(char *newname)
{
char *oldname = file_name;
file_name = newname;
return oldname;
}
long src_set_linnum(long newline)
{
long oldline = line_number;
line_number = newline;
return oldline;
}
long src_get_linnum(void)
{
return line_number;
}
int src_get(long *xline, char **xname)
{
if (!file_name || !*xname || strcmp(*xname, file_name))
{
nasm_free(*xname);
*xname = file_name ? nasm_strdup(file_name) : NULL;
*xline = line_number;
return -2;
}
if (*xline != line_number)
{
long tmp = line_number - *xline;
*xline = line_number;
return tmp;
}
return 0;
}
void nasm_quote(char **str)
{
int ln=strlen(*str);
char q=(*str)[0];
char *p;
if (ln>1 && (*str)[ln-1]==q && (q=='"' || q=='\''))
return;
q = '"';
if (strchr(*str,q))
q = '\'';
p = nasm_malloc(ln+3);
strcpy(p+1, *str);
nasm_free(*str);
p[ln+1] = p[0] = q;
p[ln+2] = 0;
*str = p;
}
char *nasm_strcat(char *one, char *two)
{
char *rslt;
int l1=strlen(one);
rslt = nasm_malloc(l1+strlen(two)+1);
strcpy(rslt, one);
strcpy(rslt+l1, two);
return rslt;
}
void null_debug_routine()
{
}
struct dfmt null_debug_form = {
"Null debug format",
"null",
null_debug_routine,
null_debug_routine,
null_debug_routine,
null_debug_routine,
null_debug_routine,
null_debug_routine,
null_debug_routine,
};
struct dfmt *null_debug_arr[2] = { &null_debug_form, NULL };

View File

@ -1,4 +1,4 @@
/* nasmlib.c header file for nasmlib.h
/* nasmlib.h header file for nasmlib.c
*
* The Netwide Assembler is copyright (C) 1996 Simon Tatham and
* Julian Hall. All rights reserved. The software is
@ -51,8 +51,8 @@ char *nasm_strndup_log (char *, int, char *, size_t);
* ANSI doesn't guarantee the presence of `stricmp' or
* `strcasecmp'.
*/
int nasm_stricmp (char *, char *);
int nasm_strnicmp (char *, char *, int);
int nasm_stricmp (const char *, const char *);
int nasm_strnicmp (const char *, const char *, int);
/*
* Convert a string into a number, using NASM number rules. Sets
@ -60,6 +60,14 @@ int nasm_strnicmp (char *, char *, int);
*/
long readnum(char *str, int *error);
/*
* Convert a character constant into a number. Sets
* `*warn' to TRUE if an overflow occurs, and FALSE otherwise.
* str points to and length covers the middle of the string,
* without the quotes.
*/
long readstrnum(char *str, int length, int *warn);
/*
* seg_init: Initialise the segment-number allocator.
* seg_alloc: allocate a hitherto unused segment number.
@ -108,7 +116,41 @@ void fwritelong (long data, FILE *fp);
* chunk.
*/
struct RAA;
#define RAA_BLKSIZE 4096 /* this many longs allocated at once */
#define RAA_LAYERSIZE 1024 /* this many _pointers_ allocated */
typedef struct RAA RAA;
typedef union RAA_UNION RAA_UNION;
typedef struct RAA_LEAF RAA_LEAF;
typedef struct RAA_BRANCH RAA_BRANCH;
struct RAA {
/*
* Number of layers below this one to get to the real data. 0
* means this structure is a leaf, holding RAA_BLKSIZE real
* data items; 1 and above mean it's a branch, holding
* RAA_LAYERSIZE pointers to the next level branch or leaf
* structures.
*/
int layers;
/*
* Number of real data items spanned by one position in the
* `data' array at this level. This number is 1, trivially, for
* a leaf (level 0): for a level 1 branch it should be
* RAA_BLKSIZE, and for a level 2 branch it's
* RAA_LAYERSIZE*RAA_BLKSIZE.
*/
long stepsize;
union RAA_UNION {
struct RAA_LEAF {
long data[RAA_BLKSIZE];
} l;
struct RAA_BRANCH {
struct RAA *data[RAA_LAYERSIZE];
} b;
} u;
};
struct RAA *raa_init (void);
void raa_free (struct RAA *);
@ -125,7 +167,15 @@ struct RAA *raa_write (struct RAA *r, long posn, long value);
* of a given size.
*/
struct SAA;
struct SAA {
/*
* members `end' and `elem_len' are only valid in first link in
* list; `rptr' and `rpos' are used for reading
*/
struct SAA *next, *end, *rptr;
long elem_len, length, posn, start, rpos;
char *data;
};
struct SAA *saa_init (long elem_len); /* 1 == byte */
void saa_free (struct SAA *);
@ -169,4 +219,23 @@ long reloc_wrt(expr *);
*/
int bsi (char *string, char **array, int size);
char *src_set_fname(char *newname);
long src_set_linnum(long newline);
long src_get_linnum(void);
/*
* src_get may be used if you simply want to know the source file and line.
* It is also used if you maintain private status about the source location
* It return 0 if the information was the same as the last time you
* checked, -1 if the name changed and (new-old) if just the line changed.
*/
int src_get(long *xline, char **xname);
void nasm_quote(char **str);
char *nasm_strcat(char *one, char *two);
void nasmlib_cleanup(void);
void null_debug_routine();
extern struct dfmt null_debug_form;
extern struct dfmt *null_debug_arr[2];
#endif

View File

@ -33,7 +33,8 @@ static const char *help =
static void output_ins (unsigned long, unsigned char *, int, char *);
static void skip (unsigned long dist, FILE *fp);
int main(int argc, char **argv) {
int main(int argc, char **argv)
{
unsigned char buffer[INSN_MAX * 2], *p, *q;
char outbuf[256];
char *pname = *argv;
@ -52,7 +53,7 @@ int main(int argc, char **argv) {
while (--argc) {
char *v, *vv, *p = *++argv;
if (*p == '-') {
if (*p == '-' && p[1]) {
p++;
while (*p) switch (tolower(*p)) {
case 'a': /* auto or intelligent sync */
@ -170,12 +171,16 @@ int main(int argc, char **argv) {
return 0;
}
fp = fopen(filename, "rb");
if (!fp) {
fprintf(stderr, "%s: unable to open `%s': %s\n",
pname, filename, strerror(errno));
return 1;
}
if (strcmp(filename, "-")) {
fp = fopen(filename, "rb");
if (!fp) {
fprintf(stderr, "%s: unable to open `%s': %s\n",
pname, filename, strerror(errno));
return 1;
}
} else
fp = stdin;
if (initskip > 0)
skip (initskip, fp);
@ -191,9 +196,12 @@ int main(int argc, char **argv) {
unsigned long to_read = buffer+sizeof(buffer)-p;
if (to_read > nextsync-offset-(p-q))
to_read = nextsync-offset-(p-q);
lenread = fread (p, 1, to_read, fp);
if (lenread == 0)
eof = TRUE; /* help along systems with bad feof */
if (to_read) {
lenread = fread (p, 1, to_read, fp);
if (lenread == 0)
eof = TRUE; /* help along systems with bad feof */
} else
lenread = 0;
p += lenread;
if (offset == nextsync) {
if (synclen) {
@ -222,12 +230,16 @@ int main(int argc, char **argv) {
q = buffer;
}
} while (lenread > 0 || !(eof || feof(fp)));
fclose (fp);
if (fp != stdin)
fclose (fp);
return 0;
}
static void output_ins (unsigned long offset, unsigned char *data,
int datalen, char *insn) {
int datalen, char *insn)
{
int bytes;
printf("%08lX ", offset);
@ -256,7 +268,8 @@ static void output_ins (unsigned long offset, unsigned char *data,
* Skip a certain amount of data in a file, either by seeking if
* possible, or if that fails then by reading and discarding.
*/
static void skip (unsigned long dist, FILE *fp) {
static void skip (unsigned long dist, FILE *fp)
{
char buffer[256]; /* should fit on most stacks :-) */
/*

View File

@ -116,7 +116,8 @@ static long aout_gotpc_sect, aout_gotoff_sect;
static long aout_got_sect, aout_plt_sect;
static long aout_sym_sect;
static void aoutg_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) {
static void aoutg_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval)
{
aoutfp = fp;
error = errfunc;
evaluate = eval;
@ -140,7 +141,8 @@ static void aoutg_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) {
#ifdef OF_AOUT
static void aout_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) {
static void aout_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval)
{
bsd = FALSE;
aoutg_init (fp, errfunc, ldef, eval);
@ -154,7 +156,8 @@ static void aout_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) {
extern struct ofmt of_aoutb;
static void aoutb_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) {
static void aoutb_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval)
{
bsd = TRUE;
aoutg_init (fp, errfunc, ldef, eval);
@ -174,9 +177,12 @@ static void aoutb_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) {
#endif
static void aout_cleanup(void) {
static void aout_cleanup(int debuginfo)
{
struct Reloc *r;
(void) debuginfo;
aout_pad_sections();
aout_fixup_relocs(&stext);
aout_fixup_relocs(&sdata);
@ -199,7 +205,8 @@ static void aout_cleanup(void) {
saa_free (strs);
}
static long aout_section_names (char *name, int pass, int *bits) {
static long aout_section_names (char *name, int pass, int *bits)
{
/*
* Default to 32 bits.
*/
@ -220,7 +227,8 @@ static long aout_section_names (char *name, int pass, int *bits) {
}
static void aout_deflabel (char *name, long segment, long offset,
int is_global, char *special) {
int is_global, char *special)
{
int pos = strslen+4;
struct Symbol *sym;
int special_used = FALSE;
@ -384,7 +392,8 @@ static void aout_deflabel (char *name, long segment, long offset,
}
static void aout_add_reloc (struct Section *sect, long segment,
int reltype, int bytes) {
int reltype, int bytes)
{
struct Reloc *r;
r = *sect->tail = nasm_malloc(sizeof(struct Reloc));
@ -429,7 +438,8 @@ static void aout_add_reloc (struct Section *sect, long segment,
*/
static long aout_add_gsym_reloc (struct Section *sect,
long segment, long offset,
int type, int bytes, int exact) {
int type, int bytes, int exact)
{
struct Symbol *sym, *sm, *shead;
struct Reloc *r;
@ -500,7 +510,8 @@ static long aout_add_gsym_reloc (struct Section *sect,
* offset from the `asym' symbol rather than the section.
*/
static long aout_add_gotoff_reloc (struct Section *sect, long segment,
long offset, int bytes) {
long offset, int bytes)
{
struct Reloc *r;
struct Symbol *asym;
@ -534,7 +545,8 @@ static long aout_add_gotoff_reloc (struct Section *sect, long segment,
}
static void aout_out (long segto, void *data, unsigned long type,
long segment, long wrt) {
long segment, long wrt)
{
struct Section *s;
long realbytes = type & OUT_SIZMASK;
long addr;
@ -695,7 +707,8 @@ static void aout_out (long segto, void *data, unsigned long type,
}
}
static void aout_pad_sections(void) {
static void aout_pad_sections(void)
{
static unsigned char pad[] = { 0x90, 0x90, 0x90, 0x90 };
/*
* Pad each of the text and data sections with NOPs until their
@ -716,7 +729,8 @@ static void aout_pad_sections(void) {
* the relocation table, _after_ the final size of each section is
* known, and fix up the relocations pointed to.
*/
static void aout_fixup_relocs(struct Section *sect) {
static void aout_fixup_relocs(struct Section *sect)
{
struct Reloc *r;
saa_rewind (sect->data);
@ -748,7 +762,8 @@ static void aout_fixup_relocs(struct Section *sect) {
}
}
static void aout_write(void) {
static void aout_write(void)
{
/*
* Emit the a.out header.
*/
@ -786,7 +801,8 @@ static void aout_write(void) {
saa_fpwrite (strs, aoutfp);
}
static void aout_write_relocs (struct Reloc *r) {
static void aout_write_relocs (struct Reloc *r)
{
while (r) {
unsigned long word2;
@ -805,7 +821,8 @@ static void aout_write_relocs (struct Reloc *r) {
}
}
static void aout_write_syms (void) {
static void aout_write_syms (void)
{
int i;
saa_rewind (syms);
@ -835,28 +852,38 @@ static void aout_write_syms (void) {
}
static void aout_sect_write (struct Section *sect,
unsigned char *data, unsigned long len) {
unsigned char *data, unsigned long len)
{
saa_wbytes (sect->data, data, len);
sect->len += len;
}
static long aout_segbase (long segment) {
static long aout_segbase (long segment)
{
return segment;
}
static int aout_directive (char *directive, char *value, int pass) {
static int aout_directive (char *directive, char *value, int pass)
{
return 0;
}
static void aout_filename (char *inname, char *outname, efunc error) {
static void aout_filename (char *inname, char *outname, efunc error)
{
standard_extension (inname, outname, ".o", error);
}
static char *aout_stdmac[] = {
"%define __SECT__ [section .text]",
"%macro __NASM_CDecl__ 1",
"%endmacro",
NULL
};
static int aout_set_info(enum geninfo type, char **val)
{
return 0;
}
#endif /* OF_AOUT || OF_AOUTB */
#ifdef OF_AOUT
@ -864,8 +891,12 @@ static char *aout_stdmac[] = {
struct ofmt of_aout = {
"Linux a.out object files",
"aout",
NULL,
null_debug_arr,
&null_debug_form,
aout_stdmac,
aout_init,
aout_set_info,
aout_out,
aout_deflabel,
aout_section_names,
@ -882,8 +913,12 @@ struct ofmt of_aout = {
struct ofmt of_aoutb = {
"NetBSD/FreeBSD a.out object files",
"aoutb",
NULL,
null_debug_arr,
&null_debug_form,
aout_stdmac,
aoutb_init,
aout_set_info,
aout_out,
aout_deflabel,
aout_section_names,

View File

@ -80,7 +80,8 @@ static void as86_write_section (struct Section *, int);
static int as86_add_string (char *name);
static void as86_sect_write(struct Section *, unsigned char *, unsigned long);
static void as86_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) {
static void as86_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval)
{
as86fp = fp;
error = errfunc;
(void) ldef; /* placate optimisers */
@ -105,9 +106,12 @@ static void as86_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) {
as86_add_string (as86_module);
}
static void as86_cleanup(void) {
static void as86_cleanup(int debuginfo)
{
struct Piece *p;
(void) debuginfo;
as86_write();
fclose (as86fp);
saa_free (stext.data);
@ -127,7 +131,8 @@ static void as86_cleanup(void) {
saa_free (strs);
}
static long as86_section_names (char *name, int pass, int *bits) {
static long as86_section_names (char *name, int pass, int *bits)
{
/*
* Default is 16 bits.
*/
@ -147,7 +152,8 @@ static long as86_section_names (char *name, int pass, int *bits) {
return NO_SEG;
}
static int as86_add_string (char *name) {
static int as86_add_string (char *name)
{
int pos = strslen;
int length = strlen(name);
@ -158,7 +164,8 @@ static int as86_add_string (char *name) {
}
static void as86_deflabel (char *name, long segment, long offset,
int is_global, char *special) {
int is_global, char *special)
{
struct Symbol *sym;
if (special)
@ -207,7 +214,8 @@ static void as86_deflabel (char *name, long segment, long offset,
}
static void as86_add_piece (struct Section *sect, int type, long offset,
long segment, long bytes, int relative) {
long segment, long bytes, int relative)
{
struct Piece *p;
sect->len += bytes;
@ -237,7 +245,8 @@ static void as86_add_piece (struct Section *sect, int type, long offset,
}
static void as86_out (long segto, void *data, unsigned long type,
long segment, long wrt) {
long segment, long wrt)
{
struct Section *s;
long realbytes = type & OUT_SIZMASK;
long offset;
@ -339,7 +348,8 @@ static void as86_out (long segto, void *data, unsigned long type,
}
}
static void as86_write(void) {
static void as86_write(void)
{
int i;
long symlen, seglen, segsize;
@ -430,7 +440,8 @@ static void as86_write(void) {
fputc (0, as86fp); /* termination */
}
static void as86_set_rsize (int size) {
static void as86_set_rsize (int size)
{
if (as86_reloc_size != size) {
switch (as86_reloc_size = size) {
case 1: fputc (0x01, as86fp); break;
@ -441,7 +452,8 @@ static void as86_set_rsize (int size) {
}
}
static void as86_write_section (struct Section *sect, int index) {
static void as86_write_section (struct Section *sect, int index)
{
struct Piece *p;
unsigned long s;
long length;
@ -512,20 +524,24 @@ static void as86_write_section (struct Section *sect, int index) {
}
static void as86_sect_write (struct Section *sect,
unsigned char *data, unsigned long len) {
unsigned char *data, unsigned long len)
{
saa_wbytes (sect->data, data, len);
sect->datalen += len;
}
static long as86_segbase (long segment) {
static long as86_segbase (long segment)
{
return segment;
}
static int as86_directive (char *directive, char *value, int pass) {
static int as86_directive (char *directive, char *value, int pass)
{
return 0;
}
static void as86_filename (char *inname, char *outname, efunc error) {
static void as86_filename (char *inname, char *outname, efunc error)
{
char *p;
if ( (p = strrchr (inname, '.')) != NULL) {
@ -539,16 +555,30 @@ static void as86_filename (char *inname, char *outname, efunc error) {
static char *as86_stdmac[] = {
"%define __SECT__ [section .text]",
"%macro __NASM_CDecl__ 1",
"%endmacro",
NULL
};
static int as86_set_info(enum geninfo type, char **val)
{
return 0;
}
void as86_linenumber (char *name, long segment, long offset, int is_main,
int lineno)
{
}
struct ofmt of_as86 = {
"Linux as86 (bin86 version 0.3) object files",
"as86",
NULL,
null_debug_arr,
&null_debug_form,
as86_stdmac,
as86_init,
as86_set_info,
as86_out,
as86_deflabel,
as86_deflabel,
as86_section_names,
as86_segbase,
as86_directive,

View File

@ -42,7 +42,8 @@ static long data_align, bss_align;
static long start_point;
static void add_reloc (struct Section *s, long bytes, long secref,
long secrel) {
long secrel)
{
struct Reloc *r;
r = *reloctail = nasm_malloc(sizeof(struct Reloc));
@ -55,9 +56,12 @@ static void add_reloc (struct Section *s, long bytes, long secref,
r->target = s;
}
static void bin_init (FILE *afp, efunc errfunc, ldfunc ldef, evalfunc eval) {
static void bin_init (FILE *afp, efunc errfunc, ldfunc ldef, evalfunc eval)
{
fp = afp;
(void) eval; /* Don't warn that this parameter is unused */
error = errfunc;
(void) ldef; /* placate optimisers */
@ -74,10 +78,13 @@ static void bin_init (FILE *afp, efunc errfunc, ldfunc ldef, evalfunc eval) {
data_align = bss_align = 4;
}
static void bin_cleanup (void) {
static void bin_cleanup (int debuginfo)
{
struct Reloc *r;
long datapos, datagap, bsspos;
(void) debuginfo;
datapos = start_point + textsect.length;
datapos = (datapos + data_align-1) & ~(data_align-1);
datagap = datapos - (start_point + textsect.length);
@ -87,7 +94,8 @@ static void bin_cleanup (void) {
saa_rewind (textsect.contents);
saa_rewind (datasect.contents);
for (r = relocs; r; r = r->next) {
for (r = relocs; r; r = r->next)
{
unsigned char *p, *q, mydata[4];
long l;
@ -141,7 +149,8 @@ static void bin_cleanup (void) {
}
static void bin_out (long segto, void *data, unsigned long type,
long segment, long wrt) {
long segment, long wrt)
{
unsigned char *p, mydata[4];
struct Section *s;
long realbytes;
@ -221,8 +230,10 @@ static void bin_out (long segto, void *data, unsigned long type,
s->length += type;
} else
bsslen += type;
} else if ((type & OUT_TYPMASK) == OUT_REL2ADR ||
(type & OUT_TYPMASK) == OUT_REL4ADR) {
}
else if ((type & OUT_TYPMASK) == OUT_REL2ADR ||
(type & OUT_TYPMASK) == OUT_REL4ADR)
{
realbytes = ((type & OUT_TYPMASK) == OUT_REL4ADR ? 4 : 2);
if (segment != NO_SEG &&
segment != textsect.index &&
@ -251,7 +262,11 @@ static void bin_out (long segto, void *data, unsigned long type,
}
static void bin_deflabel (char *name, long segment, long offset,
int is_global, char *special) {
int is_global, char *special)
{
(void) segment; /* Don't warn that this parameter is unused */
(void) offset; /* Don't warn that this parameter is unused */
if (special)
error (ERR_NONFATAL, "binary format does not support any"
@ -268,11 +283,14 @@ static void bin_deflabel (char *name, long segment, long offset,
}
}
static long bin_secname (char *name, int pass, int *bits) {
static long bin_secname (char *name, int pass, int *bits)
{
int sec_index;
long *sec_align;
char *p;
(void) pass; /* Don't warn that this parameter is unused */
/*
* Default is 16 bits.
*/
@ -318,13 +336,17 @@ static long bin_secname (char *name, int pass, int *bits) {
return sec_index;
}
static long bin_segbase (long segment) {
static long bin_segbase (long segment)
{
return segment;
}
static int bin_directive (char *directive, char *value, int pass) {
static int bin_directive (char *directive, char *value, int pass)
{
int rn_error;
(void) pass; /* Don't warn that this parameter is unused */
if (!strcmp(directive, "org")) {
start_point = readnum (value, &rn_error);
if (rn_error)
@ -334,7 +356,8 @@ static int bin_directive (char *directive, char *value, int pass) {
return 0;
}
static void bin_filename (char *inname, char *outname, efunc error) {
static void bin_filename (char *inname, char *outname, efunc error)
{
standard_extension (inname, outname, "", error);
}
@ -343,14 +366,24 @@ static char *bin_stdmac[] = {
"%imacro org 1+.nolist",
"[org %1]",
"%endmacro",
"%macro __NASM_CDecl__ 1",
"%endmacro",
NULL
};
static int bin_set_info(enum geninfo type, char **val)
{
return 0;
}
struct ofmt of_bin = {
"flat-form binary files (e.g. DOS .COM, .SYS)",
"bin",
NULL,
null_debug_arr,
&null_debug_form,
bin_stdmac,
bin_init,
bin_set_info,
bin_out,
bin_deflabel,
bin_secname,

View File

@ -127,21 +127,24 @@ static void coff_section_header (char *, long, long, long, long, int, long);
static void coff_write_relocs (struct Section *);
static void coff_write_symbols (void);
static void coff_win32_init(FILE *fp, efunc errfunc,
ldfunc ldef, evalfunc eval) {
static void coff_win32_init(FILE *fp, efunc errfunc,
ldfunc ldef, evalfunc eval)
{
win32 = TRUE;
(void) ldef; /* placate optimisers */
coff_gen_init(fp, errfunc);
}
static void coff_std_init(FILE *fp, efunc errfunc,
ldfunc ldef, evalfunc eval) {
static void coff_std_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval)
{
win32 = FALSE;
(void) ldef; /* placate optimisers */
coff_gen_init(fp, errfunc);
}
static void coff_gen_init(FILE *fp, efunc errfunc) {
static void coff_gen_init(FILE *fp, efunc errfunc)
{
coffp = fp;
error = errfunc;
sects = NULL;
@ -155,10 +158,13 @@ static void coff_gen_init(FILE *fp, efunc errfunc) {
def_seg = seg_alloc();
}
static void coff_cleanup(void) {
static void coff_cleanup(int debuginfo)
{
struct Reloc *r;
int i;
(void) debuginfo;
coff_write();
fclose (coffp);
for (i=0; i<nsects; i++) {
@ -169,6 +175,7 @@ static void coff_cleanup(void) {
sects[i]->head = sects[i]->head->next;
nasm_free (r);
}
nasm_free (sects[i]);
}
nasm_free (sects);
saa_free (syms);
@ -177,7 +184,8 @@ static void coff_cleanup(void) {
saa_free (strs);
}
static int coff_make_section (char *name, unsigned long flags) {
static int coff_make_section (char *name, unsigned long flags)
{
struct Section *s;
s = nasm_malloc (sizeof(*s));
@ -205,7 +213,8 @@ static int coff_make_section (char *name, unsigned long flags) {
return nsects-1;
}
static long coff_section_names (char *name, int pass, int *bits) {
static long coff_section_names (char *name, int pass, int *bits)
{
char *p;
unsigned long flags, align_and = ~0L, align_or = 0L;
int i;
@ -225,7 +234,7 @@ static long coff_section_names (char *name, int pass, int *bits) {
if (strlen(name) > 8) {
error (ERR_WARNING, "COFF section names limited to 8 characters:"
" truncating");
p[8] = '\0';
name[8] = '\0';
}
flags = 0;
@ -306,7 +315,8 @@ static long coff_section_names (char *name, int pass, int *bits) {
}
static void coff_deflabel (char *name, long segment, long offset,
int is_global, char *special) {
int is_global, char *special)
{
int pos = strslen+4;
struct Symbol *sym;
@ -363,7 +373,8 @@ static void coff_deflabel (char *name, long segment, long offset,
}
static long coff_add_reloc (struct Section *sect, long segment,
int relative) {
int relative)
{
struct Reloc *r;
r = *sect->tail = nasm_malloc(sizeof(struct Reloc));
@ -399,7 +410,8 @@ static long coff_add_reloc (struct Section *sect, long segment,
}
static void coff_out (long segto, void *data, unsigned long type,
long segment, long wrt) {
long segment, long wrt)
{
struct Section *s;
long realbytes = type & OUT_SIZMASK;
unsigned char mydata[4], *p;
@ -506,16 +518,19 @@ static void coff_out (long segto, void *data, unsigned long type,
}
static void coff_sect_write (struct Section *sect,
unsigned char *data, unsigned long len) {
unsigned char *data, unsigned long len)
{
saa_wbytes (sect->data, data, len);
sect->len += len;
}
static int coff_directives (char *directive, char *value, int pass) {
static int coff_directives (char *directive, char *value, int pass)
{
return 0;
}
static void coff_write (void) {
static void coff_write (void)
{
long pos, sympos, vsize;
int i;
@ -579,7 +594,8 @@ static void coff_write (void) {
static void coff_section_header (char *name, long vsize,
long datalen, long datapos,
long relpos, int nrelocs, long flags) {
long relpos, int nrelocs, long flags)
{
char padname[8];
memset (padname, 0, 8);
@ -596,7 +612,8 @@ static void coff_section_header (char *name, long vsize,
fwritelong (flags, coffp);
}
static void coff_write_relocs (struct Section *s) {
static void coff_write_relocs (struct Section *s)
{
struct Reloc *r;
for (r = s->head; r; r = r->next) {
@ -615,7 +632,8 @@ static void coff_write_relocs (struct Section *s) {
}
static void coff_symbol (char *name, long strpos, long value,
int section, int type, int aux) {
int section, int type, int aux)
{
char padname[8];
if (name) {
@ -633,7 +651,8 @@ static void coff_symbol (char *name, long strpos, long value,
fputc (aux, coffp);
}
static void coff_write_symbols (void) {
static void coff_write_symbols (void)
{
char filename[18];
int i;
@ -674,34 +693,47 @@ static void coff_write_symbols (void) {
}
}
static long coff_segbase (long segment) {
static long coff_segbase (long segment)
{
return segment;
}
static void coff_std_filename (char *inname, char *outname, efunc error) {
static void coff_std_filename (char *inname, char *outname, efunc error)
{
strcpy(coff_infile, inname);
standard_extension (inname, outname, ".o", error);
}
static void coff_win32_filename (char *inname, char *outname, efunc error) {
static void coff_win32_filename (char *inname, char *outname, efunc error)
{
strcpy(coff_infile, inname);
standard_extension (inname, outname, ".obj", error);
}
#endif /* defined(OF_COFF) || defined(OF_WIN32) */
static char *coff_stdmac[] = {
"%define __SECT__ [section .text]",
"%macro __NASM_CDecl__ 1",
"%endmacro",
NULL
};
static int coff_set_info(enum geninfo type, char **val)
{
return 0;
}
#endif /* defined(OF_COFF) || defined(OF_WIN32) */
#ifdef OF_COFF
struct ofmt of_coff = {
"COFF (i386) object files (e.g. DJGPP for DOS)",
"coff",
NULL,
null_debug_arr,
&null_debug_form,
coff_stdmac,
coff_std_init,
coff_set_info,
coff_out,
coff_deflabel,
coff_section_names,
@ -718,8 +750,12 @@ struct ofmt of_coff = {
struct ofmt of_win32 = {
"Microsoft Win32 (i386) object files",
"win32",
NULL,
null_debug_arr,
&null_debug_form,
coff_stdmac,
coff_win32_init,
coff_set_info,
coff_out,
coff_deflabel,
coff_section_names,

View File

@ -27,17 +27,24 @@ struct Section {
FILE *dbgf;
efunc dbgef;
struct ofmt of_dbg;
static void dbg_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval)
{
(void) eval;
dbgf = fp;
dbgef = errfunc;
dbgsect = NULL;
(void) ldef;
fprintf(fp,"NASM Output format debug dump\n");
of_dbg.current_dfmt->init(&of_dbg,0,fp,errfunc);
}
static void dbg_cleanup(void)
static void dbg_cleanup(int debuginfo)
{
(void) debuginfo;
of_dbg.current_dfmt->cleanup();
while (dbgsect) {
struct Section *tmp = dbgsect;
dbgsect = dbgsect->next;
@ -84,7 +91,8 @@ static long dbg_section_names (char *name, int pass, int *bits)
}
static void dbg_deflabel (char *name, long segment, long offset,
int is_global, char *special) {
int is_global, char *special)
{
fprintf(dbgf,"deflabel %s := %08lx:%08lx %s (%d)%s%s\n",
name, segment, offset,
is_global == 2 ? "common" : is_global ? "global" : "local",
@ -93,7 +101,8 @@ static void dbg_deflabel (char *name, long segment, long offset,
}
static void dbg_out (long segto, void *data, unsigned long type,
long segment, long wrt) {
long segment, long wrt)
{
long realbytes = type & OUT_SIZMASK;
long ldata;
int id;
@ -135,25 +144,99 @@ static void dbg_out (long segto, void *data, unsigned long type,
}
}
static long dbg_segbase(long segment) {
static long dbg_segbase(long segment)
{
return segment;
}
static int dbg_directive (char *directive, char *value, int pass) {
static int dbg_directive (char *directive, char *value, int pass)
{
fprintf(dbgf, "directive [%s] value [%s] (pass %d)\n",
directive, value, pass);
return 1;
}
static void dbg_filename (char *inname, char *outname, efunc error) {
static void dbg_filename (char *inname, char *outname, efunc error)
{
standard_extension (inname, outname, ".dbg", error);
}
static int dbg_set_info(enum geninfo type, char **val)
{
(void) type;
(void) val;
return 0;
}
char *types[] = {
"unknown", "label", "byte","word","dword","float","qword","tbyte"
};
void dbgdbg_init(struct ofmt * of, void * id, FILE * fp, efunc error)
{
(void) of;
(void) id;
(void) fp;
(void) error;
fprintf(fp," With debug info\n");
}
static void dbgdbg_cleanup(void)
{
}
static void dbgdbg_linnum (const char *lnfname, long lineno, long segto)
{
fprintf(dbgf,"dbglinenum %s(%ld) := %08lx\n",
lnfname,lineno,segto);
}
static void dbgdbg_deflabel (char *name, long segment,
long offset, int is_global, char *special)
{
fprintf(dbgf,"dbglabel %s := %08lx:%08lx %s (%d)%s%s\n",
name,
segment, offset,
is_global == 2 ? "common" : is_global ? "global" : "local",
is_global,
special ? ": " : "", special);
}
static void dbgdbg_define(const char *type, const char *params)
{
fprintf(dbgf,"dbgdirective [%s] value [%s]\n",type, params);
}
static void dbgdbg_output (int output_type, void *param)
{
(void) output_type;
(void) param;
}
static void dbgdbg_typevalue(long type)
{
fprintf(dbgf,"new type: %s(%lX)\n",
types[TYM_TYPE(type) >> 3], TYM_ELEMENTS(type) );
}
static struct dfmt debug_debug_form = {
"Trace of all info passed to debug stage",
"debug",
dbgdbg_init,
dbgdbg_linnum,
dbgdbg_deflabel,
dbgdbg_define,
dbgdbg_typevalue,
dbgdbg_output,
dbgdbg_cleanup,
};
static struct dfmt *debug_debug_arr[3] = {
&debug_debug_form,
&null_debug_form,
NULL
};
struct ofmt of_dbg = {
"Trace of all info passed to output stage",
"dbg",
NULL,
debug_debug_arr,
&null_debug_form,
NULL,
dbg_init,
dbg_set_info,
dbg_out,
dbg_deflabel,
dbg_section_names,

View File

@ -117,7 +117,7 @@ static struct ELF_SECTDATA {
void *data;
long len;
int is_saa;
} elf_sects[ELF_MAX_SECTIONS];
} *elf_sects;
static int elf_nsect;
static long elf_foffs;
@ -139,7 +139,8 @@ static long elf_gotpc_sect, elf_gotoff_sect;
static long elf_got_sect, elf_plt_sect;
static long elf_sym_sect;
static void elf_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) {
static void elf_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval)
{
elffp = fp;
error = errfunc;
evaluate = eval;
@ -173,10 +174,13 @@ static void elf_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) {
def_seg = seg_alloc();
}
static void elf_cleanup(void) {
static void elf_cleanup(int debuginfo)
{
struct Reloc *r;
int i;
(void) debuginfo;
elf_write();
fclose (elffp);
for (i=0; i<nsects; i++) {
@ -196,7 +200,8 @@ static void elf_cleanup(void) {
saa_free (strs);
}
static void add_sectname (char *firsthalf, char *secondhalf) {
static void add_sectname (char *firsthalf, char *secondhalf)
{
int len = strlen(firsthalf)+strlen(secondhalf);
while (shstrtablen + len + 1 > shstrtabsize)
shstrtab = nasm_realloc (shstrtab, (shstrtabsize += SHSTR_DELTA));
@ -205,7 +210,8 @@ static void add_sectname (char *firsthalf, char *secondhalf) {
shstrtablen += len+1;
}
static int elf_make_section (char *name, int type, int flags, int align) {
static int elf_make_section (char *name, int type, int flags, int align)
{
struct Section *s;
s = nasm_malloc (sizeof(*s));
@ -235,18 +241,18 @@ static int elf_make_section (char *name, int type, int flags, int align) {
return nsects-1;
}
static long elf_section_names (char *name, int pass, int *bits) {
static long elf_section_names (char *name, int pass, int *bits)
{
char *p;
int flags_and, flags_or, type, align, i;
/*
* Default is 32 bits.
*/
if (!name)
if (!name) {
*bits = 32;
if (!name)
return def_seg;
}
p = name;
while (*p && !isspace(*p)) p++;
@ -334,7 +340,8 @@ static long elf_section_names (char *name, int pass, int *bits) {
}
static void elf_deflabel (char *name, long segment, long offset,
int is_global, char *special) {
int is_global, char *special)
{
int pos = strslen;
struct Symbol *sym;
int special_used = FALSE;
@ -439,9 +446,29 @@ static void elf_deflabel (char *name, long segment, long offset,
sym->value = (sym->section == SHN_UNDEF ? 0 : offset);
if (sym->type == SYM_GLOBAL) {
/*
* There's a problem here that needs fixing.
* If sym->section == SHN_ABS, then the first line of the
* else section causes a core dump, because its a reference
* beyond the end of the section array.
* This behaviour is exhibited by this code:
* GLOBAL crash_nasm
* crash_nasm equ 0
*
* I'm not sure how to procede, because I haven't got the
* first clue about how ELF works, so I don't know what to
* do with it. Furthermore, I'm not sure what the rest of this
* section of code does. Help?
*
* For now, I'll see if doing absolutely nothing with it will
* work...
*/
if (sym->section == SHN_UNDEF || sym->section == SHN_COMMON)
{
bsym = raa_write (bsym, segment, nglobs);
else {
}
else if (sym->section != SHN_ABS)
{
/*
* This is a global symbol; so we must add it to the linked
* list of global symbols in its section. We'll push it on
@ -505,7 +532,8 @@ static void elf_deflabel (char *name, long segment, long offset,
}
static void elf_add_reloc (struct Section *sect, long segment,
int type) {
int type)
{
struct Reloc *r;
r = *sect->tail = nasm_malloc(sizeof(struct Reloc));
@ -553,7 +581,8 @@ static void elf_add_reloc (struct Section *sect, long segment,
*/
static long elf_add_gsym_reloc (struct Section *sect,
long segment, long offset,
int type, int exact) {
int type, int exact)
{
struct Reloc *r;
struct Section *s;
struct Symbol *sym, *sm;
@ -617,7 +646,8 @@ static long elf_add_gsym_reloc (struct Section *sect,
}
static void elf_out (long segto, void *data, unsigned long type,
long segment, long wrt) {
long segment, long wrt)
{
struct Section *s;
long realbytes = type & OUT_SIZMASK;
long addr;
@ -744,7 +774,8 @@ static void elf_out (long segto, void *data, unsigned long type,
}
}
static void elf_write(void) {
static void elf_write(void)
{
int nsections, align;
char *p;
int commlen;
@ -819,6 +850,7 @@ static void elf_write(void) {
align = ((elf_foffs+SEG_ALIGN_1) & ~SEG_ALIGN_1) - elf_foffs;
elf_foffs += align;
elf_nsect = 0;
elf_sects = nasm_malloc(sizeof(*elf_sects) * (2 * nsects + 10));
elf_section_header (0, 0, 0, NULL, FALSE, 0L, 0, 0, 0, 0); /* SHN_UNDEF */
p = shstrtab+1;
@ -853,10 +885,12 @@ static void elf_write(void) {
*/
elf_write_sections();
nasm_free (elf_sects);
saa_free (symtab);
}
static struct SAA *elf_build_symtab (long *len, long *local) {
static struct SAA *elf_build_symtab (long *len, long *local)
{
struct SAA *s = saa_init(1L);
struct Symbol *sym;
unsigned char entry[16], *p;
@ -968,7 +1002,8 @@ static struct SAA *elf_build_reltab (long *len, struct Reloc *r) {
static void elf_section_header (int name, int type, int flags,
void *data, int is_saa, long datalen,
int link, int info, int align, int eltsize) {
int link, int info, int align, int eltsize)
{
elf_sects[elf_nsect].data = data;
elf_sects[elf_nsect].len = datalen;
elf_sects[elf_nsect].is_saa = is_saa;
@ -988,7 +1023,8 @@ static void elf_section_header (int name, int type, int flags,
fwritelong ((long)eltsize, elffp);
}
static void elf_write_sections (void) {
static void elf_write_sections (void)
{
int i;
for (i = 0; i < elf_nsect; i++)
if (elf_sects[i].data) {
@ -1004,34 +1040,49 @@ static void elf_write_sections (void) {
}
static void elf_sect_write (struct Section *sect,
unsigned char *data, unsigned long len) {
unsigned char *data, unsigned long len)
{
saa_wbytes (sect->data, data, len);
sect->len += len;
}
static long elf_segbase (long segment) {
static long elf_segbase (long segment)
{
return segment;
}
static int elf_directive (char *directive, char *value, int pass) {
static int elf_directive (char *directive, char *value, int pass)
{
return 0;
}
static void elf_filename (char *inname, char *outname, efunc error) {
static void elf_filename (char *inname, char *outname, efunc error)
{
strcpy(elf_module, inname);
standard_extension (inname, outname, ".o", error);
}
static char *elf_stdmac[] = {
"%define __SECT__ [section .text]",
"%macro __NASM_CDecl__ 1",
"%define $_%1 $%1",
"%endmacro",
NULL
};
static int elf_set_info(enum geninfo type, char **val)
{
return 0;
}
struct ofmt of_elf = {
"ELF32 (i386) object files (e.g. Linux)",
"elf",
NULL,
null_debug_arr,
&null_debug_form,
elf_stdmac,
elf_init,
elf_set_info,
elf_out,
elf_deflabel,
elf_section_names,

View File

@ -11,9 +11,10 @@
#include <stdio.h>
#include <string.h>
#define BUILD_DRIVERS_ARRAY
#include "outform.h"
static struct ofmt *drivers[MAX_OUTPUT_FORMATS];
static int ndrivers = 0;
struct ofmt *ofmt_find(char *name) /* find driver */
@ -26,17 +27,45 @@ struct ofmt *ofmt_find(char *name) /* find driver */
return NULL;
}
struct dfmt *dfmt_find(struct ofmt *ofmt, char *name) /* find driver */
{
struct dfmt **dfmt = ofmt->debug_formats;
while (*dfmt) {
if (!strcmp(name, (*dfmt)->shortname))
return (*dfmt);
dfmt++;
}
return NULL;
}
void ofmt_list(struct ofmt *deffmt, FILE *fp)
{
int i;
for (i=0; i<ndrivers; i++)
fprintf(fp, " %c %-7s%s\n",
fprintf(fp, " %c %-10s%s\n",
drivers[i] == deffmt ? '*' : ' ',
drivers[i]->shortname,
drivers[i]->fullname);
}
void ofmt_register (struct ofmt *info) {
drivers[ndrivers++] = info;
void dfmt_list(struct ofmt *ofmt, FILE *fp)
{
struct dfmt ** drivers = ofmt->debug_formats;
while (*drivers) {
fprintf(fp, " %c %-10s%s\n",
drivers[0] == ofmt->current_dfmt ? '*' : ' ',
drivers[0]->shortname,
drivers[0]->fullname);
drivers++;
}
}
struct ofmt *ofmt_register (efunc error) {
for (ndrivers=0; drivers[ndrivers] != NULL; ndrivers++);
if (ndrivers==0)
{
error(ERR_PANIC | ERR_NOFILE,
"No output drivers given at compile time");
}
return (&OF_DEFAULT);
}

View File

@ -20,6 +20,9 @@
* OF_UNIX -- ensure that 'aout', 'aoutb', 'coff', 'elf' are in.
* OF_OTHERS -- ensure that 'bin', 'as86' & 'rdf' are in.
* OF_ALL -- ensure that all formats are included.
* note that this doesn't include 'dbg', which is
* only really useful if you're doing development
* work on NASM. Define OF_DBG if you want this.
*
* OF_DEFAULT=of_name -- ensure that 'name' is the default format.
*
@ -35,12 +38,6 @@
#include "nasm.h"
#define MAX_OUTPUT_FORMATS 16
struct ofmt *ofmt_find(char *);
void ofmt_list(struct ofmt *, FILE *);
void ofmt_register (struct ofmt *);
/* -------------- USER MODIFIABLE PART ---------------- */
/*
@ -60,7 +57,7 @@ void ofmt_register (struct ofmt *);
/* ====configurable info begins here==== */
/* formats configurable:
* bin,obj,elf,aout,aoutb,coff,win32,as86,rdf */
* bin,obj,elf,aout,aoutb,coff,win32,as86,rdf,rdf2 */
/* process options... */
@ -95,8 +92,8 @@ void ofmt_register (struct ofmt *);
#ifndef OF_AS86
#define OF_AS86
#endif
#ifndef OF_RDF
#define OF_RDF
#ifndef OF_RDF2
#define OF_RDF2
#endif
#endif /* OF_ALL */
@ -138,6 +135,9 @@ void ofmt_register (struct ofmt *);
#ifndef OF_RDF
#define OF_RDF
#endif
#ifndef OF_RDF2
#define OF_RDF2
#endif
#endif
/* finally... override any format specifically specifed to be off */
@ -168,9 +168,75 @@ void ofmt_register (struct ofmt *);
#ifdef OF_NO_RDF
#undef OF_RDF
#endif
#ifdef OF_NO_RDF2
#undef OF_RDF
#endif
#ifndef OF_DEFAULT
#define OF_DEFAULT of_bin
#endif
#ifdef BUILD_DRIVERS_ARRAY /* only if included from outform.c */
/* pull in the externs for the different formats, then make the *drivers
* array based on the above defines */
extern struct ofmt of_bin;
extern struct ofmt of_aout;
extern struct ofmt of_aoutb;
extern struct ofmt of_coff;
extern struct ofmt of_elf;
extern struct ofmt of_as86;
extern struct ofmt of_obj;
extern struct ofmt of_win32;
extern struct ofmt of_rdf;
extern struct ofmt of_rdf2;
extern struct ofmt of_dbg;
struct ofmt *drivers[]={
#ifdef OF_BIN
&of_bin,
#endif
#ifdef OF_AOUT
&of_aout,
#endif
#ifdef OF_AOUTB
&of_aoutb,
#endif
#ifdef OF_COFF
&of_coff,
#endif
#ifdef OF_ELF
&of_elf,
#endif
#ifdef OF_AS86
&of_as86,
#endif
#ifdef OF_OBJ
&of_obj,
#endif
#ifdef OF_WIN32
&of_win32,
#endif
#ifdef OF_RDF
&of_rdf,
#endif
#ifdef OF_RDF2
&of_rdf2,
#endif
#ifdef OF_DBG
&of_dbg,
#endif
NULL
};
#endif /* BUILD_DRIVERS_ARRAY */
struct ofmt *ofmt_find(char *);
struct dfmt *dfmt_find(struct ofmt *, char *);
void ofmt_list(struct ofmt *, FILE *);
void dfmt_list(struct ofmt *ofmt, FILE *fp);
struct ofmt *ofmt_register (efunc error);
#endif /* NASM_OUTFORM_H */

223
outforms.h Normal file
View File

@ -0,0 +1,223 @@
/* outform.h header file for binding output format drivers to the
* remainder of the code in the Netwide Assembler
*
* The Netwide Assembler is copyright (C) 1996 Simon Tatham and
* Julian Hall. All rights reserved. The software is
* redistributable under the licence given in the file "Licence"
* distributed in the NASM archive.
*/
/*
* This header file allows configuration of which output formats
* get compiled into the NASM binary. You can configure by defining
* various preprocessor symbols beginning with "OF_", either on the
* compiler command line or at the top of this file.
*
* OF_ONLY -- only include specified object formats
* OF_name -- ensure that output format 'name' is included
* OF_NO_name -- remove output format 'name'
* OF_DOS -- ensure that 'obj', 'bin' & 'win32' are included.
* OF_UNIX -- ensure that 'aout', 'aoutb', 'coff', 'elf' are in.
* OF_OTHERS -- ensure that 'bin', 'as86' & 'rdf' are in.
* OF_ALL -- ensure that all formats are included.
*
* OF_DEFAULT=of_name -- ensure that 'name' is the default format.
*
* eg: -DOF_UNIX -DOF_ELF -DOF_DEFAULT=of_elf would be a suitable config
* for an average linux system.
*
* Default config = -DOF_ALL -DOF_DEFAULT=of_bin
*
* You probably only want to set these options while compiling 'nasm.c'. */
#ifndef NASM_OUTFORMS_H
#define NASM_OUTFORMS_H
#include "nasm.h"
/* -------------- USER MODIFIABLE PART ---------------- */
/*
* Insert #defines here in accordance with the configuration
* instructions above.
*
* E.g.
*
* #define OF_ONLY
* #define OF_OBJ
* #define OF_BIN
*
* for a 16-bit DOS assembler with no extraneous formats.
*/
/* ------------ END USER MODIFIABLE PART -------------- */
/* ====configurable info begins here==== */
/* formats configurable:
* bin,obj,elf,aout,aoutb,coff,win32,as86,rdf */
/* process options... */
#ifndef OF_ONLY
#ifndef OF_ALL
#define OF_ALL /* default is to have all formats */
#endif
#endif
#ifdef OF_ALL /* set all formats on... */
#ifndef OF_BIN
#define OF_BIN
#endif
#ifndef OF_OBJ
#define OF_OBJ
#endif
#ifndef OF_ELF
#define OF_ELF
#endif
#ifndef OF_COFF
#define OF_COFF
#endif
#ifndef OF_AOUT
#define OF_AOUT
#endif
#ifndef OF_AOUTB
#define OF_AOUTB
#endif
#ifndef OF_WIN32
#define OF_WIN32
#endif
#ifndef OF_AS86
#define OF_AS86
#endif
#ifndef OF_RDF
#define OF_RDF
#endif
#endif /* OF_ALL */
/* turn on groups of formats specified.... */
#ifdef OF_DOS
#ifndef OF_OBJ
#define OF_OBJ
#endif
#ifndef OF_BIN
#define OF_BIN
#endif
#ifndef OF_WIN32
#define OF_WIN32
#endif
#endif
#ifdef OF_UNIX
#ifndef OF_AOUT
#define OF_AOUT
#endif
#ifndef OF_AOUTB
#define OF_AOUTB
#endif
#ifndef OF_COFF
#define OF_COFF
#endif
#ifndef OF_ELF
#define OF_ELF
#endif
#endif
#ifdef OF_OTHERS
#ifndef OF_BIN
#define OF_BIN
#endif
#ifndef OF_AS86
#define OF_AS86
#endif
#ifndef OF_RDF
#define OF_RDF
#endif
#endif
/* finally... override any format specifically specifed to be off */
#ifdef OF_NO_BIN
#undef OF_BIN
#endif
#ifdef OF_NO_OBJ
#undef OF_OBJ
#endif
#ifdef OF_NO_ELF
#undef OF_ELF
#endif
#ifdef OF_NO_AOUT
#undef OF_AOUT
#endif
#ifdef OF_NO_AOUTB
#undef OF_AOUTB
#endif
#ifdef OF_NO_COFF
#undef OF_COFF
#endif
#ifdef OF_NO_WIN32
#undef OF_WIN32
#endif
#ifdef OF_NO_AS86
#undef OF_AS86
#endif
#ifdef OF_NO_RDF
#undef OF_RDF
#endif
#ifndef OF_DEFAULT
#define OF_DEFAULT of_bin
#endif
#ifdef BUILD_DRIVERS_ARRAY /* only if included from outform.c */
/* pull in the externs for the different formats, then make the *drivers
* array based on the above defines */
extern struct ofmt of_bin;
extern struct ofmt of_aout;
extern struct ofmt of_aoutb;
extern struct ofmt of_coff;
extern struct ofmt of_elf;
extern struct ofmt of_as86;
extern struct ofmt of_obj;
extern struct ofmt of_win32;
extern struct ofmt of_rdf;
extern struct ofmt of_dbg;
struct ofmt *drivers[]={
#ifdef OF_BIN
&of_bin,
#endif
#ifdef OF_AOUT
&of_aout,
#endif
#ifdef OF_AOUTB
&of_aoutb,
#endif
#ifdef OF_COFF
&of_coff,
#endif
#ifdef OF_ELF
&of_elf,
#endif
#ifdef OF_AS86
&of_as86,
#endif
#ifdef OF_OBJ
&of_obj,
#endif
#ifdef OF_WIN32
&of_win32,
#endif
#ifdef OF_RDF
&of_rdf,
#endif
#ifdef OF_DBG
&of_dbg,
#endif
NULL
};
#endif /* BUILD_DRIVERS_ARRAY */
#endif /* NASM_OUTFORMS_H */

1614
outobj.c

File diff suppressed because it is too large Load Diff

View File

@ -316,6 +316,12 @@ static void rdf_out (long segto, void *data, unsigned long type,
struct RelocRec rr;
unsigned char databuf[4],*pd;
if (segto == NO_SEG) {
if ((type & OUT_TYPMASK) != OUT_RESERVE)
error (ERR_NONFATAL, "attempt to assemble code in ABSOLUTE space");
return;
}
segto >>= 1; /* convert NASM segment no to RDF number */
if (segto != 0 && segto != 1 && segto != 2) {
@ -426,11 +432,13 @@ static void rdf_out (long segto, void *data, unsigned long type,
}
}
static void rdf_cleanup (void) {
static void rdf_cleanup (int debuginfo) {
long l;
unsigned char b[4],*d;
struct BSSRec bs;
(void) debuginfo;
/* should write imported & exported symbol declarations to header here */
@ -496,14 +504,29 @@ static char *rdf_stdmac[] = {
"%imacro library 1+.nolist",
"[library %1]",
"%endmacro",
"%macro __NASM_CDecl__ 1",
"%endmacro",
NULL
};
static int rdf_set_info(enum geninfo type, char **val)
{
return 0;
}
struct ofmt of_rdf = {
"Relocatable Dynamic Object File Format v1.1",
#ifdef OF_RDF2
"oldrdf",
#else
"rdf",
#endif
NULL,
null_debug_arr,
&null_debug_form,
rdf_stdmac,
rdf_init,
rdf_set_info,
rdf_out,
rdf_deflabel,
rdf_section_names,

690
outrdf2.c Normal file
View File

@ -0,0 +1,690 @@
/* outrdf2.c output routines for the Netwide Assembler to produce
* RDOFF version 2 format object files (which are intended
* mainly for use in proprietary projects, as the code to
* load and execute them is very simple). They will also be
* used for device drivers and possibly some executable files
* in the MOSCOW operating system. See Rdoff.txt for
* details.
*
* The Netwide Assembler is copyright (C) 1996-1998 Simon Tatham and
* Julian Hall. All rights reserved. The software is
* redistributable under the licence given in the file "Licence"
* distributed in the NASM archive.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include "nasm.h"
#include "nasmlib.h"
#include "outform.h"
/* VERBOSE_WARNINGS: define this to add some extra warnings... */
#define VERBOSE_WARNINGS
#ifdef OF_RDF2
#define RDF_MAXSEGS 64 /* maximum number of segments - user configurable */
typedef unsigned short int16;
typedef unsigned char byte;
static const char *RDOFF2Id = "RDOFF2"; /* written to start of RDOFF files */
/* the records that can be found in the RDOFF header */
/* Note that whenever a segment is referred to in the RDOFF file, its number
* is always half of the segment number that NASM uses to refer to it; this
* is because NASM only allocates even numbered segments, so as to not
* waste any of the 16 bits of segment number written to the file - this
* allows up to 65533 external labels to be defined; otherwise it would be
* 32764. */
struct RelocRec {
byte type; /* must be 1, or 6 for segment base ref */
byte reclen; /* set to 8 */
byte segment; /* only 0 for code, or 1 for data supported,
* but add 64 for relative refs (ie do not require
* reloc @ loadtime, only linkage) */
long offset; /* from start of segment in which reference is loc'd */
byte length; /* 1 2 or 4 bytes */
int16 refseg; /* segment to which reference refers to */
};
struct ImportRec {
byte type; /* must be 2, or 7 for FAR import */
byte reclen; /* equals 3+label length */
int16 segment; /* segment number allocated to the label for reloc
* records - label is assumed to be at offset zero
* in this segment, so linker must fix up with offset
* of segment and of offset within segment */
char label[33]; /* zero terminated... should be written to file until
* the zero, but not after it - max len = 32 chars */
};
struct ExportRec {
byte type; /* must be 3 */
byte reclen; /* equals 6+label length */
byte segment; /* segment referred to (0/1) */
long offset; /* offset within segment */
char label[33]; /* zero terminated as above. max len = 32 chars */
};
struct DLLRec {
byte type; /* must be 4 */
byte reclen; /* equals 1+library name */
char libname[128]; /* name of library to link with at load time */
};
struct BSSRec {
byte type; /* must be 5 */
byte reclen; /* equeals 4 */
long amount; /* number of bytes BSS to reserve */
};
#define COUNT_SEGTYPES 9
static char * segmenttypes[COUNT_SEGTYPES] = {
"null", "text", "code", "data", "comment", "lcomment", "pcomment",
"symdebug", "linedebug"
};
static int segmenttypenumbers[COUNT_SEGTYPES] = {
0, 1, 1, 2, 3, 4, 5, 6, 7
};
/* code for managing buffers needed to seperate code and data into individual
* sections until they are ready to be written to the file.
* We'd better hope that it all fits in memory else we're buggered... */
#define BUF_BLOCK_LEN 4088 /* selected to match page size (4096)
* on 80x86 machines for efficiency */
/***********************************************************************
* Actual code to deal with RDOFF2 ouput format begins here...
*/
/* global variables set during the initialisation phase */
static struct SAA *seg[RDF_MAXSEGS]; /* seg 0 = code, seg 1 = data */
static struct SAA *header; /* relocation/import/export records */
static FILE *ofile;
static efunc error;
static struct seginfo {
char *segname;
int segnumber;
int16 segtype;
int16 segreserved;
long seglength;
} segments[RDF_MAXSEGS];
static int nsegments;
static long bsslength;
static long headerlength;
static void rdf2_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval)
{
int segtext, segdata, segbss;
/* set up the initial segments */
segments[0].segname = ".text";
segments[0].segnumber = 0;
segments[0].segtype = 1;
segments[0].segreserved = 0;
segments[0].seglength = 0;
segments[1].segname = ".data";
segments[1].segnumber = 1;
segments[1].segtype = 2;
segments[1].segreserved = 0;
segments[1].seglength = 0;
segments[2].segname = ".bss";
segments[2].segnumber = 2;
segments[2].segtype = 0xFFFF; /* reserved - should never be produced */
segments[2].segreserved = 0;
segments[2].seglength = 0;
nsegments = 3;
ofile = fp;
error = errfunc;
seg[0] = saa_init(1L);
seg[1] = saa_init(1L);
seg[2] = NULL; /* special case! */
header = saa_init(1L);
segtext = seg_alloc();
segdata = seg_alloc();
segbss = seg_alloc();
if (segtext != 0 || segdata != 2 || segbss != 4)
error(ERR_PANIC,"rdf segment numbers not allocated as expected (%d,%d,%d)",
segtext,segdata,segbss);
bsslength=0;
headerlength = 0;
}
static long rdf2_section_names(char *name, int pass, int *bits)
{
int i;
char * p, * q;
int code = -1;
int reserved = 0;
/*
* Default is 32 bits, in the text segment.
*/
if (!name) {
*bits = 32;
return 0;
}
/* look for segment type code following segment name */
p = name;
while (*p && !isspace(*p)) p++;
if (*p) { /* we're now in whitespace */
*p++ = '\0';
while (*p && isspace(80)) *p++ = '\0';
}
if (*p) { /* we're now in an attribute value */
/*
* see if we have an optional ',number' following the type code
*/
if ((q = strchr(p, ','))) {
*q++ = '\0';
reserved = readnum(q, &i);
if (i) {
error(ERR_NONFATAL, "value following comma must be numeric");
reserved = 0;
}
}
/*
* check it against the text strings in segmenttypes
*/
for (i = 0; i < COUNT_SEGTYPES; i++)
if (!nasm_stricmp(p, segmenttypes[i])) {
code = segmenttypenumbers[i];
break;
}
if (code == -1) { /* didn't find anything */
code = readnum(p, &i);
if (i) {
error(ERR_NONFATAL, "unrecognised RDF segment type (%s)",p);
code = 3;
}
}
}
for (i = 0; i < nsegments; i++) {
if (!strcmp(name, segments[i].segname)) {
if (code != -1 || reserved != 0)
error(ERR_NONFATAL, "segment attributes specified on"
" redeclaration of segment");
return segments[i].segnumber * 2;
}
}
/* declaring a new segment! */
if (code == -1) {
error(ERR_NONFATAL, "new segment declared without type code");
code = 3;
}
if (nsegments == RDF_MAXSEGS) {
error(ERR_FATAL, "reached compiled-in maximum segment limit (%d)",
RDF_MAXSEGS);
return NO_SEG;
}
segments[nsegments].segname = nasm_strdup(name);
i = seg_alloc();
if (i % 2 != 0)
error(ERR_PANIC, "seg_alloc() returned odd number");
segments[nsegments].segnumber = i >> 1;
segments[nsegments].segtype = code;
segments[nsegments].segreserved = reserved;
segments[nsegments].seglength = 0;
seg[nsegments] = saa_init(1L);
return i;
}
static void write_reloc_rec(struct RelocRec *r)
{
char buf[4],*b;
if (r->refseg != (int16)NO_SEG && (r->refseg & 1)) /* segment base ref */
r->type = 6;
r->refseg >>= 1; /* adjust segment nos to RDF rather than NASM */
saa_wbytes(header,&r->type,1);
saa_wbytes(header,&r->reclen,1);
saa_wbytes(header,&r->segment,1);
b = buf; WRITELONG(b,r->offset);
saa_wbytes(header,buf,4);
saa_wbytes(header,&r->length,1);
b = buf; WRITESHORT(b,r->refseg);
saa_wbytes(header,buf,2);
headerlength += r->reclen + 2;
}
static void write_export_rec(struct ExportRec *r)
{
char buf[4], *b;
r->segment >>= 1;
saa_wbytes(header,&r->type,1);
saa_wbytes(header,&r->reclen,1);
saa_wbytes(header,&r->segment,1);
b = buf; WRITELONG(b,r->offset);
saa_wbytes(header,buf,4);
saa_wbytes(header,r->label,strlen(r->label) + 1);
headerlength += r->reclen + 2;
}
static void write_import_rec(struct ImportRec *r)
{
char buf[4], *b;
r->segment >>= 1;
saa_wbytes(header,&r->type,1);
saa_wbytes(header,&r->reclen,1);
b = buf; WRITESHORT(b,r->segment);
saa_wbytes(header,buf,2);
saa_wbytes(header,r->label,strlen(r->label) + 1);
headerlength += r->reclen + 2;
}
static void write_bss_rec(struct BSSRec *r)
{
char buf[4], *b;
saa_wbytes(header,&r->type,1);
saa_wbytes(header,&r->reclen,1);
b = buf; WRITELONG(b,r->amount);
saa_wbytes(header,buf,4);
headerlength += r->reclen + 2;
}
static void write_dll_rec(struct DLLRec *r)
{
saa_wbytes(header,&r->type,1);
saa_wbytes(header,&r->reclen,1);
saa_wbytes(header,r->libname,strlen(r->libname) + 1);
headerlength += r->reclen + 2;
}
static void rdf2_deflabel(char *name, long segment, long offset,
int is_global, char *special)
{
struct ExportRec r;
struct ImportRec ri;
#ifdef VERBOSE_WARNINGS
static int warned_common = 0;
#endif
static int farsym = 0;
static int i;
if (special) {
while(*special == ' ' || *special == '\t') special++;
if (!nasm_stricmp(special, "far")) {
farsym = 1;
}
else if (!nasm_stricmp(special, "near")) {
farsym = 0;
}
else
error(ERR_NONFATAL, "unrecognised symbol type `%s'", special);
}
if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
error (ERR_NONFATAL, "unrecognised special symbol `%s'", name);
return;
}
if (is_global == 2) {
#ifdef VERBOSE_WARNINGS
if (!warned_common) {
error(ERR_WARNING,"common declarations not supported: using extern");
warned_common = 1;
}
#endif
is_global = 1;
}
for (i = 0; i < nsegments; i++) {
if (segments[i].segnumber == segment>>1) break;
}
if (i >= nsegments) { /* EXTERN declaration */
if (farsym)
ri.type = 7;
else
ri.type = 2;
ri.segment = segment;
strncpy(ri.label,name,32);
ri.label[32] = 0;
ri.reclen = 3 + strlen(ri.label);
write_import_rec(&ri);
} else if (is_global) {
r.type = 3;
r.segment = segment;
r.offset = offset;
strncpy(r.label,name,32);
r.label[32] = 0;
r.reclen = 6 + strlen(r.label);
write_export_rec(&r);
}
}
static void membufwrite(int segment, void * data, int bytes)
{
int i;
char buf[4], * b;
for (i = 0; i < nsegments; i++) {
if (segments[i].segnumber == segment) break;
}
if (i == nsegments)
error(ERR_PANIC, "can't find segment %d", segment);
if (bytes < 0) {
b = buf;
if (bytes == -2)
WRITESHORT(b,*(short *)data);
else
WRITELONG(b,*(long *)data);
data = buf;
bytes = -bytes;
}
segments[i].seglength += bytes;
saa_wbytes(seg[i],data,bytes);
}
static int getsegmentlength(int segment)
{
int i;
for (i = 0; i < nsegments; i++) {
if (segments[i].segnumber == segment) break;
}
if (i == nsegments)
error(ERR_PANIC, "can't find segment %d", segment);
return segments[i].seglength;
}
static void rdf2_out (long segto, void *data, unsigned long type,
long segment, long wrt)
{
long bytes = type & OUT_SIZMASK;
struct RelocRec rr;
unsigned char databuf[4],*pd;
int seg;
if (segto == NO_SEG) {
if ((type & OUT_TYPMASK) != OUT_RESERVE)
error (ERR_NONFATAL, "attempt to assemble code in ABSOLUTE space");
return;
}
segto >>= 1; /* convert NASM segment no to RDF number */
for (seg = 0; seg < nsegments; seg++) {
if (segments[seg].segnumber == segto) break;
}
if (seg >= nsegments) {
error(ERR_NONFATAL,"specified segment not supported by rdf output format");
return;
}
if (wrt != NO_SEG) {
wrt = NO_SEG; /* continue to do _something_ */
error (ERR_NONFATAL, "WRT not supported by rdf output format");
}
type &= OUT_TYPMASK;
if (segto == 2 && type != OUT_RESERVE)
{
error(ERR_NONFATAL, "BSS segments may not be initialised");
/* just reserve the space for now... */
if (type == OUT_REL2ADR)
bytes = 2;
else
bytes = 4;
type = OUT_RESERVE;
}
if (type == OUT_RESERVE) {
if (segto == 2) /* BSS segment space reserverd */
bsslength += bytes;
else
while (bytes --)
membufwrite(segto,databuf,1);
}
else if (type == OUT_RAWDATA) {
if (segment != NO_SEG)
error(ERR_PANIC, "OUT_RAWDATA with other than NO_SEG");
membufwrite(segto,data,bytes);
}
else if (type == OUT_ADDRESS) {
/* if segment == NO_SEG then we are writing an address of an
object within the same segment - do not produce reloc rec. */
/* FIXME - is this behaviour sane? at first glance it doesn't
appear to be. Must test this thoroughly...! */
if (segment != NO_SEG)
{
/* it's an address, so we must write a relocation record */
rr.type = 1; /* type signature */
rr.reclen = 8;
rr.segment = segto; /* segment we're currently in */
rr.offset = getsegmentlength(segto); /* current offset */
rr.length = bytes; /* length of reference */
rr.refseg = segment; /* segment referred to */
write_reloc_rec(&rr);
}
pd = databuf; /* convert address to little-endian */
if (bytes == 2)
WRITESHORT (pd, *(long *)data);
else
WRITELONG (pd, *(long *)data);
membufwrite(segto,databuf,bytes);
}
else if (type == OUT_REL2ADR)
{
if (segment == segto)
error(ERR_PANIC, "intra-segment OUT_REL2ADR");
rr.reclen = 8;
rr.offset = getsegmentlength(segto); /* current offset */
rr.length = 2; /* length of reference */
rr.refseg = segment; /* segment referred to (will be >>1'd)*/
if (segment != NO_SEG && segment % 2) {
rr.type = 6;
rr.segment = segto; /* memory base refs *aren't ever* relative! */
write_reloc_rec(&rr);
/* what do we put in the code? Simply the data. This should almost
* always be zero, unless someone's doing segment arithmetic...
*/
rr.offset = *(long *) data;
}
else
{
rr.type = 1; /* type signature */
rr.segment = segto+64; /* segment we're currently in + rel flag */
write_reloc_rec(&rr);
/* work out what to put in the code: offset of the end of this operand,
* subtracted from any data specified, so that loader can just add
* address of imported symbol onto it to get address relative to end of
* instruction: import_address + data(offset) - end_of_instrn */
rr.offset = *(long *)data -(rr.offset + bytes);
}
membufwrite(segto,&rr.offset,-2);
}
else if (type == OUT_REL4ADR)
{
if (segment == segto)
error(ERR_PANIC, "intra-segment OUT_REL4ADR");
if (segment != NO_SEG && segment % 2) {
error(ERR_PANIC, "erm... 4 byte segment base ref?");
}
rr.type = 1; /* type signature */
rr.segment = segto+64; /* segment we're currently in + rel tag */
rr.offset = getsegmentlength(segto); /* current offset */
rr.length = 4; /* length of reference */
rr.refseg = segment; /* segment referred to */
rr.reclen = 8;
write_reloc_rec(&rr);
rr.offset = *(long *)data -(rr.offset + bytes);
membufwrite(segto,&rr.offset,-4);
}
}
static void rdf2_cleanup (int debuginfo) {
long l;
struct BSSRec bs;
int i;
(void) debuginfo;
/* should write imported & exported symbol declarations to header here */
/* generate the output file... */
fwrite(RDOFF2Id,6,1,ofile); /* file type magic number */
if (bsslength != 0) /* reserve BSS */
{
bs.type = 5;
bs.amount = bsslength;
bs.reclen = 4;
write_bss_rec(&bs);
}
/*
* calculate overall length of the output object
*/
l = headerlength + 4;
for (i = 0; i < nsegments; i++) {
if (i == 2) continue; /* skip BSS segment */
l += 10 + segments[i].seglength;
}
l += 10; /* null segment */
fwritelong(l, ofile);
fwritelong(headerlength, ofile);
saa_fpwrite(header,ofile); /* dump header */
saa_free(header);
for (i = 0; i < nsegments; i++) {
if (i == 2) continue;
fwriteshort(segments[i].segtype, ofile);
fwriteshort(segments[i].segnumber, ofile);
fwriteshort(segments[i].segreserved, ofile);
fwritelong(segments[i].seglength, ofile);
saa_fpwrite(seg[i], ofile);
saa_free(seg[i]);
}
/* null segment - write 10 bytes of zero */
fwritelong(0,ofile);
fwritelong(0,ofile);
fwriteshort(0,ofile);
fclose(ofile);
}
static long rdf2_segbase (long segment) {
return segment;
}
static int rdf2_directive (char *directive, char *value, int pass) {
struct DLLRec r;
if (! strcmp(directive, "library")) {
if (pass == 1) {
r.type = 4;
strcpy(r.libname, value);
write_dll_rec(&r);
}
return 1;
}
return 0;
}
static void rdf2_filename (char *inname, char *outname, efunc error) {
standard_extension(inname,outname,".rdf",error);
}
static char *rdf2_stdmac[] = {
"%define __SECT__ [section .text]",
"%imacro library 1+.nolist",
"[library %1]",
"%endmacro",
"%macro __NASM_CDecl__ 1",
"%endmacro",
NULL
};
static int rdf2_set_info(enum geninfo type, char **val)
{
return 0;
}
struct ofmt of_rdf2 = {
"Relocatable Dynamic Object File Format v2.0",
"rdf",
NULL,
null_debug_arr,
&null_debug_form,
rdf2_stdmac,
rdf2_init,
rdf2_set_info,
rdf2_out,
rdf2_deflabel,
rdf2_section_names,
rdf2_segbase,
rdf2_directive,
rdf2_filename,
rdf2_cleanup
};
#endif /* OF_RDF2 */

202
parser.c
View File

@ -41,26 +41,34 @@ static int is_comma_next (void);
static int i;
static struct tokenval tokval;
static efunc error;
static struct ofmt *outfmt; /* Structure of addresses of output routines */
static loc_t *location; /* Pointer to current line's segment,offset */
void parser_global_info (struct ofmt *output, loc_t *locp)
{
outfmt = output;
location = locp;
}
insn *parse_line (int pass, char *buffer, insn *result,
efunc errfunc, evalfunc evaluate, evalinfofunc einfo) {
efunc errfunc, evalfunc evaluate, ldfunc ldef)
{
int operand;
int critical;
struct eval_hints hints;
result->forw_ref = FALSE;
error = errfunc;
einfo ("", 0L, 0L);
stdscan_reset();
stdscan_bufptr = buffer;
i = stdscan(NULL, &tokval);
result->label = NULL; /* Assume no label */
result->eops = NULL; /* must do this, whatever happens */
result->operands = 0; /* must initialise this */
if (i==0) { /* blank line - ignore */
result->label = NULL; /* so, no label on it */
result->opcode = -1; /* and no instruction either */
return result;
}
@ -68,23 +76,32 @@ insn *parse_line (int pass, char *buffer, insn *result,
(i!=TOKEN_REG || (REG_SREG & ~reg_flags[tokval.t_integer]))) {
error (ERR_NONFATAL, "label or instruction expected"
" at start of line");
result->label = NULL;
result->opcode = -1;
return result;
}
if (i == TOKEN_ID) { /* there's a label here */
result->label = tokval.t_charptr;
einfo (result->label, 0L, 0L);
i = stdscan(NULL, &tokval);
if (i == ':') { /* skip over the optional colon */
i = stdscan(NULL, &tokval);
} else if (i == 0 && pass == 1) {
error (ERR_WARNING|ERR_WARN_OL,
} else if (i == 0) {
error (ERR_WARNING|ERR_WARN_OL|ERR_PASS1,
"label alone on a line without a colon might be in error");
}
} else /* no label; so, moving swiftly on */
result->label = NULL;
if (i != TOKEN_INSN || tokval.t_integer != I_EQU)
{
/*
* FIXME: location->segment could be NO_SEG, in which case
* it is possible we should be passing 'abs_seg'. Look into this.
* Work out whether that is *really* what we should be doing.
* Generally fix things. I think this is right as it is, but
* am still not certain.
*/
ldef (result->label, location->segment,
location->offset, NULL, TRUE, FALSE, outfmt, errfunc);
}
}
if (i==0) {
result->opcode = -1; /* this line contains just a label */
@ -95,7 +112,8 @@ insn *parse_line (int pass, char *buffer, insn *result,
result->times = 1L;
while (i == TOKEN_PREFIX ||
(i==TOKEN_REG && !(REG_SREG & ~reg_flags[tokval.t_integer]))) {
(i==TOKEN_REG && !(REG_SREG & ~reg_flags[tokval.t_integer])))
{
/*
* Handle special case: the TIMES prefix.
*/
@ -115,9 +133,11 @@ insn *parse_line (int pass, char *buffer, insn *result,
result->times = 1L;
} else {
result->times = value->value;
if (value->value < 0)
if (value->value < 0) {
error(ERR_NONFATAL, "TIMES value %d is negative",
value->value);
result->times = 0;
}
}
} else {
if (result->nprefix == MAXPREFIX)
@ -169,7 +189,9 @@ insn *parse_line (int pass, char *buffer, insn *result,
result->opcode == I_RESQ ||
result->opcode == I_REST ||
result->opcode == I_EQU)
{
critical = pass;
}
else
critical = (pass==2 ? 2 : 0);
@ -178,12 +200,15 @@ insn *parse_line (int pass, char *buffer, insn *result,
result->opcode == I_DD ||
result->opcode == I_DQ ||
result->opcode == I_DT ||
result->opcode == I_INCBIN) {
result->opcode == I_INCBIN)
{
extop *eop, **tail = &result->eops, **fixptr;
int oper_num = 0;
result->eops_float = FALSE;
/*
* Begin to read the DB/DW/DD/DQ/DT operands.
* Begin to read the DB/DW/DD/DQ/DT/INCBIN operands.
*/
while (1) {
i = stdscan(NULL, &tokval);
@ -204,14 +229,14 @@ insn *parse_line (int pass, char *buffer, insn *result,
continue;
}
if (i == TOKEN_FLOAT || i == '-') {
if ((i == TOKEN_FLOAT && is_comma_next()) || i == '-') {
long sign = +1L;
if (i == '-') {
char *save = stdscan_bufptr;
i = stdscan(NULL, &tokval);
sign = -1L;
if (i != TOKEN_FLOAT) {
if (i != TOKEN_FLOAT || !is_comma_next()) {
stdscan_bufptr = save;
i = tokval.t_type = '-';
}
@ -219,23 +244,30 @@ insn *parse_line (int pass, char *buffer, insn *result,
if (i == TOKEN_FLOAT) {
eop->type = EOT_DB_STRING;
result->eops_float = TRUE;
if (result->opcode == I_DD)
eop->stringlen = 4;
else if (result->opcode == I_DQ)
eop->stringlen = 8;
else if (result->opcode == I_DT)
eop->stringlen = 10;
eop->stringlen = 10;
else {
error(ERR_NONFATAL, "floating-point constant"
" encountered in `D%c' instruction",
result->opcode == I_DW ? 'W' : 'B');
eop->type = EOT_NOTHING;
/*
* fix suggested by Pedro Gimeno... original line
* was:
* eop->type = EOT_NOTHING;
*/
eop->stringlen = 0;
}
eop = nasm_realloc(eop, sizeof(extop)+eop->stringlen);
tail = &eop->next;
*fixptr = eop;
eop->stringval = (char *)eop + sizeof(extop);
if (!float_const (tokval.t_charptr, sign,
if (eop->stringlen < 4 ||
!float_const (tokval.t_charptr, sign,
(unsigned char *)eop->stringval,
eop->stringlen, error))
eop->type = EOT_NOTHING;
@ -244,7 +276,8 @@ insn *parse_line (int pass, char *buffer, insn *result,
}
}
/* anything else */ {
/* anything else */
{
expr *value;
value = evaluate (stdscan, NULL, &tokval, NULL,
critical, error, NULL);
@ -312,7 +345,12 @@ insn *parse_line (int pass, char *buffer, insn *result,
*/
result->opcode = -1;
return result;
}
} else /* DB ... */
if (oper_num == 0)
error (ERR_WARNING|ERR_PASS1,
"no operand for data declaration");
else
result->operands = oper_num;
return result;
}
@ -324,29 +362,42 @@ insn *parse_line (int pass, char *buffer, insn *result,
expr *value; /* used most of the time */
int mref; /* is this going to be a memory ref? */
int bracket; /* is it a [] mref, or a & mref? */
int setsize = 0;
result->oprs[operand].addr_size = 0;/* have to zero this whatever */
result->oprs[operand].eaflags = 0; /* and this */
result->oprs[operand].opflags = 0;
i = stdscan(NULL, &tokval);
if (i == 0) break; /* end of operands: get out of here */
result->oprs[operand].type = 0; /* so far, no override */
while (i == TOKEN_SPECIAL) {/* size specifiers */
switch ((int)tokval.t_integer) {
case S_BYTE:
result->oprs[operand].type |= BITS8;
if (!setsize) /* we want to use only the first */
result->oprs[operand].type |= BITS8;
setsize = 1;
break;
case S_WORD:
result->oprs[operand].type |= BITS16;
if (!setsize)
result->oprs[operand].type |= BITS16;
setsize = 1;
break;
case S_DWORD:
case S_LONG:
result->oprs[operand].type |= BITS32;
if (!setsize)
result->oprs[operand].type |= BITS32;
setsize = 1;
break;
case S_QWORD:
result->oprs[operand].type |= BITS64;
if (!setsize)
result->oprs[operand].type |= BITS64;
setsize = 1;
break;
case S_TWORD:
result->oprs[operand].type |= BITS80;
if (!setsize)
result->oprs[operand].type |= BITS80;
setsize = 1;
break;
case S_TO:
result->oprs[operand].type |= TO;
@ -360,6 +411,8 @@ insn *parse_line (int pass, char *buffer, insn *result,
case S_SHORT:
result->oprs[operand].type |= SHORT;
break;
default:
error (ERR_NONFATAL, "invalid operand size specification");
}
i = stdscan(NULL, &tokval);
}
@ -397,8 +450,12 @@ insn *parse_line (int pass, char *buffer, insn *result,
}
value = evaluate (stdscan, NULL, &tokval,
&result->forw_ref, critical, error, &hints);
&result->oprs[operand].opflags,
critical, error, &hints);
i = tokval.t_type;
if (result->oprs[operand].opflags & OPFLAG_FORWARD) {
result->forw_ref = TRUE;
}
if (!value) { /* error in evaluator */
result->opcode = -1; /* unrecoverable parse error: */
return result; /* ignore this instruction */
@ -434,8 +491,12 @@ insn *parse_line (int pass, char *buffer, insn *result,
i = stdscan(NULL, &tokval);
}
value = evaluate (stdscan, NULL, &tokval,
&result->forw_ref, critical, error, &hints);
&result->oprs[operand].opflags,
critical, error, &hints);
i = tokval.t_type;
if (result->oprs[operand].opflags & OPFLAG_FORWARD) {
result->forw_ref = TRUE;
}
/* and get the offset */
if (!value) { /* but, error in evaluator */
result->opcode = -1; /* unrecoverable parse error: */
@ -480,34 +541,38 @@ insn *parse_line (int pass, char *buffer, insn *result,
i = e->type, s = e->value;
e++;
}
if (e->type && e->type <= EXPR_REG_END) {/* it's a 2nd register */
if (e->value != 1) { /* it has to be indexreg */
if (i != -1) { /* but it can't be */
error(ERR_NONFATAL, "invalid effective address");
result->opcode = -1;
return result;
} else
i = e->type, s = e->value;
} else { /* it can be basereg */
if (b != -1) /* or can it? */
i = e->type, s = 1;
else
b = e->type;
}
if (e->type && e->type <= EXPR_REG_END) /* it's a 2nd register */
{
if (b != -1) /* If the first was the base, ... */
i = e->type, s = e->value; /* second has to be indexreg */
else if (e->value != 1) /* If both want to be index */
{
error(ERR_NONFATAL, "invalid effective address");
result->opcode = -1;
return result;
}
else
b = e->type;
e++;
}
if (e->type != 0) { /* is there an offset? */
if (e->type <= EXPR_REG_END) {/* in fact, is there an error? */
if (e->type <= EXPR_REG_END) /* in fact, is there an error? */
{
error (ERR_NONFATAL, "invalid effective address");
result->opcode = -1;
return result;
} else {
}
else
{
if (e->type == EXPR_UNKNOWN) {
o = 0; /* doesn't matter what */
result->oprs[operand].wrt = NO_SEG; /* nor this */
o = 0; /* doesn't matter what */
result->oprs[operand].wrt = NO_SEG; /* nor this */
result->oprs[operand].segment = NO_SEG; /* or this */
while (e->type) e++; /* go to the end of the line */
} else {
}
else
{
if (e->type == EXPR_SIMPLE) {
o = e->value;
e++;
@ -566,30 +631,63 @@ insn *parse_line (int pass, char *buffer, insn *result,
result->oprs[operand].indexreg = i;
result->oprs[operand].scale = s;
result->oprs[operand].offset = o;
} else { /* it's not a memory reference */
}
else /* it's not a memory reference */
{
if (is_just_unknown(value)) { /* it's immediate but unknown */
result->oprs[operand].type |= IMMEDIATE;
result->oprs[operand].offset = 0; /* don't care */
result->oprs[operand].segment = NO_SEG; /* don't care again */
result->oprs[operand].wrt = NO_SEG;/* still don't care */
} else if (is_reloc(value)) { /* it's immediate */
}
else if (is_reloc(value)) /* it's immediate */
{
result->oprs[operand].type |= IMMEDIATE;
result->oprs[operand].offset = reloc_value(value);
result->oprs[operand].segment = reloc_seg(value);
result->oprs[operand].wrt = reloc_wrt(value);
if (is_simple(value) && reloc_value(value)==1)
result->oprs[operand].type |= UNITY;
} else { /* it's a register */
}
else /* it's a register */
{
int i;
if (value->type>=EXPR_SIMPLE || value->value!=1) {
error (ERR_NONFATAL, "invalid operand type");
result->opcode = -1;
return result;
}
/*
* check that its only 1 register, not an expression...
*/
for (i = 1; value[i].type; i++)
if (value[i].value) {
error (ERR_NONFATAL, "invalid operand type");
result->opcode = -1;
return result;
}
/* clear overrides, except TO which applies to FPU regs */
if (result->oprs[operand].type & ~TO) {
/*
* we want to produce a warning iff the specified size
* is different from the register size
*/
i = result->oprs[operand].type & SIZE_MASK;
}
else
i = 0;
result->oprs[operand].type &= TO;
result->oprs[operand].type |= REGISTER;
result->oprs[operand].type |= reg_flags[value->type];
result->oprs[operand].basereg = value->type;
if (i && (result->oprs[operand].type & SIZE_MASK) != i)
error (ERR_WARNING|ERR_PASS1,
"register size specification ignored");
}
}
}
@ -612,7 +710,8 @@ insn *parse_line (int pass, char *buffer, insn *result,
return result;
}
static int is_comma_next (void) {
static int is_comma_next (void)
{
char *p;
int i;
struct tokenval tv;
@ -623,7 +722,8 @@ static int is_comma_next (void) {
return (i == ',' || i == ';' || !i);
}
void cleanup_insn (insn *i) {
void cleanup_insn (insn *i)
{
extop *e;
while (i->eops) {

View File

@ -10,8 +10,9 @@
#ifndef NASM_PARSER_H
#define NASM_PARSER_H
void parser_global_info (struct ofmt *output, loc_t *locp);
insn *parse_line (int pass, char *buffer, insn *result,
efunc error, evalfunc evaluate, evalinfofunc einfo);
efunc error, evalfunc evaluate, ldfunc ldef);
void cleanup_insn (insn *instruction);
#endif

1468
preproc.c

File diff suppressed because it is too large Load Diff

9
sync.c
View File

@ -25,7 +25,8 @@ static struct Sync {
} *synx;
static int nsynx;
void init_sync(void) {
void init_sync(void)
{
/*
* I'd like to allocate an array of size SYNC_MAX, then write
* `synx--' which would allow numbering the array from one
@ -48,7 +49,8 @@ void init_sync(void) {
nsynx = 0;
}
void add_sync(unsigned long pos, unsigned long length) {
void add_sync(unsigned long pos, unsigned long length)
{
int i;
if (nsynx == SYNC_MAX)
@ -68,7 +70,8 @@ void add_sync(unsigned long pos, unsigned long length) {
}
}
unsigned long next_sync(unsigned long position, unsigned long *length) {
unsigned long next_sync(unsigned long position, unsigned long *length)
{
while (nsynx > 0 && synx[1].pos + synx[1].length <= position) {
int i, j;
struct Sync t;

1457
zoutieee.c Normal file

File diff suppressed because it is too large Load Diff