NASM 0.98.08

This commit is contained in:
H. Peter Anvin 2002-04-30 21:00:33 +00:00
parent af535c16cf
commit 1cd0e2d5bf
54 changed files with 4335 additions and 605 deletions

90
AUTHORS Normal file
View File

@ -0,0 +1,90 @@
This is the AUTHORS file for the NASM project located at:
http://nasm.rm-f.net/
Names should be inserted as follows:
N: Name Here
E: Email Here
D: Description Here
D: Additional Description Here.... and so on
Such is life.
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
N: Julian Hall
E: Jules@acris.co.uk
D: Original author and co-conspirator
N: Simon Tatham
E: anakin@pobox.com
D: Original author and co-conspirator
N: Nelson Rush
E: palisade@users.sourceforge.net
D: Some guy.
N: Frank Kotler
E: fbkotler@nettaxi.com
D: Bug smashing.
D: Documentation - "KATMAI" and "3DNow!" instructions supported by 0.98
N: Stephen Silver
E: nasm@argentum.freeserve.co.uk
D: Documentation - "3dNow!" instructions and misc.
D: insns.dat fixes and new instructions.
N: AMD Inc. (names of developers here?)
E:
D: 3DNow instructions
D: New Athlon instructions
D: Makefile.vc fix
N: John Coffman
E: johninsd@users.sourceforge.net
D: added Jcc optimizations; CPU level checks
D: bug fixes, compilation fixes
N: Yuri Zaporogets
E: yuriz@users.sourceforge.net
D: RDOFF support
N: H. Peter Anvin
E: hpa@zytor.com
D: Organized 0.98 release and Linux binaries
N: John Fine
E: johnfine@earthlink.net
D: Preprocessor and OBJ (OMF) output format driver
D: Organized DOS versions of 0.98 release
N: Kendall Bennet
E: KendallB@scitechsoft.com
D: NASM enhancements
D: macros
D: Syntax modifications
N: Gary Clark
E:
D: AMD 3DNow! instructions
N: Andrew Crabtree
E:
D: Debugging support
N: Rafael R. Sevilla
E: dido@pacific.net.ph
D: RDF2HEX utility
N: Jaime Tejedor Gómez, aka Metalbrain
E: metalbrain_coder@gmx.net
D: jecxz bug fix
N: James Seter
E: pharos@zsnes.com
D: --POSTFIX, --PREFIX switches
D: ?
N: Edward J. Beroset
E: beroset@mindspring.com
D: added %substr and %strlen

View File

@ -1,3 +1,46 @@
01/28/01 - fbk - added Stepane Denis' SSE2 instructions to a *working*
version of the code - some earlier versions were based on
broken code - sorry 'bout that. version "0.98.07"
01/28/01 - fbk - cosmetic modifications to nasm.c, nasm.h,
AUTHORS, MODIFIED
01/18/01 - fbk - "metalbrain"s jecxz bug fix in insns.dat
- alter nasmdoc.src to match - version "0.98.06f"
01/09/01 - fbk - removed the "outforms.h" file - it appears to be
someone's old backup of "outform.h". version "0.98.06e"
01/09/01 - fbk - finally added the fix for the "multiple %includes bug",
known since 7/27/99 - reported originally (?) and sent to
us by Austin Lunnen - he reports that John Fine had a fix
within the day. Here it is...
---- Nelson Rush resigns from the group. Big thanks to Nelson for
his leadership and enthusiasm in getting these changes
incorporated into Nasm!
---- fbk - [list +], [list -] directives - ineptly implemented, should
be re-written or removed, perhaps.
---- Brian Raiter / fbk - "elfso bug" fix - applied to aoutb format
as well - testing might be desirable...
08/07/00 - James Seter - -postfix, -prefix command line switches.
---- Yuri Zaporogets - rdoff utility changes.
John Coffman's changes:
For the JMP and other optimizations see the file README03.txt.
Kendall Bennett's changes:
For changes since the 0.98 release see the file scitech.txt. Note
that you must define "TASM_COMPAT" at compile-time
to get the Tasm Ideal Mode compatibility.
----------------------------------------------
... this is the 0.98 "modified" file ...
--------------------------------------------------
This file details changes since NASM 0.98p3. All the releases in this
file have been produced by H. Peter Anvin <hpa@zytor.com>.

View File

@ -13,7 +13,7 @@
# You may need to adjust these values.
CC = gcc -s
CC = gcc
CFLAGS = -O2 -I.
# You _shouldn't_ need to adjust anything below this line.

145
Mkfiles/Makefile.emx Normal file
View File

@ -0,0 +1,145 @@
# Generated automatically from Makefile.in by configure.
# $Id$
#
# Auto-configuring Makefile for 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.
srcdir = .
prefix = /usr/local
exec_prefix = ${prefix}
bindir = ${exec_prefix}/bin
mandir = ${prefix}/man
CC = gcc
CFLAGS = -s -Zomf -O2 -fomit-frame-pointer -Wall -pedantic \
-I$(srcdir) -I. -DTASM_COMPAT
LDFLAGS = -s -Zomf -Zexe -Zcrtdll
LIBS = -lgcc
INSTALL = ./install-sh -c
INSTALL_PROGRAM = ${INSTALL}
INSTALL_DATA = ${INSTALL} -m 644
NROFF = echo
.SUFFIXES: .c .i .s .o .1 .man
.PHONY: all doc rdf install clean distclean cleaner spotless install_rdf
.PHONY: install_doc everything install_everything
.c.o:
$(CC) -c $(CFLAGS) -o $@ $<
.c.s:
$(CC) -S $(CFLAGS) -o $@ $<
.c.i:
$(CC) -E $(CFLAGS) -o $@ $<
.1.man:
$(NROFF) -man $< > $@
NASM = nasm.o nasmlib.o float.o insnsa.o assemble.o labels.o \
parser.o outform.o outbin.o outaout.o outcoff.o outelf.o \
outobj.o outas86.o outrdf.o outrdf2.o outdbg.o zoutieee.o \
preproc.o listing.o eval.o
NDISASM = ndisasm.o disasm.o sync.o nasmlib.o insnsd.o
all: nasm ndisasm nasm.man ndisasm.man
$(MAKE) -C rdoff -f Makefile.emx all
nasm: $(NASM)
$(CC) $(LDFLAGS) -o nasm $(NASM) $(LIBS)
ndisasm: $(NDISASM)
$(CC) $(LDFLAGS) -o ndisasm $(NDISASM) $(LIBS)
assemble.o: assemble.c nasm.h insnsi.h nasmlib.h assemble.h insns.h
disasm.o: disasm.c nasm.h insnsi.h disasm.h sync.h insns.h names.c insnsn.c
eval.o: eval.c eval.h nasm.h insnsi.h nasmlib.h
float.o: float.c nasm.h insnsi.h
insnsa.o: insnsa.c nasm.h insnsi.h insns.h
insnsd.o: insnsd.c nasm.h insnsi.h insns.h
labels.o: labels.c nasm.h insnsi.h nasmlib.h
listing.o: listing.c nasm.h insnsi.h nasmlib.h listing.h
nasm.o: nasm.c nasm.h insnsi.h nasmlib.h preproc.h parser.h assemble.h labels.h \
outform.h listing.h
nasmlib.o: nasmlib.c nasm.h insnsi.h nasmlib.h names.c insnsn.c
ndisasm.o: ndisasm.c nasm.h insnsi.h nasmlib.h sync.h disasm.h
outaout.o: outaout.c nasm.h insnsi.h nasmlib.h outform.h
outas86.o: outas86.c nasm.h insnsi.h nasmlib.h outform.h
outbin.o: outbin.c nasm.h insnsi.h nasmlib.h outform.h
outcoff.o: outcoff.c nasm.h insnsi.h nasmlib.h outform.h
outdbg.o: outdbg.c nasm.h insnsi.h nasmlib.h outform.h
outelf.o: outelf.c nasm.h insnsi.h nasmlib.h outform.h
outform.o: outform.c outform.h nasm.h insnsi.h
outobj.o: outobj.c nasm.h insnsi.h nasmlib.h outform.h
outrdf.o: outrdf.c nasm.h insnsi.h nasmlib.h outform.h
outrdf2.o: outrdf2.c nasm.h insnsi.h nasmlib.h outform.h
parser.o: parser.c nasm.h insnsi.h nasmlib.h parser.h float.h names.c insnsn.c
preproc.o: preproc.c nasm.h insnsi.h nasmlib.h macros.c
sync.o: sync.c sync.h
zoutieee.o: zoutieee.c nasm.h insnsi.h nasmlib.h outform.h
# These source files are automagically generated from a single
# instruction-table file by a Perl script. They're distributed,
# though, so it isn't necessary to have Perl just to recompile NASM
# from the distribution.
insnsa.c: insns.dat insns.pl
perl $(srcdir)/insns.pl -a $(srcdir)/insns.dat
insnsd.c: insns.dat insns.pl
perl $(srcdir)/insns.pl -d $(srcdir)/insns.dat
insnsi.h: insns.dat insns.pl
perl $(srcdir)/insns.pl -i $(srcdir)/insns.dat
insnsn.c: insns.dat insns.pl
perl $(srcdir)/insns.pl -n $(srcdir)/insns.dat
# This source file is generated from the standard macros file
# `standard.mac' by another Perl script. Again, it's part of the
# standard distribution.
macros.c: standard.mac macros.pl
perl $(srcdir)/macros.pl $(srcdir)/standard.mac
install: nasm ndisasm
$(INSTALL_PROGRAM) nasm $(INSTALLROOT)$(bindir)/nasm
$(INSTALL_PROGRAM) ndisasm $(INSTALLROOT)$(bindir)/ndisasm
$(INSTALL_DATA) $(srcdir)/nasm.1 $(INSTALLROOT)$(mandir)/man1/nasm.1
$(INSTALL_DATA) $(srcdir)/ndisasm.1 $(INSTALLROOT)$(mandir)/man1/ndisasm.1
clean:
rm -f *.o *.s *.i nasm ndisasm
cd rdoff && $(MAKE) clean
distclean: clean
rm -f config.* Makefile *~ *.bak *.lst *.bin
cd rdoff && $(MAKE) distclean
cleaner: clean
rm -f insnsa.c insnsd.c insnsi.h insnsn.c macros.c *.man
cd doc && $(MAKE) clean
spotless: distclean cleaner
rdf:
cd rdoff && $(MAKE)
rdf_install install_rdf:
cd rdoff && $(MAKE) install
doc:
cd doc && $(MAKE) all
doc_install install_doc:
cd doc && $(MAKE) install
everything: all doc rdf
install_everything: everything install install_doc install_rdf

View File

@ -34,7 +34,7 @@ all : nasm$(SUFFIX)$(EXE) ndisasm$(SUFFIX)$(EXE)
# We have to have a horrible kludge here to get round the 128 character
# limit, as usual...
LINKOBJS = a*.obj e*.obj f*.obj insnsa.obj l*.obj na*.obj o*.obj p*.obj
LINKOBJS = a*.obj e*.obj f*.obj insnsa.obj l*.obj na*.obj o*.obj p*.obj z*.obj
nasm$(SUFFIX)$(EXE): $(NASMOBJS)
cl /Fenasm$(SUFFIX).exe $(LINKOBJS)

187
README.1st Normal file
View File

@ -0,0 +1,187 @@
This is a specially patched version of NASM. It can be used to supplement
building of Crystal Space, the Open Source 3D Engine project. You can find
Crystal Space at the following locations:
http://crystal.linuxgames.com/
http://crystal.sourceforge.net/
Details of changes in this version of NASM follow.
-*- A new keyword %xdefine and its case-insensitive counterpart %ixdefine.
They work almost the same way as %define and %idefine but expand
the definition immediately, not on the invocation. Something like a cross
between %define and %assign. The "x" suffix stands for "eXpand", so
"xdefine" can be deciphered as "expand-and-define". Thus you can do
things like this:
%assign ofs 0
%macro arg 1
%xdefine %1 dword [esp+ofs]
%assign ofs ofs+4
%endmacro
-*- Changed the place where the expansion of %$name macros are expanded.
Now they are converted into ..@ctxnum.name form when detokenizing, so
there are no quirks as before when using %$name arguments to macros,
in macros etc. For example:
%macro abc 1
%define %1 hello
%endm
abc %$here
%$here
Now last line will be expanded to "hello" as expected. This also allows
for lots of goodies, a good example are extended "proc" macros included
in this archive.
-*- Added a check for "cstk" in smacro_defined() before calling get_ctx() -
this allows for things like:
%ifdef %$abc
%endif
to work without warnings even in no context.
-*- Added a check for "cstk" in %if*ctx and %elif*ctx directives -
this allows to use %ifctx without excessive warnings. If there is
no active context, %ifctx goes through "false" branch.
-*- Removed "user error: " prefix with %error directive: it just clobbers the
output and has absolutely no functionality. Besides, this allows to write
macros that does not differ from build-in functions in any way.
-*- Added expansion of string that is output by %error directive. Now you
can do things like:
%define hello(x) Hello, x!
%define %$name andy
%error "hello(%$name)"
Same happened with %include directive.
-*- Now all directives that expect an identifier will try to expand and
concatenate everything without whitespaces in between before usage.
For example, with "unfixed" nasm the commands
%define %$abc hello
%define __%$abc goodbye
__%$abc
would produce "incorrect" output: last line will expand to
hello goodbyehello
Not quite what you expected, eh? :-) The answer is that preprocessor
treats the %define construct as if it would be
%define __ %$abc goodbye
(note the white space between __ and %$abc). After my "fix" it
will "correctly" expand into
goodbye
as expected. Note that I use quotes around words "correct", "incorrect"
etc because this is rather a feature not a bug; however current behaviour
is more logical (and allows more advanced macro usage :-).
Same change was applied to:
%push,%macro,%imacro,%define,%idefine,%xdefine,%ixdefine,
%assign,%iassign,%undef
-*- A new directive [WARNING {+|-}warning-id] have been added. It works only
if the assembly phase is enabled (i.e. it doesn't work with nasm -e).
-*- A new warning type: macro-selfref. By default this warning is disabled;
when enabled NASM warns when a macro self-references itself; for example
the following source:
[WARNING macro-selfref]
%macro push 1-*
%rep %0
push %1
%rotate 1
%endrep
%endmacro
push eax,ebx,ecx
will produce a warning, but if we remove the first line we won't see it
anymore (which is The Right Thing To Do {tm} IMHO since C preprocessor
eats such constructs without warnings at all).
-*- Added a "error" routine to preprocessor which always will set ERR_PASS1
bit in severity_code. This removes annoying repeated errors on first
and second passes from preprocessor.
-*- Added the %+ operator in single-line macros for concatenating two
identifiers. Usage example:
%define _myfunc _otherfunc
%define cextern(x) _ %+ x
cextern (myfunc)
After first expansion, third line will become "_myfunc". After this
expansion is performed again so it becomes "_otherunc".
-*- Now if preprocessor is in a non-emmitting state, no warning or error
will be emmitted. Example:
%if 1
mov eax,ebx
%else
put anything you want between these two brackets,
even macro-parameter references %1 or local labels %$zz
or macro-local labels %%zz - no warning will be emmitted.
%endif
-*- Context-local variables on expansion as a last resort are looked up
in outer contexts. For example, the following piece:
%push outer
%define %$a [esp]
%push inner
%$a
%pop
%pop
will expand correctly the fourth line to [esp]; if we'll define another
%$a inside the "inner" context, it will take precedence over outer
definition. However, this modification has been applied only to
expand_smacro and not to smacro_define: as a consequence expansion
looks in outer contexts, but %ifdef won't look in outer contexts.
This behaviour is needed because we don't want nested contexts to
act on already defined local macros. Example:
%define %$arg1 [esp+4]
test eax,eax
if nz
mov eax,%$arg1
endif
In this example the "if" mmacro enters into the "if" context, so %$arg1
is not valid anymore inside "if". Of course it could be worked around
by using explicitely %$$arg1 but this is ugly IMHO.
-------------------------------// fixes for 0.98 //-----------------------------
-*- Fixed memory leak in %undef. The origline wasn't freed before
exiting on success.
-----------------------------// Fixes for 0.98.01 //----------------------------
-*- Fixed trap in preprocessor when line expanded to empty set of tokens.
This happens, for example, in the following case:
#define SOMETHING
SOMETHING
Andrew Zabolotny <bit@eltech.ru>

76
Readme
View File

@ -1,53 +1,49 @@
This directory contains the necessary files to port the C compiler
``LCC'' (available by FTP from sunsite.doc.ic.ac.uk in the directory
/computing/programming/languages/c/lcc) to compile for Linux (a.out or
ELF) or other supported operating systems by using NASM as a back-end
code generator.
This patch has been tested on lcc version 4.0.
NetWide Assembler for the SciTech MGL
-------------------------------------
To install:
This is a modified distribution of NASM, the Netwide Assembler. NASM
is a prototype general-purpose x86 assembler. It will currently output
flat-form binary files, a.out, COFF and ELF Unix object files,
Microsoft Win32 and 16-bit DOS object files, OS/2 object files, the
as86 object format, and a home-grown format called RDF.
- Copy `x86nasm.md' into the `src' directory of the lcc tree.
This version of NASM has been modified by SciTech Software such that it
can be used to assemble source code in the SciTech MGL graphics library,
and understands enough of TASM assembler syntax such that both NASM
and TASM can be used to generate assembler modules for the MGL graphics
library. A complete macro package is provided as part of the SciTech
MGL that provides macros to help in building modules that will work with
either assembler.
- Copy either `lin-elf.c' or `lin-aout.c' into the `etc' directory.
A pre-compiled binary of NASM is provided as part of the SciTech MGL
graphics library, however you may re-build the assembler from the sources
provided. To do so make sure you have the SciTech Makefile Utilties
correctly configured for your compiler, and then simly type:
- With previous versions, you had to modify x86-nasm.md if you weren't
using ELF. There is now inbuilt support within NASM in the shape
of the __CDECL__ macro, so this modification is no longer necessary.
unset DBG
dmake OPT=1
- Make the following changes to `bind.c' in the `src' directory:
to build an optimised, non-debug version of the assembler. If you wish
to rebuild for a different OS other than DOS or Win32, you will need to
first compile the DMAKE make program for your OS. See the DMAKE source
code for more information.
- Near the top of the file, add a line that reads
extern Interface x86nasmIR;
Licensing issues:
-----------------
- In the `bindings' array, add the lines
"x86-nasm", &x86nasmIR,
"x86/nasm", &x86nasmIR,
(in sensible looking places...)
For information about how you can distribute and use NASM, see the
file Licence.
A sample `bind.c' has been provided to show what the result of
this might look like. You might be able to get away with using it
directly...
The NASM web page is at http://www.cryogen.com/Nasm/
- Modify the lcc makefile to include rules for x86nasm.o: this will
have to be done in about three places. Just copy any line with
`x86' on it and modify it to read `x86nasm' everywhere. (Except
that in the list of object files that rcc is made up from, do
remember to ensure that every line but the last has a trailing
backslash...)
Bug reports specific to the SciTech MGL should be posted to SciTech
Software MGL newsgroups:
- You may have to modify the contents of `lin-elf.c' or `lin-aout.c'
to reflect the true locations of files such as crt0.o, crt1.o,
ld-linux.so and so forth. If you don't know where to find these,
compile a short C program with `gcc -v' and see what command line
gcc feeds to `ld'.
news://news.scitechsoft.com/scitech.mgl.developer
- You should now be able to build lcc, using `lin-elf.c' or
`lin-aout.c' as the system-dependent part of the `lcc' wrapper
program.
Bug reports (and patches if you can) for NASM itself that are not SciTech
MGL related should be sent to the authors at:
- Symlink x86nasm.c into the `src' directory before attempting the
triple test, or the compile will fail.
- Now it should pass the triple test, on either ELF or a.out. Voila!
Julian Hall <jules@earthcorp.com>
Simon Tatham <anakin@pobox.com>

View File

@ -152,7 +152,7 @@ static int jmp_match (long segment, long offset, int bits,
if (c != 0370) return 0;
if (ins->oprs[0].opflags & OPFLAG_FORWARD) return 1; /* match a forward reference */
if (ins->oprs[0].opflags & OPFLAG_FORWARD) return (! pass0); /*1;*/ /* match a forward reference */
isize = calcsize (segment, offset, bits, ins, code);
if (ins->oprs[0].segment != segment) return 0;

View File

@ -24,7 +24,9 @@ OUT = nasm.info
all: $(OUT)
.SUFFIXES: .src .texi .info .ps .rtf .hpj .dvi .ps .txt .pl
os2: nasm.inf
.SUFFIXES: .src .texi .info .ps .rtf .hpj .dvi .ps .txt .pl .ipf .inf
# Consider html, txt and src output a side effect
.src.texi:
@ -37,11 +39,18 @@ nasm.info: nasmdoc.texi
$(MAKEINFO) $<
mv -f *.info *.info-* info
# Rules for building an OS/2 book
.texi.ipf:
texi2ipf $< >$@
nasm.inf: nasmdoc.ipf
ipfc -i -s $< $@
clean:
-rm -f *.rtf *.hpj *.texi *.ph *.gid
-rm -f *.rtf *.hpj *.texi *.ph *.gid *.ipf
spotless: clean
-rm -rf html info *.hlp *.txt *.ps
-rm -rf html info *.hlp *.txt *.ps *.inf
install: all
$(INSTALL_DATA) info/* $(INSTALLROOT)$(infodir)

File diff suppressed because it is too large Load Diff

View File

@ -5,11 +5,6 @@
# TODO:
#
# PS output:
# - show page numbers in printed output
# - think about double-sided support (start all chapters on RHS,
# ie odd-numbered, pages).
#
# Ellipsis support would be nice.
# Source-form features:
@ -1091,6 +1086,7 @@ sub write_ps {
# now) to the length of the current page. Also, _put_ this line on
# the current page, and allocate it a y-coordinate.
if ($ltypes[$i] =~ /^chap$/) {
$pnum += 1 - ($pnum & 1); # advance to odd numbered page if necessary
$plen = 100; # ADJUSTABLE: space taken up by a chapter heading
$ycoord[$i] = 0; # chapter heading: y-coord doesn't matter
} else {
@ -1234,7 +1230,7 @@ sub write_ps {
last PAGE if $i > $#psindex;
}
}
&ps_trailer;
&ps_trailer($page);
close PS;
select STDOUT;
}
@ -1263,6 +1259,10 @@ sub ps_header {
'/es /Helvetica-Oblique findfont 12 scalefont def',
'/cs /Courier-Bold findfont 12 scalefont def',
'/n 16#6E def /e 16#65 def /c 16#63 def',
'/pageodd {',
' 550 50 moveto ns setfont dup stringwidth pop neg 0 rmoveto show',
'} def',
'/pageeven { 50 50 moveto ns setfont show } def',
'/chapter {',
' 100 620 moveto',
' {',
@ -1383,14 +1383,18 @@ sub ps_header {
}
sub ps_trailer {
&ps_donepg;
my ($oldpg) = @_;
&ps_donepg($oldpg);
print "%%Trailer\nrestore\n%%EOF\n";
}
sub ps_throw_pg {
my ($oldpg, $newpg) = @_;
&ps_donepg;
&ps_initpg($newpg);
while ($oldpg < $newpg) {
&ps_donepg($oldpg);
$oldpg++;
&ps_initpg($oldpg);
}
}
sub ps_initpg {
@ -1400,7 +1404,12 @@ sub ps_initpg {
}
sub ps_donepg {
print "%%PageTrailer\nrestore showpage\n";
my ($pgnum) = @_;
if ($pgnum & 1) {
print "%%PageTrailer\n($pgnum)pageodd restore showpage\n";
} else {
print "%%PageTrailer\n($pgnum)pageeven restore showpage\n";
}
}
sub ps_out_line {
@ -1516,7 +1525,7 @@ sub write_texi {
select TEXT;
# Preamble.
print "\input texinfo \@c -*-texinfo-*-\n";
print "\\input texinfo \@c -*-texinfo-*-\n";
print "\@c \%**start of header\n";
print "\@setfilename nasm.info\n";
print "\@dircategory Programming\n";
@ -1550,7 +1559,7 @@ sub write_texi {
print "\@end titlepage\n";
print "\n";
print "\@node Top, $tstruct_next{'Top'}, (dir), (dir)\n";
print "\@top\n";
print "\@top Netwide Assembler\n";
print "\n";
print "\@ifinfo\n";
print "This file documents NASM, the Netwide Assembler: an assembler\n";
@ -1606,7 +1615,9 @@ sub write_texi {
$title .= $ww unless $ww eq "\001";
}
print "\@node $node, $tstruct_next{$node}, $tstruct_prev{$node},";
print " $tstruct_up{$node}\n\@unnumbered $title\n";
print " $tstruct_up{$node}\n";
$hdr = ($ptype eq "subh" ? "\@unnumberedsubsec" : "\@unnumberedsec");
print "$hdr $title\n";
} elsif ($ptype eq "code") {
# Code paragraph. Surround with @example / @end example.
print "\@example\n";

287
insns.dat
View File

@ -291,6 +291,7 @@ FDIVRP fpureg,fpu0 \1\xDE\10\xF0 8086,FPU
FEMMS void \2\x0F\x0E PENT,3DNOW
FENI void \3\x9B\xDB\xE0 8086,FPU
FFREE fpureg \1\xDD\10\xC0 8086,FPU
FFREEP fpureg \1\xDF\10\xC0 P6,FPU,UNDOC
FIADD mem32 \300\1\xDA\200 8086,FPU
FIADD mem16 \300\1\xDE\200 8086,FPU
FICOM mem32 \300\1\xDA\202 8086,FPU
@ -459,8 +460,8 @@ INVLPG mem \300\2\x0F\x01\207 486,PRIV
IRET void \322\1\xCF 8086
IRETD void \321\1\xCF 386
IRETW void \320\1\xCF 8086
JCXZ imm \320\1\xE3\50 8086
JECXZ imm \321\1\xE3\50 386
JCXZ imm \310\1\xE3\50 8086
JECXZ imm \311\1\xE3\50 386
JMP imm|short \1\xEB\50 8086
JMP imm \370\1\xEB\50 8086,ND
JMP imm \322\1\xE9\64 8086
@ -887,9 +888,10 @@ 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
RSDC reg_sreg,mem80 \301\2\x0F\x79\101 486,CYRIX,SMM
RSDC reg_sreg,mem80 \301\2\x0F\x79\110 486,CYRIX,SMM
RSLDT mem80 \300\2\x0F\x7B\200 486,CYRIX,SMM
RSM void \2\x0F\xAA PENT,SMM
RSTS mem80 \300\2\x0F\x7D\200 486,CYRIX,SMM
SAHF void \1\x9E 8086
SAL rm8,unity \300\1\xD0\204 8086,ND
SAL rm8,reg_cl \300\1\xD2\204 8086,ND
@ -1062,6 +1064,7 @@ VERW mem \300\1\x0F\17\205 286,PROT
VERW mem16 \300\1\x0F\17\205 286,PROT
VERW reg16 \300\1\x0F\17\205 286,PROT
WAIT void \1\x9B 8086
FWAIT void \1\x9B 8086
WBINVD void \2\x0F\x09 486,PRIV
WRSHR void \2\x0F\x37 P6,CYRIX,SMM
WRMSR void \2\x0F\x30 PENT,PRIV
@ -1143,7 +1146,7 @@ ANDPS xmmreg,mem \301\2\x0F\x54\110 KATMAI,S
ANDPS xmmreg,xmmreg \2\x0F\x54\110 KATMAI,SSE
CMPEQPS xmmreg,mem \301\331\2\x0F\xC2\110\1\x00 KATMAI,SSE
CMPEQPS xmmreg,xmmreg \331\2\x0F\xC2\110\1\x00 KATMAI,SSE
CMPEQSS xmmreg,mem \301\333\2\x0F\xC2\110\1\0x00 KATMAI,SSE
CMPEQSS xmmreg,mem \301\333\2\x0F\xC2\110\1\x00 KATMAI,SSE
CMPEQSS xmmreg,xmmreg \333\2\x0F\xC2\110\1\x00 KATMAI,SSE
CMPLEPS xmmreg,mem \301\331\2\x0F\xC2\110\1\x02 KATMAI,SSE
CMPLEPS xmmreg,xmmreg \331\2\x0F\xC2\110\1\x02 KATMAI,SSE
@ -1303,3 +1306,279 @@ PSADBW mmxreg,mmxreg \2\x0F\xF6\110 KATMAI,MMX
PSADBW mmxreg,mem \301\2\x0F\xF6\110 KATMAI,MMX,SM
PSHUFW mmxreg,mmxreg,imm \2\x0F\x70\110\22 KATMAI,MMX,SB,AR2
PSHUFW mmxreg,mem,imm \301\2\x0F\x70\110\22 KATMAI,MMX,SM2,SB,AR2
; The five new Athlon instructions
PF2IW mmxreg,mem \301\2\x0F\x0F\110\01\x1C PENT,3DNOW,SM
PF2IW mmxreg,mmxreg \2\x0F\x0F\110\01\x1C PENT,3DNOW
PFNACC mmxreg,mem \301\2\x0F\x0F\110\01\x8A PENT,3DNOW,SM
PFNACC mmxreg,mmxreg \2\x0F\x0F\110\01\x8A PENT,3DNOW
PFPNACC mmxreg,mem \301\2\x0F\x0F\110\01\x8E PENT,3DNOW,SM
PFPNACC mmxreg,mmxreg \2\x0F\x0F\110\01\x8E PENT,3DNOW
PI2FW mmxreg,mem \301\2\x0F\x0F\110\01\x0C PENT,3DNOW,SM
PI2FW mmxreg,mmxreg \2\x0F\x0F\110\01\x0C PENT,3DNOW
PSWAPD mmxreg,mem \301\2\x0F\x0F\110\01\xBB PENT,3DNOW,SM
PSWAPD mmxreg,mmxreg \2\x0F\x0F\110\01\xBB PENT,3DNOW
; Introduced in Willamette
; opcode parameters assembly range
MASKMOVDQU xmmreg,xmmreg \3\x66\x0F\xF7 WILLAMETTE
CLFLUSH mem \2\x0F\xAE WILLAMETTE
MOVNTDQ xmmreg,mem \3\x66\x0F\xEF WILLAMETTE
MOVNTI reg32,mem \2\x0F\xC3 WILLAMETTE
PAUSE void \2\xF3\x90 WILLAMETTE
LFENCE void \3\x0F\xAE\xF8 WILLAMETTE
MFENCE void \3\x0F\xAE\xF8 WILLAMETTE
; Willamette MMX instructions (SSE2)
MOVD xmmreg,reg32 \3\x66\x0F\x6E WILLAMETTE
MOVD reg32,xmmreg \3\x66\x0F\x7E WILLAMETTE
MOVD mem,xmmreg \3\x66\x0F\x7E WILLAMETTE
MOVD xmmreg,mem \3\x66\x0F\x6E WILLAMETTE
MOVDQA xmmreg,reg32 \3\x66\x0F\x6F WILLAMETTE
MOVDQA mem,xmmreg \3\x66\x0F\x7F WILLAMETTE
MOVDQA xmmreg,mem \3\x66\x0F\x6F WILLAMETTE
MOVDQA reg32,xmmreg \3\x66\x0F\x7F WILLAMETTE
MOVDQU xmmreg,reg32 \3\xF3\x0F\x6F WILLAMETTE
MOVDQU mem,xmmreg \3\xF3\x0F\x7F WILLAMETTE
MOVDQU xmmreg,mem \3\xF3\x0F\x6F WILLAMETTE
MOVDQU reg32,xmmreg \3\xF3\x0F\x7F WILLAMETTE
MOVQ2DQ mmxreg,xmmreg \3\xF2\x0F\xD6 WILLAMETTE
PACKSSWB xmmreg,xmmreg \3\x66\x0F\x63 WILLAMETTE
PACKSSWB xmmreg,mem \3\x66\x0F\x63 WILLAMETTE
PACKSSDW xmmreg,xmmreg \3\x66\x0F\x6B WILLAMETTE
PACKSSDW xmmreg,mem \3\x66\x0F\x6B WILLAMETTE
PACKUSWB xmmreg,xmmreg \3\x66\x0F\x67 WILLAMETTE
PACKUSWB xmmreg,mem \3\x66\x0F\x67 WILLAMETTE
PADDQ xmmreg,mmxreg \3\x66\x0F\xD4 WILLAMETTE
PADDQ xmmreg,mem \3\x66\x0F\xD4 WILLAMETTE
PADDD xmmreg,xmmreg \3\x66\x0F\xFE WILLAMETTE
PADDD xmmreg,mem \3\x66\x0F\xFE WILLAMETTE
PADDSB xmmreg,mem \3\x66\x0F\xEC WILLAMETTE
PADDSB xmmreg,xmmreg \3\x66\x0F\xEC WILLAMETTE
PADDSW xmmreg,mem \3\x66\x0F\xED WILLAMETTE
PADDSW xmmreg,xmmreg \3\x66\x0F\xED WILLAMETTE
PADDUSB xmmreg,mem \3\x66\x0F\xDC WILLAMETTE
PADDUSB xmmreg,xmmreg \3\x66\x0F\xDC WILLAMETTE
PADDUSW xmmreg,mem \3\x66\x0F\xDD WILLAMETTE
PADDUSW xmmreg,xmmreg \3\x66\x0F\xDD WILLAMETTE
PAND xmmreg,xmmreg \3\x66\x0F\xDB WILLAMETTE
PAND xmmreg,mem \3\x66\x0F\xDB WILLAMETTE
PANDN xmmreg,xmmreg \3\x66\x0F\xDF WILLAMETTE
PANDN xmmreg,mem \3\x66\x0F\xDF WILLAMETTE
PAVGB xmmreg,xmmreg \3\x66\x0F\xE0 WILLAMETTE
PAVGB xmmreg,mem \3\x66\x0F\xE0 WILLAMETTE
PAVGW xmmreg,xmmreg \3\x66\x0F\xE3 WILLAMETTE
PAVGW xmmreg,mem \3\x66\x0F\xE3 WILLAMETTE
PCMPEQB xmmreg,xmmreg \3\x66\x0F\x74 WILLAMETTE
PCMPEQB xmmreg,mem \3\x66\x0F\x74 WILLAMETTE
PCMPEQW xmmreg,xmmreg \3\x66\x0F\x75 WILLAMETTE
PCMPEQW xmmreg,mem \3\x66\x0F\x75 WILLAMETTE
PCMPEQD xmmreg,xmmreg \3\x66\x0F\x76 WILLAMETTE
PCMPEQD xmmreg,mem \3\x66\x0F\x76 WILLAMETTE
PCMPGTB xmmreg,xmmreg \3\x66\x0F\x64 WILLAMETTE
PCMPGTB xmmreg,mem \3\x66\x0F\x64 WILLAMETTE
PCMPGTW xmmreg,xmmreg \3\x66\x0F\x65 WILLAMETTE
PCMPGTW xmmreg,mem \3\x66\x0F\x65 WILLAMETTE
PCMPGTD xmmreg,xmmreg \3\x66\x0F\x66 WILLAMETTE
PCMPGTD xmmreg,mem \3\x66\x0F\x66 WILLAMETTE
PEXTRW reg32,xmmreg,imm8 \3\x66\x0F\xC5\110\22 WILLAMETTE
PINSRW xmmreg,reg16,imm \3\x66\x0F\xC4\110\22 WILLAMETTE,MMX,SB,AR2
PINSRW xmmreg,reg32,imm \3\x66\x0F\xC4\110\22 WILLAMETTE,MMX,SB,AR2,ND
PINSRW xmmreg,mem,imm \301\3\x66\x0F\xC4\110\22 WILLAMETTE,MMX,SB,AR2
PINSRW xmmreg,mem16,imm \301\3\x66\x0F\xC4\110\22 WILLAMETTE,MMX,SB,AR2,ND
PMAXSW xmmreg,xmmreg \3\x66\x0F\xEE\110 WILLAMETTE,MMX
PMAXSW xmmreg,mem \301\3\x66\x0F\xEE\110 WILLAMETTE,MMX,SM
PMAXUB xmmreg,xmmreg \3\x66\x0F\xDE\110 WILLAMETTE,MMX
PMAXUB xmmreg,mem \301\3\x66\x0F\xDE\110 WILLAMETTE,MMX,SM
PMINSW xmmreg,xmmreg \3\x66\x0F\xEA\110 WILLAMETTE,MMX
PMINSW xmmreg,mem \301\3\x66\x0F\xEA\110 WILLAMETTE,MMX,SM
PMINUB xmmreg,xmmreg \3\x66\x0F\xDA\110 WILLAMETTE,MMX
PMINUB xmmreg,mem \301\3\x66\x0F\xDA\110 WILLAMETTE,MMX,SM
PMOVMSKB reg32,xmmreg \3\x66\x0F\xD7\110 WILLAMETTE,MMX
PMULHUW xmmreg,xmmreg \3\x66\x0F\xE4\110 WILLAMETTE,MMX
PMULHUW xmmreg,mem \301\3\x66\x0F\xE4\110 WILLAMETTE,MMX,SM
PSADBW xmmreg,xmmreg \3\x66\x0F\xF6\110 WILLAMETTE,MMX
PSADBW xmmreg,mem \301\3\x66\x0F\xF6\110 WILLAMETTE,MMX,SM
PSHUFD xmmreg,xmmreg,imm \3\x66\x0F\x70\110\22 WILLAMETTE,MMX,SB,AR2
PSHUFD xmmreg,mem,imm \301\3\x66\x0F\x70\110\22 WILLAMETTE,MMX,SM2,SB,AR2
PMADDWD xmmreg,mem \301\3\x66\x0F\xF5\110 WILLAMETTE,MMX,SM
PMADDWD xmmreg,xmmreg \3\x66\x0F\xF5\110 WILLAMETTE,MMX
PMULLW xmmreg,mem \301\3\x66\x0F\xD5\110 WILLAMETTE,MMX,SM
PMULLW xmmreg,xmmreg \3\x66\x0F\xD5\110 WILLAMETTE,MMX
PMULUDQ mmxreg,mmxreg \2\x0F\xF4 WILLAMETTE
PMULUDQ mmxreg,mem \2\x0F\xF4 WILLAMETTE
PMULUDQ xmmreg,xmmreg \3\x66\x0F\xF4 WILLAMETTE
PMULUDQ xmmreg,mem \3\x66\x0F\xF4 WILLAMETTE
POR xmmreg,mem \301\3\x66\x0F\xEB\110 WILLAMETTE,MMX,SM
POR xmmreg,xmmreg \3\x66\x0F\xEB\110 WILLAMETTE,MMX
PSHUFLW xmmreg,xmmreg,imm8 \3\xF2\x0F\x70 WILLAMETTE
PSHUFLW xmmreg,mem,imm8 \3\xF2\x0F\x70 WILLAMETTE
PSHUFHW xmmreg,xmmreg,imm8 \3\xF3\x0F\x70 WILLAMETTE
PSHUFHW xmmreg,mem,imm8 \3\xF3\x0F\x70 WILLAMETTE
PSLLDQ xmmreg,imm8 \3\x66\x0F\x73 WILLAMETTE
PSLLD xmmreg,mem \301\3\x66\x0F\xF2\110 WILLAMETTE,MMX,SM
PSLLD xmmreg,xmmreg \3\x66\x0F\xF2\110 WILLAMETTE,MMX
PSLLD xmmreg,imm \3\x66\x0F\x72\206\25 WILLAMETTE,MMX
PSLLQ xmmreg,mem \301\3\x66\x0F\xF3\110 WILLAMETTE,MMX,SM
PSLLQ xmmreg,xmmreg \3\x66\x0F\xF3\110 WILLAMETTE,MMX
PSLLQ xmmreg,imm \3\x66\x0F\x73\206\25 WILLAMETTE,MMX
PSLLW xmmreg,mem \301\3\x66\x0F\xF1\110 WILLAMETTE,MMX,SM
PSLLW xmmreg,xmmreg \3\x66\x0F\xF1\110 WILLAMETTE,MMX
PSLLW xmmreg,imm \3\x66\x0F\x71\206\25 WILLAMETTE,MMX
PSRAD xmmreg,mem \301\3\x66\x0F\xE2\110 WILLAMETTE,MMX,SM
PSRAD xmmreg,xmmreg \3\x66\x0F\xE2\110 WILLAMETTE,MMX
PSRAD xmmreg,imm \3\x66\x0F\x72\204\25 WILLAMETTE,MMX
PSRAW xmmreg,mem \301\3\x66\x0F\xE1\110 WILLAMETTE,MMX,SM
PSRAW xmmreg,xmmreg \3\x66\x0F\xE1\110 WILLAMETTE,MMX
PSRAW xmmreg,imm \3\x66\x0F\x71\204\25 WILLAMETTE,MMX
PSRLW xmmreg,imm \3\x66\x0F\x73\202\25 WILLAMETTE,MMX
PSRLD xmmreg,mem \301\3\x66\x0F\xD2\110 WILLAMETTE,MMX,SM
PSRLD xmmreg,xmmreg \3\x66\x0F\xD2\110 WILLAMETTE,MMX
PSRLD xmmreg,imm \3\x66\x0F\x72\202\25 WILLAMETTE,MMX
PSRLQ xmmreg,mem \301\3\x66\x0F\xD3\110 WILLAMETTE,MMX,SM
PSRLQ xmmreg,xmmreg \3\x66\x0F\xD3\110 WILLAMETTE,MMX
PSRLQ xmmreg,imm \3\x66\x0F\x73\202\25 WILLAMETTE,MMX
PSRLW xmmreg,mem \301\3\x66\x0F\xD1\110 WILLAMETTE,MMX,SM
PSRLW xmmreg,xmmreg \3\x66\x0F\xD1\110 WILLAMETTE,MMX
PSRLW xmmreg,imm \3\x66\x0F\x71\202\25 WILLAMETTE,MMX
PSUBQ mmxreg,mmxreg \2\x0F\xFB WILLAMETTE
PSUBQ mmxreg,mem \2\x0F\xFB WILLAMETTE
PSUBQ xmmreg,xmmreg \3\x66\x0F\xFB WILLAMETTE
PSUBQ xmmreg,mem \3\x66\x0F\xFB WILLAMETTE
PSUBB xmmreg,mem \301\3\x66\x0F\xF8\110 WILLAMETTE,MMX,SM
PSUBB xmmreg,xmmreg \3\x66\x0F\xF8\110 WILLAMETTE,MMX
PSUBD xmmreg,mem \301\3\x66\x0F\xFA\110 WILLAMETTE,MMX,SM
PSUBD xmmreg,xmmreg \3\x66\x0F\xFA\110 WILLAMETTE,MMX
PSUBSB xmmreg,mem \301\3\x66\x0F\xE8\110 WILLAMETTE,MMX,SM
PSUBSB xmmreg,xmmreg \3\x66\x0F\xE8\110 WILLAMETTE,MMX
PSUBSW xmmreg,mem \301\3\x66\x0F\xE9\110 WILLAMETTE,MMX,SM
PSUBSW xmmreg,xmmreg \3\x66\x0F\xE9\110 WILLAMETTE,MMX
PSUBUSB xmmreg,mem \301\3\x66\x0F\xD8\110 WILLAMETTE,MMX,SM
PSUBUSB xmmreg,xmmreg \3\x66\x0F\xD8\110 WILLAMETTE,MMX
PSUBUSW xmmreg,mem \301\3\x66\x0F\xD9\110 WILLAMETTE,MMX,SM
PSUBUSW xmmreg,xmmreg \3\x66\x0F\xD9\110 WILLAMETTE,MMX
PSUBW xmmreg,mem \301\3\x66\x0F\xF9\110 WILLAMETTE,MMX,SM
PSUBW xmmreg,xmmreg \3\x66\x0F\xF9\110 WILLAMETTE,MMX
PUNPCKHBW xmmreg,mem \301\3\x66\x0F\x68\110 WILLAMETTE,MMX,SM
PUNPCKHBW xmmreg,xmmreg \3\x66\x0F\x68\110 WILLAMETTE,MMX
PUNPCKHDQ xmmreg,mem \301\3\x66\x0F\x6A\110 WILLAMETTE,MMX,SM
PUNPCKHDQ xmmreg,xmmreg \3\x66\x0F\x6A\110 WILLAMETTE,MMX
PUNPCKHWD xmmreg,mem \301\3\x66\x0F\x69\110 WILLAMETTE,MMX,SM
PUNPCKHWD xmmreg,xmmreg \3\x66\x0F\x69\110 WILLAMETTE,MMX
PUNPCKLBW xmmreg,mem \301\3\x66\x0F\x60\110 WILLAMETTE,MMX,SM
PUNPCKLBW xmmreg,xmmreg \3\x66\x0F\x60\110 WILLAMETTE,MMX
PUNPCKLDQ xmmreg,mem \301\3\x66\x0F\x62\110 WILLAMETTE,MMX,SM
PUNPCKLDQ xmmreg,xmmreg \3\x66\x0F\x62\110 WILLAMETTE,MMX
PUNPCKLWD xmmreg,mem \301\3\x66\x0F\x61\110 WILLAMETTE,MMX,SM
PUNPCKLWD xmmreg,xmmreg \3\x66\x0F\x61\110 WILLAMETTE,MMX
PUNPCKLQDQ xmmreg,xmmreg \3\x66\x0F\x6C\110 WILLAMETTE
PUNPCKLQDQ xmmreg,mem \301\3\x66\x0F\x6C\110 WILLAMETTE
PUNPCKHQDQ xmmreg,xmmreg \3\x66\x0F\x6D\110 WILLAMETTE
PUNPCKHQDQ xmmreg,mem \301\3\x66\x0F\x6D\110 WILLAMETTE
PXOR xmmreg,mem \301\3\x66\x0F\xEF\110 WILLAMETTE,MMX,SM
PXOR xmmreg,xmmreg \3\x66\x0F\xEF\110 WILLAMETTE,MMX
; Willamette Streaming SIMD instructions (SSE2)
; opcode parameters assembly range
ADDPD xmmreg,xmmreg \3\x66\x0F\x58 WILLAMETTE,SSE2
ADDPD mem,xmmreg \3\x66\x0F\x58 WILLAMETTE,SSE2
ADDSD xmmreg,xmmreg \3\xF2\x0F\x58 WILLAMETTE,SSE2
ADDSD mem,xmmreg \3\xF2\x0F\x58 WILLAMETTE,SSE2
ANDNPD xmmreg,xmmreg \3\x66\x0F\x54 WILLAMETTE,SSE2
ANDNPD mem,xmmreg \3\x66\x0F\x54 WILLAMETTE,SSE2
ANDDPD xmmreg,xmmreg \3\x66\x0F\x55 WILLAMETTE,SSE2
ANDDPD mem,xmmreg \3\x66\x0F\x55 WILLAMETTE,SSE2
CMPPD xmmreg,xmmreg,imm8 \3\x66\x0F\xC2 WILLAMETTE,SSE2
CMPPD mem,xmmreg,imm8 \3\x66\x0F\xC2 WILLAMETTE,SSE2
CMPSD xmmreg,xmmreg,imm8 \1\xA7 WILLAMETTE,SSE2
CMPSD mem,xmmreg,imm8 \1\xA7 WILLAMETTE,SSE2
COMISD xmmreg,xmmreg \3\x66\x0F\x2F WILLAMETTE,SSE2
COMISD mem,xmmreg \3\x66\x0F\x2F WILLAMETTE,SSE2
CVTPI2PD mmxreg,xmmreg \3\x66\x0F\x2A WILLAMETTE,SSE2
CVTPI2PD mem,xmmreg \3\x66\x0F\x2A WILLAMETTE,SSE2
CVTPD2PI xmmreg,mmxreg \3\x66\x0F\x2C WILLAMETTE,SSE2
CVTPD2PI mem,mmxreg \3\x66\x0F\x2C WILLAMETTE,SSE2
CVTSI2SD reg32,xmmreg \3\xF2\x0F\x2A WILLAMETTE,SSE2
CVTSI2SD mem,xmmreg \3\xF2\x0F\x2A WILLAMETTE,SSE2
CVTSD2SI xmmreg,reg32 \3\xF2\x0F\x2D WILLAMETTE,SSE2
CVTSD2SI mem,reg32 \3\xF2\x0F\x2D WILLAMETTE,SSE2
CVTPD2PS xmmreg,xmmreg \2\x0F\x2A WILLAMETTE,SSE2
CVTPD2PS mem,xmmreg \2\x0F\x2A WILLAMETTE,SSE2
CVTPS2PD xmmreg,xmmreg \2\x0F\x5A WILLAMETTE,SSE2
CVTPS2PD mem,xmmreg \2\x0F\x5A WILLAMETTE,SSE2
CVTSD2SS xmmreg,xmmreg \3\xF2\x0F\x5A WILLAMETTE,SSE2
CVTSD2SS mem,xmmreg \3\xF2\x0F\x5A WILLAMETTE,SSE2
CVTSS2SD xmmreg,xmmreg \3\xF3\x0F\x5A WILLAMETTE,SSE2
CVTSS2SD mem,xmmreg \3\xF3\x0F\x5A WILLAMETTE,SSE2
CVTPD2DQ xmmreg,xmmreg \3\xF2\x0F\xE6 WILLAMETTE,SSE2
CVTPD2DQ mem,xmmreg \3\xF2\x0F\xE6 WILLAMETTE,SSE2
CVTDQ2PD xmmreg,xmmreg \3\xF3\x0F\xE6 WILLAMETTE,SSE2
CVTDQ2PD mem,xmmreg \3\xF3\x0F\xE6 WILLAMETTE,SSE2
CVTDQ2PS xmmreg,xmmreg \2\x0F\x5B WILLAMETTE,SSE2
CVTDQ2PS mem,xmmreg \2\x0F\x5B WILLAMETTE,SSE2
CVTPS2DQ xmmreg,xmmreg \3\x66\x0F\x5B WILLAMETTE,SSE2
CVTPS2DQ mem,xmmreg \3\x66\x0F\x5B WILLAMETTE,SSE2
CVTTPD2PI mmxreg,xmmreg \3\x66\x0F\x2C WILLAMETTE,SSE2
CVTTPD2PI mem,xmmreg \3\x66\x0F\x2C WILLAMETTE,SSE2
CVTTPD2DQ mmxreg,xmmreg \3\x66\x0F\xE6 WILLAMETTE,SSE2
CVTTPD2DQ mem,xmmreg \3\x66\x0F\xE6 WILLAMETTE,SSE2
CVTTPS2DQ mmxreg,xmmreg \3\xF3\x0F\x5B WILLAMETTE,SSE2
CVTTPS2DQ mem,xmmreg \3\xF3\x0F\x5B WILLAMETTE,SSE2
CVTTPS2PI mmxreg,xmmreg \3\x0F\x2C WILLAMETTE,SSE2
CVTTPS2PI mem,xmmreg \3\x0F\x2C WILLAMETTE,SSE2
CVTTSD2SI mmxreg,xmmreg \3\xF2\x0F\x2C WILLAMETTE,SSE2
CVTTSD2SI mem,xmmreg \3\xF2\x0F\x2C WILLAMETTE,SSE2
CVTTSS2SI mmxreg,xmmreg \3\xF3\x0F\x2C WILLAMETTE,SSE2
CVTTSS2SI mem,xmmreg \3\xF3\x0F\x2C WILLAMETTE,SSE2
DIVPD xmmreg,xmmreg \3\x66\x0F\x5E WILLAMETTE,SSE2
DIVPD mem,xmmreg \3\x66\x0F\x5E WILLAMETTE,SSE2
DIVSD xmmreg,xmmreg \3\xF2\x0F\x5E WILLAMETTE,SSE2
DIVSD mem,xmmreg \3\xF2\x0F\x5E WILLAMETTE,SSE2
MAXPD xmmreg,xmmreg \3\x66\x0F\x5F WILLAMETTE,SSE2
MAXPD mem,xmmreg \3\x66\x0F\x5F WILLAMETTE,SSE2
MAXSD xmmreg,xmmreg \3\xF2\x0F\x5F WILLAMETTE,SSE2
MAXSD mem,xmmreg \3\xF2\x0F\x5F WILLAMETTE,SSE2
MINPD xmmreg,xmmreg \3\x66\x0F\x5D WILLAMETTE,SSE2
MINPD mem,xmmreg \3\x66\x0F\x5D WILLAMETTE,SSE2
MINSD xmmreg,xmmreg \3\xF2\x0F\x5D WILLAMETTE,SSE2
MINSD mem,xmmreg \3\xF2\x0F\x5D WILLAMETTE,SSE2
MOVAPD xmmreg,xmmreg \3\x66\x0F\x28 WILLAMETTE,SSE2
MOVAPD xmmreg,xmmreg \3\x66\x0F\x29 WILLAMETTE,SSE2
MOVAPD mem,xmmreg \3\x66\x0F\x29 WILLAMETTE,SSE2
MOVAPD xmmreg,mem \3\x66\x0F\x28 WILLAMETTE,SSE2
MOVHPD mem,xmmreg \3\x66\x0F\x17 WILLAMETTE,SSE2
MOVHPD xmmreg,xmmreg \3\x66\x0F\x16 WILLAMETTE,SSE2
MOVLPD mem,xmmreg \3\x66\x0F\x13 WILLAMETTE,SSE2
MOVLPD xmmreg,xmmreg \3\x66\x0F\x12 WILLAMETTE,SSE2
MOVMSKPD xmmreg,reg32 \3\x66\x0F\x50 WILLAMETTE,SSE2
MOVSD xmmreg,xmmreg \3\xF2\x0F\x10 WILLAMETTE,SSE2
MOVSD xmmreg,xmmreg \3\xF2\x0F\x11 WILLAMETTE,SSE2
MOVSD mem,xmmreg \3\xF2\x0F\x11 WILLAMETTE,SSE2
MOVSD xmmreg,mem \3\xF2\x0F\x10 WILLAMETTE,SSE2
MOVUPD xmmreg,xmmreg \3\x66\x0F\x10 WILLAMETTE,SSE2
MOVUPD xmmreg,xmmreg \3\x66\x0F\x11 WILLAMETTE,SSE2
MOVUPD mem,xmmreg \3\x66\x0F\x11 WILLAMETTE,SSE2
MOVUPD xmmreg,mem \3\x66\x0F\x10 WILLAMETTE,SSE2
MULPD xmmreg,xmmreg \3\x66\x0F\x59 WILLAMETTE,SSE2
MULPD mem,xmmreg \3\x66\x0F\x59 WILLAMETTE,SSE2
MULSD xmmreg,xmmreg \3\xF2\x0F\x59 WILLAMETTE,SSE2
MULSD mem,xmmreg \3\xF2\x0F\x59 WILLAMETTE,SSE2
ORPD mem,xmmreg \3\x66\x0F\x56 WILLAMETTE,SSE2
ORPD xmmreg,xmmreg,imm8 \3\x66\x0F\x56 WILLAMETTE,SSE2
SHUFPD xmmreg,xmmreg,imm8 \3\x66\x0F\xC6 WILLAMETTE,SSE2
SHUFPD mem,xmmreg \3\x66\x0F\xC6 WILLAMETTE,SSE2
SQRTPD xmmreg,xmmreg \3\x66\x0F\x51 WILLAMETTE,SSE2
SQRTPD mem,xmmreg \3\x66\x0F\x51 WILLAMETTE,SSE2
SQRTSD xmmreg,xmmreg \3\xF2\x0F\x51 WILLAMETTE,SSE2
SQRTSD mem,xmmreg \3\xF2\x0F\x51 WILLAMETTE,SSE2
SUBPD xmmreg,xmmreg \3\x66\x0F\x5C WILLAMETTE,SSE2
SUBPD mem,xmmreg \3\x66\x0F\x5C WILLAMETTE,SSE2
SUBSD xmmreg,xmmreg \3\xF2\x0F\x5C WILLAMETTE,SSE2
SUBSD mem,xmmreg \3\xF2\x0F\x5C WILLAMETTE,SSE2
UCOMISD xmmreg,xmmreg \3\x66\x0F\x2E WILLAMETTE,SSE2
UCOMISD mem,xmmreg \3\x66\x0F\x2E WILLAMETTE,SSE2
UNPCKHPD xmmreg,xmmreg \3\x66\x0F\x15 WILLAMETTE,SSE2
UNPCKHPD mem,xmmreg \3\x66\x0F\x15 WILLAMETTE,SSE2
UNPCKLPD xmmreg,xmmreg \3\x66\x0F\x14 WILLAMETTE,SSE2
UNPCKLPD mem,xmmreg \3\x66\x0F\x14 WILLAMETTE,SSE2
XORPD xmmreg,xmmreg \3\x66\x0F\x57 WILLAMETTE,SSE2
XORPD mem,xmmreg \3\x66\x0F\x57 WILLAMETTE,SSE2

View File

@ -62,6 +62,7 @@ struct itemplate {
#define IF_MMX 0x00004000UL /* it's an MMX instruction */
#define IF_3DNOW 0x00008000UL /* it's a 3DNow! instruction */
#define IF_SSE 0x00010000UL /* it's a SSE (KNI, MMX2) instruction */
#define IF_SSE2 0x00020000UL /* it's a SSE2 instruction */
#define IF_PMASK 0xFF000000UL /* the mask for processor types */
#define IF_PLEVEL 0x0F000000UL /* the mask for processor instr. level */
/* also the highest possible processor */
@ -74,6 +75,7 @@ struct itemplate {
#define IF_PENT 0x05000000UL /* Pentium instruction */
#define IF_P6 0x06000000UL /* P6 instruction */
#define IF_KATMAI 0x07000000UL /* Katmai instructions */
#define IF_WILLAMETTE 0x08000000UL /* Willamette instructions */
#define IF_CYRIX 0x10000000UL /* Cyrix-specific instruction */
#define IF_AMD 0x20000000UL /* AMD-specific instruction */

108
labels.c
View File

@ -15,8 +15,24 @@
/*
* A local label is one that begins with exactly one period. Things
* that begin with _two_ periods are NASM-specific things.
*
* If TASM compatibility is enabled, a local label can also begin with
* @@, so @@local is a TASM compatible local label. Note that we only
* check for the first @ symbol, although TASM requires both.
*/
#ifdef TASM_COMPAT
#define islocal(l) \
(tasm_compatible_mode ? \
(((l)[0] == '.' || (l)[0] == '@') && (l)[1] != '.') : \
((l)[0] == '.' && (l)[1] != '.'))
#define islocalchar(c) \
(tasm_compatible_mode ? \
((c) == '.' || (c) == '@') : \
((c) == '.'))
#else
#define islocal(l) ((l)[0] == '.' && (l)[1] != '.')
#define islocalchar(c) ((c) == '.')
#endif
#define LABEL_BLOCK 32 /* no. of labels/block */
#define LBLK_SIZE (LABEL_BLOCK*sizeof(union label))
@ -71,6 +87,9 @@ static char *prevlabel;
static int initialised = FALSE;
char lprefix[PREFIX_MAX] = {0};
char lpostfix[PREFIX_MAX] = {0};
/*
* Internal routine: finds the `union label' corresponding to the
* given label name. Creates a new one, if it isn't found, and if
@ -160,7 +179,8 @@ void redefine_label (char *label, long segment, long offset, char *special,
int is_norm, int isextrn, struct ofmt *ofmt, efunc error)
{
union label *lptr;
int exi;
/* 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
@ -185,18 +205,50 @@ void redefine_label (char *label, long segment, long offset, char *special,
error (ERR_PANIC, "can't find label `%s' on pass two", label);
if (!islocal(label)) {
if (*label != '.' && lptr->defn.is_norm)
if (!islocalchar(*label) && lptr->defn.is_norm)
prevlabel = lptr->defn.label;
}
global_offset_changed |= (lptr->defn.offset != offset);
lptr->defn.offset = offset;
if (pass0 == 1) {
exi = !!(lptr->defn.is_global & GLOBAL_BIT);
if (exi)
{
char *xsymbol;
int slen;
slen = strlen(lprefix);
slen += strlen(lptr->defn.label);
slen += strlen(lpostfix);
slen++; /* room for that null char */
xsymbol = nasm_malloc(slen);
sprintf(xsymbol,"%s%s%s",lprefix,lptr->defn.label,lpostfix);
ofmt->symdef (xsymbol, segment, offset, exi,
special ? special : lptr->defn.special);
ofmt->current_dfmt->debug_deflabel (xsymbol, segment, offset, exi,
special ? special : lptr->defn.special);
/** nasm_free(xsymbol); ! outobj.c stores the pointer; ouch!!! **/
}
else
{
if ( (lptr->defn.is_global & (GLOBAL_BIT|EXTERN_BIT)) != EXTERN_BIT ) {
ofmt->symdef (lptr->defn.label, segment, offset, exi,
special ? special : lptr->defn.special);
ofmt->current_dfmt->debug_deflabel (label, segment, offset, exi,
special ? special : lptr->defn.special);
}
}
} /* if (pass0 == 1) */
}
void define_label (char *label, long segment, long offset, char *special,
int is_norm, int isextrn, struct ofmt *ofmt, efunc error)
{
union label *lptr;
int exi;
#ifdef DEBUG
#if DEBUG<3
@ -212,26 +264,48 @@ void define_label (char *label, long segment, long offset, char *special,
}
lptr->defn.is_global |= DEFINED_BIT;
if (isextrn)
lptr->defn.is_global |= EXTERN_BIT;
lptr->defn.is_global |= EXTERN_BIT;
if (label[0] != '.' && is_norm) /* not local, but not special either */
prevlabel = lptr->defn.label;
else if (label[0] == '.' && label[1] != '.' && !*prevlabel)
error(ERR_NONFATAL, "attempt to define a local label before any"
" non-local labels");
if (!islocalchar(label[0]) && is_norm) /* not local, but not special either */
prevlabel = lptr->defn.label;
else if (islocal(label) && !*prevlabel) {
error(ERR_NONFATAL, "attempt to define a local label before any"
" non-local labels");
}
lptr->defn.segment = segment;
lptr->defn.offset = offset;
lptr->defn.is_norm = (label[0] != '.' && is_norm);
lptr->defn.is_norm = (!islocalchar(label[0]) && is_norm);
if ( (lptr->defn.is_global & (GLOBAL_BIT|EXTERN_BIT)) != EXTERN_BIT ) {
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);
if (pass0 == 1 || (!is_norm && !isextrn && (segment&1))) {
exi = !!(lptr->defn.is_global & GLOBAL_BIT);
if (exi)
{
char *xsymbol;
int slen;
slen = strlen(lprefix);
slen += strlen(lptr->defn.label);
slen += strlen(lpostfix);
slen++; /* room for that null char */
xsymbol = nasm_malloc(slen);
sprintf(xsymbol,"%s%s%s",lprefix,lptr->defn.label,lpostfix);
ofmt->symdef (xsymbol, segment, offset, exi,
special ? special : lptr->defn.special);
ofmt->current_dfmt->debug_deflabel (xsymbol, segment, offset, exi,
special ? special : lptr->defn.special);
/** nasm_free(xsymbol); ! outobj.c stores the pointer; ouch!!! **/
}
else
{
if ( (lptr->defn.is_global & (GLOBAL_BIT|EXTERN_BIT)) != EXTERN_BIT ) {
ofmt->symdef (lptr->defn.label, segment, offset, exi,
special ? special : lptr->defn.special);
ofmt->current_dfmt->debug_deflabel (label, segment, offset, exi,
special ? special : lptr->defn.special);
}
}
} /* if (pass0 == 1) */
}
void define_common (char *label, long segment, long size, char *special,
@ -246,7 +320,7 @@ void define_common (char *label, long segment, long size, char *special,
}
lptr->defn.is_global |= DEFINED_BIT;
if (label[0] != '.') /* not local, but not special either */
if (!islocalchar(label[0])) /* not local, but not special either */
prevlabel = lptr->defn.label;
else
error(ERR_NONFATAL, "attempt to define a local label as a "

View File

@ -6,6 +6,9 @@
* distributed in the NASM archive.
*/
extern char lprefix[PREFIX_MAX];
extern char lpostfix[PREFIX_MAX];
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,

View File

@ -124,7 +124,7 @@ static void list_output (long offset, void *data, unsigned long type)
{
long typ, size;
if (!listp || suppress)
if (!listp || suppress || user_nolist) /* fbk - 9/2/00 */
return;
typ = type & OUT_TYPMASK;
@ -201,6 +201,10 @@ static void list_line (int type, char *line)
{
if (!listp)
return;
if (user_nolist){ /* fbk - 9/2/00 */
listlineno++;
return;
}
if (mistack && mistack->inhibiting)
{

View File

@ -10,5 +10,6 @@
#define NASM_LISTING_H
extern ListGen nasmlist;
extern int user_nolist; /* fbk - 9/1/00 */
#endif

View File

@ -57,12 +57,6 @@ static char *stdmac[] = {
"%imacro bits 1+.nolist",
"[bits %1]",
"%endmacro",
"%imacro use16 0.nolist",
"[bits 16]",
"%endmacro",
"%imacro use32 0.nolist",
"[bits 32]",
"%endmacro",
"%imacro global 1-*.nolist",
"%rep %0",
"[global %1]",
@ -75,8 +69,5 @@ static char *stdmac[] = {
"%rotate 1",
"%endrep",
"%endmacro",
"%imacro cpu 1+.nolist",
"[cpu %1]",
"%endmacro",
NULL
};

285
nasm.c
View File

@ -38,18 +38,21 @@ static void register_output_formats(void);
static void usage(void);
static int using_debug_info;
#ifdef TASM_COMPAT
int tasm_compatible_mode = FALSE;
#endif
static char inname[FILENAME_MAX];
static char outname[FILENAME_MAX];
static char listname[FILENAME_MAX];
static int globallineno; /* for forward-reference tracking */
static int pass = 0;
/* static int pass = 0; */
static struct ofmt *ofmt = NULL;
static FILE *error_file; /* Where to write error messages */
static FILE *ofile = NULL;
static int optimizing = 10; /* number of optimization passes to take */
static int optimizing = 0; /* number of optimization passes to take */
static int sb, cmd_sb = 16; /* by default */
static unsigned long cmd_cpu = IF_PLEVEL; /* highest level by default */
static unsigned long cpu = IF_PLEVEL; /* passed to insn_size & assemble.c */
@ -73,8 +76,6 @@ enum op_type {
};
static enum op_type operating_mode;
/* used by error function to report location */
/*
* Which of the suppressible warnings are suppressed. Entry zero
* doesn't do anything. Initial defaults are given here.
@ -128,6 +129,7 @@ static Preproc no_pp = {
static int want_usage;
static int terminate_after_phase;
int user_nolist = 0; /* fbk 9/2/00 */
static void nasm_fputs(char *line, FILE *ofile)
{
@ -140,6 +142,7 @@ static void nasm_fputs(char *line, FILE *ofile)
int main(int argc, char **argv)
{
pass0 = 1;
want_usage = terminate_after_phase = FALSE;
nasm_set_malloc_error (report_error);
@ -184,7 +187,7 @@ int main(int argc, char **argv)
if (outname[0] == '\0')
ofmt->filename (inname, outname, report_error);
ofile = NULL;
printf("%s: %s", outname, inname);
fprintf(stdout, "%s: %s", outname, inname);
while ( (line = preproc->getline()) )
nasm_free (line);
preproc->cleanup();
@ -209,7 +212,7 @@ int main(int argc, char **argv)
location.known = FALSE;
pass = 1;
/* pass = 1; */
preproc->reset (inname, 2, report_error, evaluate, &nasmlist);
while ( (line = preproc->getline()) ) {
/*
@ -326,6 +329,22 @@ static char *get_param (char *p, char *q, int *advance)
return NULL;
}
struct textargs
{
char *label;
int value;
};
#define OPT_PREFIX 0
#define OPT_POSTFIX 1
struct textargs textopts[] =
{
{"prefix",OPT_PREFIX},
{"postfix",OPT_POSTFIX},
{NULL,0}
};
int stopoptions = 0;
static int process_arg (char *p, char *q)
{
@ -338,9 +357,6 @@ static int process_arg (char *p, char *q)
if (p[0]=='-' && ! stopoptions)
{
switch (p[1]) {
case '-': /* -- => stop processing options */
stopoptions = 1;
break;
case 's':
error_file = stdout;
break;
@ -370,7 +386,7 @@ static int process_arg (char *p, char *q)
ofmt->current_dfmt = ofmt->debug_formats[0];
} else if (p[1]=='O') { /* Optimization level */
if (!isdigit(*param)) report_error(ERR_FATAL,
"command line optimization level must be 0..3");
"command line optimization level must be 0..3 or <nn>");
optimizing = atoi(param);
if (optimizing <= 0) optimizing = 0;
else if (optimizing <= 3) optimizing *= 5; /* 5 passes for each level */
@ -385,7 +401,7 @@ static int process_arg (char *p, char *q)
} else if (p[1]=='l') { /* listing file */
strcpy (listname, param);
} else if (p[1]=='E') { /* error messages file */
error_file = fopen(param, "wt");
error_file = fopen(param, "w");
if ( !error_file ) {
error_file = stderr; /* Revert to default! */
report_error (ERR_FATAL | ERR_NOFILE | ERR_USAGE,
@ -410,6 +426,10 @@ static int process_arg (char *p, char *q)
"[-l listfile]\n"
" [options...] [--] filename\n"
" or nasm -r for version info\n\n"
#ifdef TASM_COMPAT
" -t Assemble in SciTech TASM compatible mode\n"
" -g Generate debug information in selected format.\n"
#endif
" -e preprocess only (writes output to stdout by default)\n"
" -a don't preprocess (assemble only)\n"
" -M generate Makefile dependencies on stdout\n\n"
@ -448,8 +468,17 @@ static int process_arg (char *p, char *q)
dfmt_list(ofmt, stdout);
exit(0);
break;
#ifdef TASM_COMPAT
case 't':
tasm_compatible_mode = TRUE;
break;
#endif
case 'r':
#ifdef TASM_COMPAT
printf("NASM version %s - SciTech TASM compatible additions\n", NASM_VER);
#else
printf("NASM version %s\n", NASM_VER);
#endif
#ifdef DEBUG
printf("Compiled with -DDEBUG on " __DATE__ "\n");
#endif
@ -479,6 +508,66 @@ static int process_arg (char *p, char *q)
case 'M':
operating_mode = op_depend;
break;
case '-':
{
int s;
if (p[2]==0) { /* -- => stop processing options */
stopoptions = 1;
break;
}
for(s=0; textopts[s].label; s++)
{
if(!nasm_stricmp(p+2, textopts[s].label))
{
break;
}
}
switch(s)
{
case OPT_PREFIX:
case OPT_POSTFIX:
{
if (!q)
{
report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
"option `--%s' requires an argument",
p+2);
break;
}
else
{
advance = 1, param = q;
}
if(s == OPT_PREFIX)
{
strncpy(lprefix,param,PREFIX_MAX-1);
lprefix[PREFIX_MAX-1]=0;
break;
}
if(s == OPT_POSTFIX)
{
strncpy(lpostfix,param,POSTFIX_MAX-1);
lpostfix[POSTFIX_MAX-1]=0;
break;
}
break;
}
default:
{
report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
"unrecognised option `--%s'",
p+2);
break;
}
}
break;
}
default:
if (!ofmt->setinfo(GI_SWITCH,&p))
report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
@ -562,11 +651,41 @@ static void process_respfile (FILE *rfile)
}
}
/* Function to process args from a string of args, rather than the
* argv array. Used by the environment variable and response file
* processing.
*/
#ifdef TASM_COMPAT
static void process_args (char *args) {
char *p, *q, *arg, *prevarg;
char separator = ' ';
p = args;
if (*p && *p != '-')
separator = *p++;
arg = NULL;
while (*p) {
q = p;
while (*p && *p != separator) p++;
while (*p == separator) *p++ = '\0';
prevarg = arg;
arg = q;
if (process_arg (prevarg, arg))
arg = NULL;
}
if (arg)
process_arg (arg, NULL);
}
#endif
static void parse_cmdline(int argc, char **argv)
{
FILE *rfile;
char *envreal, *envcopy=NULL, *p, *q, *arg, *prevarg;
char *envreal, *envcopy=NULL, *p, *arg;
#ifndef TASM_COMPAT
char *q, *prevarg;
char separator = ' ';
#endif
*inname = *outname = *listname = '\0';
@ -577,6 +696,9 @@ static void parse_cmdline(int argc, char **argv)
arg = NULL;
if (envreal) {
envcopy = nasm_strdup(envreal);
#ifdef TASM_COMPAT
process_args(envcopy);
#else
p = envcopy;
if (*p && *p != '-')
separator = *p++;
@ -591,6 +713,7 @@ static void parse_cmdline(int argc, char **argv)
}
if (arg)
process_arg (arg, NULL);
#endif
nasm_free (envcopy);
}
@ -601,6 +724,31 @@ static void parse_cmdline(int argc, char **argv)
{
int i;
argv++;
#ifdef TASM_COMPAT
if (argv[0][0] == '@') {
/* We have a response file, so process this as a set of
* arguments like the environment variable. This allows us
* to have multiple arguments on a single line, which is
* different to the -@resp file processing below for regular
* NASM.
*/
char *str = malloc(2048);
FILE *f = fopen(&argv[0][1],"r");
if (!str) {
printf("out of memory");
exit(-1);
}
if (f) {
while (fgets(str,2048,f)) {
process_args(str);
}
fclose(f);
}
free(str);
argc--;
argv++;
}
#endif
if (!stopoptions && argv[0][0] == '-' && argv[0][1] == '@') {
if ((p = get_param (argv[0], argc > 1 ? argv[1] : NULL, &i))) {
if ((rfile = fopen(p, "r"))) {
@ -629,7 +777,7 @@ static void assemble_file (char *fname)
long seg, offs;
struct tokenval tokval;
expr * e;
int pass_max;
int pass, pass_max;
int pass_cnt = 0; /* count actual passes */
if (cmd_sb == 32 && cmd_cpu < IF_386)
@ -637,18 +785,21 @@ static void assemble_file (char *fname)
"32-bit segment size requires a higher cpu");
pass_max = optimizing + 2; /* passes 1, optimizing, then 2 */
for (pass = 1; pass <= pass_max; pass++) {
pass0 = !optimizing; /* start at 1 if not optimizing */
for (pass = 1; pass <= pass_max && pass0 <= 2; pass++) {
int pass1, pass2;
ldfunc def_label;
pass1 = pass < pass_max ? 1 : 2; /* seq is 1, 1, 1,..., 1, 2 */
pass2 = pass > 1 ? 2 : 1; /* seq is 1, 2, 2,..., 2, 2 */
/* pass0 seq is 0, 0, 0,..., 1, 2 */
def_label = pass > 1 ? redefine_label : define_label;
sb = cmd_sb; /* set 'bits' to command line default */
cpu = cmd_cpu;
if (pass == pass_max) {
if (pass0 == 2) {
if (*listname)
nasmlist.init(listname, report_error);
}
@ -687,7 +838,8 @@ static void assemble_file (char *fname)
}
break;
case 2: /* [EXTERN label:special] */
if (pass == pass_max) {
if (*value == '$') value++; /* skip initial $ if present */
if (pass0 == 2) {
q = value;
while (*q && *q != ':')
q++;
@ -695,9 +847,7 @@ static void assemble_file (char *fname)
*q++ = '\0';
ofmt->symdef(value, 0L, 0L, 3, q);
}
} else if (pass == 1) { /* pass == 1 */
if (*value == '$')
value++; /* skip initial $ if present */
} else if (pass0 == 1) { /* pass == 1 */
q = value;
validid = TRUE;
if (!isidstart(*q))
@ -722,13 +872,14 @@ static void assemble_file (char *fname)
define_label (value, seg_alloc(), 0L, NULL, FALSE, TRUE,
ofmt, report_error);
}
} /* else pass == 1 */
} /* else pass0 == 1 */
break;
case 3: /* [BITS bits] */
sb = get_bits(value);
break;
case 4: /* [GLOBAL symbol:special] */
if (pass == pass_max) { /* pass 2 */
if (*value == '$') value++; /* skip initial $ if present */
if (pass0 == 2) { /* pass 2 */
q = value;
while (*q && *q != ':')
q++;
@ -736,9 +887,7 @@ static void assemble_file (char *fname)
*q++ = '\0';
ofmt->symdef(value, 0L, 0L, 3, q);
}
} else if (pass == 1) { /* pass == 1 */
if (*value == '$')
value++; /* skip initial $ if present */
} else if (pass2 == 1) { /* pass == 1 */
q = value;
validid = TRUE;
if (!isidstart(*q))
@ -762,7 +911,8 @@ static void assemble_file (char *fname)
} /* pass == 1 */
break;
case 5: /* [COMMON symbol size:special] */
if (pass == 1) {
if (*value == '$') value++; /* skip initial $ if present */
if (pass0 == 1) {
p = value;
validid = TRUE;
if (!isidstart(*p))
@ -800,7 +950,7 @@ static void assemble_file (char *fname)
} else
report_error (ERR_NONFATAL, "no size specified in"
" COMMON declaration");
} else if (pass == pass_max) { /* pass == 2 */
} else if (pass0 == 2) { /* pass == 2 */
q = value;
while (*q && *q != ':') {
if (isspace(*q))
@ -821,7 +971,7 @@ static void assemble_file (char *fname)
NULL);
if (e) {
if (!is_reloc(e))
report_error (pass==1 ? ERR_NONFATAL : ERR_PANIC,
report_error (pass0==1 ? ERR_NONFATAL : ERR_PANIC,
"cannot use non-relocatable expression as "
"ABSOLUTE address");
else {
@ -878,17 +1028,32 @@ static void assemble_file (char *fname)
case 9: /* cpu */
cpu = get_cpu (value);
break;
case 10: /* fbk 9/2/00 */ /* [LIST {+|-}] */
while (*value && isspace(*value))
value++;
if (*value == '+') {
user_nolist = 0;
}
else {
if (*value == '-') {
user_nolist = 1;
}
else {
report_error (ERR_NONFATAL, "invalid parameter to \"list\" directive");
}
}
break;
default:
if (!ofmt->directive (line+1, value, pass1))
if (!ofmt->directive (line+1, value, pass2))
report_error (pass1==1 ? ERR_NONFATAL : ERR_PANIC,
"unrecognised directive [%s]",
line+1);
break;
}
}
else /* it isn't a directive */
{
parse_line (pass2, line, &output_ins,
parse_line (pass1, line, &output_ins,
report_error, evaluate,
def_label);
@ -1026,33 +1191,38 @@ static void assemble_file (char *fname)
} else { /* instruction isn't an EQU */
if (pass1 == 1) {
long l = insn_size (location.segment, offs, sb, cpu,
&output_ins, report_error);
if (using_debug_info && output_ins.opcode != -1) {
/* if (using_debug_info) && output_ins.opcode != -1)*/
if (using_debug_info); /* fbk 12/29/00 */
{
/* this is done here so we can do debug type info */
long typeinfo = TYS_ELEMENTS(output_ins.operands);
switch (output_ins.opcode) {
case I_RESB:
typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_BYTE;
break;
typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_BYTE;
break;
case I_RESW:
typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_WORD;
break;
typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_WORD;
break;
case I_RESD:
typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_DWORD;
break;
typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_DWORD;
break;
case I_RESQ:
typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_QWORD;
break;
typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_QWORD;
break;
case I_REST:
typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_TBYTE;
break;
case I_DB:
typeinfo |= TY_BYTE;
break;
typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_TBYTE;
break;
case I_DB:
typeinfo |= TY_BYTE;
break;
case I_DW:
typeinfo |= TY_WORD;
break;
typeinfo |= TY_WORD;
break;
case I_DD:
if (output_ins.eops_float)
typeinfo |= TY_FLOAT;
@ -1062,13 +1232,16 @@ static void assemble_file (char *fname)
case I_DQ:
typeinfo |= TY_QWORD;
break;
case I_DT:
case I_DT:
typeinfo |= TY_TBYTE;
break;
default:
typeinfo = TY_LABEL;
}
ofmt->current_dfmt->debug_typevalue(typeinfo);
}
if (l != -1) {
offs += l;
@ -1104,13 +1277,17 @@ static void assemble_file (char *fname)
usage();
exit (1);
}
pass_cnt++;
if (pass>1 && !global_offset_changed && pass<pass_max) pass = pass_max-1;
pass_cnt++;
if (pass>1 && !global_offset_changed) {
pass0++;
if (pass0==2) pass = pass_max - 1;
} else if (!optimizing) pass0++;
} /* for (pass=1; pass<=2; pass++) */
nasmlist.cleanup();
#if 1
if (optimizing)
if (optimizing && using_debug_info) /* -On and -g switches */
fprintf(error_file,
"info:: assembly required 1+%d+1 passes\n", pass_cnt-2);
#endif
@ -1175,6 +1352,8 @@ static int getkw (char *buf, char **value)
return 8;
if (!nasm_stricmp(p, "cpu"))
return 9;
if (!nasm_stricmp(p, "list")) /* fbk 9/2/00 */
return 10;
return -1;
}
@ -1193,7 +1372,7 @@ static void report_error (int severity, char *fmt, ...)
/*
* See if it's a pass-one only warning and we're not in pass one.
*/
if ((severity & ERR_PASS1) && pass != 1)
if ((severity & ERR_PASS1) && pass0 == 2)
return;
if (severity & ERR_NOFILE)
@ -1363,7 +1542,7 @@ static unsigned long get_cpu (char *value)
if (!nasm_stricmp(value, "p3") ||
!nasm_stricmp(value, "katmai") ) return IF_KATMAI;
report_error (pass ? ERR_NONFATAL : ERR_FATAL, "unknown 'cpu' type");
report_error (pass0<2 ? ERR_NONFATAL : ERR_FATAL, "unknown 'cpu' type");
return IF_PLEVEL; /* the maximum level */
}
@ -1381,7 +1560,7 @@ static int get_bits (char *value)
i = 16;
}
} else {
report_error(pass ? ERR_NONFATAL : ERR_FATAL,
report_error(pass0<2 ? ERR_NONFATAL : ERR_FATAL,
"`%s' is not a valid segment size; must be 16 or 32",
value);
i = 16;

32
nasm.h
View File

@ -13,7 +13,7 @@
#define NASM_MAJOR_VER 0
#define NASM_MINOR_VER 98
#define NASM_VER "0.98.03"
#define NASM_VER "0.98.08"
#ifndef NULL
#define NULL 0
@ -33,6 +33,16 @@
#define FILENAME_MAX 256
#endif
#ifndef PREFIX_MAX
#define PREFIX_MAX 10
#endif
#ifndef POSTFIX_MAX
#define POSTFIX_MAX 10
#endif
/*
* Name pollution problems: <time.h> on Digital UNIX pulls in some
* strange hardware header file which sees fit to define R_SP. We
@ -78,13 +88,15 @@ typedef void (*efunc) (int severity, char *fmt, ...);
/*
* These codes define specific types of suppressible warning.
*/
#define ERR_WARN_MASK 0x0000FF00 /* the mask for this feature */
#define ERR_WARN_SHR 8 /* how far to shift right */
#define ERR_WARN_MNP 0x00000100 /* macro-num-parameters warning */
#define ERR_WARN_MSR 0x00000200 /* macro self-reference */
#define ERR_WARN_OL 0x00000300 /* orphan label (no colon, and
* alone on line) */
#define ERR_WARN_NOV 0x00000400 /* numeric overflow */
#define ERR_WARN_MASK 0x0000FF00 /* the mask for this feature */
#define ERR_WARN_SHR 8 /* how far to shift right */
#define ERR_WARN_MAX 4 /* the highest numbered one */
/*
@ -844,4 +856,18 @@ struct dfmt {
#define elements(x) ( sizeof(x) / sizeof(*(x)) )
#ifdef TASM_COMPAT
extern int tasm_compatible_mode;
#endif
/*
* This declaration passes the "pass" number to all other modules
* "pass0" assumes the values: 0, 0, ..., 0, 1, 2
* where 0 = optimizing pass
* 1 = pass 1
* 2 = pass 2
*/
int pass0; /* this is globally known */
#endif

View File

@ -341,6 +341,7 @@ static void aout_deflabel (char *name, long segment, long offset,
struct tokenval tokval;
expr *e;
int fwd = FALSE;
char *saveme=stdscan_bufptr; /* bugfix? fbk 8/10/00 */
if (!bsd) {
error(ERR_NONFATAL, "Linux a.out does not support"
@ -369,6 +370,7 @@ static void aout_deflabel (char *name, long segment, long offset,
sym->size = reloc_value(e);
}
}
stdscan_bufptr=saveme; /* bugfix? fbk 8/10/00 */
}
special_used = TRUE;
}

View File

@ -346,6 +346,10 @@ static void elf_deflabel (char *name, long segment, long offset,
struct Symbol *sym;
int special_used = FALSE;
#if defined(DEBUG) && DEBUG>2
fprintf(stderr, " elf_deflabel: %s, seg=%ld, off=%ld, is_global=%d, %s\n",
name, segment, offset, is_global, special);
#endif
if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
/*
* This is a NASM special symbol. We never allow it into
@ -496,6 +500,7 @@ static void elf_deflabel (char *name, long segment, long offset,
struct tokenval tokval;
expr *e;
int fwd = FALSE;
char *saveme=stdscan_bufptr; /* bugfix? fbk 8/10/00 */
while (special[n] && isspace(special[n]))
n++;
@ -518,6 +523,7 @@ static void elf_deflabel (char *name, long segment, long offset,
else
sym->size = reloc_value(e);
}
stdscan_bufptr=saveme; /* bugfix? fbk 8/10/00 */
}
special_used = TRUE;
}

View File

@ -105,7 +105,8 @@ enum RecordID { /* record ID codes */
FIXUPP = 0x9C, /* fixups (relocations) */
FIXU32 = 0x9D, /* 32-bit fixups (relocations) */
MODEND = 0x8A /* module end */
MODEND = 0x8A, /* module end */
MODE32 = 0x8B /* module end for 32-bit objects */
};
enum ComentID { /* ID codes for comment records */
@ -142,6 +143,7 @@ static void ori_null(ObjRecord *orp);
static ObjRecord *obj_commit(ObjRecord *orp);
static int obj_uppercase; /* Flag: all names in uppercase */
static int obj_use32; /* Flag: at least one segment is 32-bit */
/*
* Clear an ObjRecord structure. (Never reallocates).
@ -590,6 +592,9 @@ static long obj_entry_seg, obj_entry_ofs;
struct ofmt of_obj;
/* The current segment */
static struct Segment *current_seg;
static long obj_segment (char *, int, int *);
static void obj_write_file(int debuginfo);
static int obj_directive (char *, char *, int);
@ -620,7 +625,9 @@ static void obj_init (FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval)
grptail = &grphead;
obj_entry_seg = NO_SEG;
obj_uppercase = FALSE;
obj_use32 = FALSE;
passtwo = 0;
current_seg = NULL;
of_obj.current_dfmt->init (&of_obj,NULL,fp,errfunc);
}
@ -740,6 +747,11 @@ static void obj_deflabel (char *name, long segment,
int i;
int used_special = FALSE; /* have we used the special text? */
#if defined(DEBUG) && DEBUG>2
fprintf(stderr, " obj_deflabel: %s, seg=%ld, off=%ld, is_global=%d, %s\n",
name, segment, offset, is_global, special);
#endif
/*
* If it's a special-retry from pass two, discard it.
*/
@ -829,7 +841,17 @@ static void obj_deflabel (char *name, long segment,
ext->next = NULL;
exttail = &ext->next;
ext->name = name;
/* Place by default all externs into the current segment */
ext->defwrt_type = DEFWRT_NONE;
if (current_seg) {
if (current_seg->grp) {
ext->defwrt_type = DEFWRT_GROUP;
ext->defwrt_ptr.grp = current_seg->grp;
} else {
ext->defwrt_type = DEFWRT_SEGMENT;
ext->defwrt_ptr.seg = current_seg;
}
}
if (is_global == 2) {
ext->commonsize = offset;
ext->commonelem = 1; /* default FAR */
@ -1088,7 +1110,7 @@ static void obj_write_fixup (ObjRecord *orp, int bytes,
if (segto->use32)
forp->type = FIXU32;
else
forp->type = FIXUPP;
forp->type = FIXUPP;
}
if (seg % 2) {
@ -1224,8 +1246,13 @@ static long obj_segment (char *name, int pass, int *bits)
* using the pointer it gets passed. That way we save memory,
* by sponging off the label manager.
*/
#if defined(DEBUG) && DEBUG>=3
fprintf(stderr," obj_segment: < %s >, pass=%d, *bits=%d\n",
name, pass, *bits);
#endif
if (!name) {
*bits = 16;
current_seg = NULL;
return first_seg;
} else {
struct Segment *seg;
@ -1271,6 +1298,7 @@ static long obj_segment (char *name, int pass, int *bits)
*bits = 32;
else
*bits = 16;
current_seg = seg;
return seg->index;
}
}
@ -1398,6 +1426,9 @@ static long obj_segment (char *name, int pass, int *bits)
}
}
/* We need to know whenever we have at least one 32-bit segment */
obj_use32 |= seg->use32;
obj_seg_needs_update = seg;
if (seg->align >= SEG_ABS)
deflabel (name, NO_SEG, seg->align - SEG_ABS,
@ -1447,6 +1478,7 @@ static long obj_segment (char *name, int pass, int *bits)
*bits = 32;
else
*bits = 16;
current_seg = seg;
return seg->index;
}
}
@ -2178,7 +2210,7 @@ static void obj_write_file (int debuginfo)
}
}
if (orp->used)
obj_emit (orp);
obj_emit (orp);
/*
* Write the LEDATA/FIXUPP pairs.
@ -2191,9 +2223,10 @@ static void obj_write_file (int debuginfo)
/*
* Write the MODEND module end marker.
*/
orp->type = MODEND;
orp->type = obj_use32 ? MODE32 : MODEND;
orp->ori = ori_null;
if (entry_seg_ptr) {
orp->type = entry_seg_ptr->use32 ? MODE32 : MODEND;
obj_byte (orp, 0xC1);
seg = entry_seg_ptr;
if (seg->grp) {
@ -2324,7 +2357,8 @@ static void dbgbi_linnum (const char *lnfname, long lineno, long segto)
if (!seg)
error (ERR_PANIC, "lineno directed to nonexistent segment?");
for (fn = fnhead; fn; fn = fnhead->next)
/* for (fn = fnhead; fn; fn = fnhead->next) */
for (fn = fnhead; fn; fn = fn->next) /* fbk - Austin Lunnen - John Fine*/
if (!nasm_stricmp(lnfname,fn->name))
break;
if (!fn) {

View File

@ -74,18 +74,18 @@ struct ExportRec {
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 */
byte reclen; /* equals 4 */
long amount; /* number of bytes BSS to reserve */
};
struct DLLModRec {
byte type; /* 4 for DLLRec, 8 for ModRec */
byte reclen; /* 1+lib name length for DLLRec, 1+mod name length */
char name[128]; /* library to link at load time or module name */
};
#define COUNT_SEGTYPES 9
static char * segmenttypes[COUNT_SEGTYPES] = {
@ -321,11 +321,14 @@ static void write_bss_rec(struct BSSRec *r)
headerlength += r->reclen + 2;
}
static void write_dll_rec(struct DLLRec *r)
/*
* Write library record. Also used for module name records.
*/
static void write_dllmod_rec(struct DLLModRec *r)
{
saa_wbytes(header,&r->type,1);
saa_wbytes(header,&r->reclen,1);
saa_wbytes(header,r->libname,strlen(r->libname) + 1);
saa_wbytes(header,r->name,strlen(r->name) + 1);
headerlength += r->reclen + 2;
}
@ -334,12 +337,11 @@ static void rdf2_deflabel(char *name, long segment, long offset,
{
struct ExportRec r;
struct ImportRec ri;
#ifdef VERBOSE_WARNINGS
static int warned_common = 0;
#endif
static int farsym = 0;
static int i;
if (is_global != 1) return;
if (special) {
while(*special == ' ' || *special == '\t') special++;
@ -358,16 +360,6 @@ static void rdf2_deflabel(char *name, long segment, long offset,
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;
}
@ -635,13 +627,24 @@ static long rdf2_segbase (long segment) {
}
static int rdf2_directive (char *directive, char *value, int pass) {
struct DLLRec r;
struct DLLModRec r;
if (! strcmp(directive, "library")) {
if (pass == 1) {
r.type = 4;
strcpy(r.libname, value);
write_dll_rec(&r);
r.reclen=strlen(value)+1;
strcpy(r.name, value);
write_dllmod_rec(&r);
}
return 1;
}
if (! strcmp(directive, "module")) {
if (pass == 1) {
r.type = 8;
r.reclen=strlen(value)+1;
strcpy(r.name, value);
write_dllmod_rec(&r);
}
return 1;
}
@ -658,6 +661,9 @@ static char *rdf2_stdmac[] = {
"%imacro library 1+.nolist",
"[library %1]",
"%endmacro",
"%imacro module 1+.nolist",
"[module %1]",
"%endmacro",
"%macro __NASM_CDecl__ 1",
"%endmacro",
NULL

View File

@ -421,28 +421,68 @@ insn *parse_line (int pass, char *buffer, insn *result,
if (i == '[' || i == '&') { /* memory reference */
mref = TRUE;
bracket = (i == '[');
i = stdscan(NULL, &tokval);
i = stdscan(NULL, &tokval);
if (i == TOKEN_SPECIAL) { /* check for address size override */
switch ((int)tokval.t_integer) {
case S_NOSPLIT:
result->oprs[operand].eaflags |= EAF_TIMESTWO;
break;
case S_BYTE:
result->oprs[operand].eaflags |= EAF_BYTEOFFS;
break;
case S_WORD:
result->oprs[operand].addr_size = 16;
result->oprs[operand].eaflags |= EAF_WORDOFFS;
break;
case S_DWORD:
case S_LONG:
result->oprs[operand].addr_size = 32;
result->oprs[operand].eaflags |= EAF_WORDOFFS;
break;
default:
error (ERR_NONFATAL, "invalid size specification in"
" effective address");
#ifdef TASM_COMPAT
if (tasm_compatible_mode) {
switch ((int)tokval.t_integer) {
/* For TASM compatibility a size override inside the
* brackets changes the size of the operand, not the
* address type of the operand as it does in standard
* NASM syntax. Hence:
*
* mov eax,[DWORD val]
*
* is valid syntax in TASM compatibility mode. Note that
* you lose the ability to override the default address
* type for the instruction, but we never use anything
* but 32-bit flat model addressing in our code.
*/
case S_BYTE:
result->oprs[operand].type |= BITS8;
break;
case S_WORD:
result->oprs[operand].type |= BITS16;
break;
case S_DWORD:
case S_LONG:
result->oprs[operand].type |= BITS32;
break;
case S_QWORD:
result->oprs[operand].type |= BITS64;
break;
case S_TWORD:
result->oprs[operand].type |= BITS80;
break;
default:
error (ERR_NONFATAL, "invalid operand size specification");
}
} else {
#endif
/* Standard NASM compatible syntax */
switch ((int)tokval.t_integer) {
case S_NOSPLIT:
result->oprs[operand].eaflags |= EAF_TIMESTWO;
break;
case S_BYTE:
result->oprs[operand].eaflags |= EAF_BYTEOFFS;
break;
case S_WORD:
result->oprs[operand].addr_size = 16;
result->oprs[operand].eaflags |= EAF_WORDOFFS;
break;
case S_DWORD:
case S_LONG:
result->oprs[operand].addr_size = 32;
result->oprs[operand].eaflags |= EAF_WORDOFFS;
break;
default:
error (ERR_NONFATAL, "invalid size specification in"
" effective address");
}
#ifdef TASM_COMPAT
}
#endif
i = stdscan(NULL, &tokval);
}
} else { /* immediate operand, or register */

529
preproc.c
View File

@ -262,6 +262,9 @@ static int inverse_ccs[] = {
* Directive names.
*/
static char *directives[] = {
#ifdef TASM_COMPAT
"%arg",
#endif
"%assign", "%clear", "%define", "%elif", "%elifctx", "%elifdef",
"%elifid", "%elifidn", "%elifidni", "%elifnctx", "%elifndef",
"%elifnid", "%elifnidn", "%elifnidni", "%elifnnum", "%elifnstr",
@ -269,11 +272,21 @@ static char *directives[] = {
"%endrep", "%error", "%exitrep", "%iassign", "%idefine", "%if",
"%ifctx", "%ifdef", "%ifid", "%ifidn", "%ifidni", "%ifnctx",
"%ifndef", "%ifnid", "%ifnidn", "%ifnidni", "%ifnnum",
"%ifnstr", "%ifnum", "%ifstr", "%imacro", "%include", "%ixdefine",
"%line", "%macro", "%pop", "%push", "%rep", "%repl", "%rotate",
"%undef", "%xdefine"
"%ifnstr", "%ifnum", "%ifstr", "%imacro", "%include",
"%ixdefine", "%line",
#ifdef TASM_COMPAT
"%local",
#endif
"%macro", "%pop", "%push", "%rep", "%repl", "%rotate",
#ifdef TASM_COMPAT
"%stacksize",
#endif
"%strlen", "%substr", "%undef", "%xdefine"
};
enum {
#ifdef TASM_COMPAT
PP_ARG,
#endif
PP_ASSIGN, PP_CLEAR, PP_DEFINE, PP_ELIF, PP_ELIFCTX, PP_ELIFDEF,
PP_ELIFID, PP_ELIFIDN, PP_ELIFIDNI, PP_ELIFNCTX, PP_ELIFNDEF,
PP_ELIFNID, PP_ELIFNIDN, PP_ELIFNIDNI, PP_ELIFNNUM, PP_ELIFNSTR,
@ -281,11 +294,46 @@ enum {
PP_ENDREP, PP_ERROR, PP_EXITREP, PP_IASSIGN, PP_IDEFINE, PP_IF,
PP_IFCTX, PP_IFDEF, PP_IFID, PP_IFIDN, PP_IFIDNI, PP_IFNCTX,
PP_IFNDEF, PP_IFNID, PP_IFNIDN, PP_IFNIDNI, PP_IFNNUM,
PP_IFNSTR, PP_IFNUM, PP_IFSTR, PP_IMACRO, PP_INCLUDE, PP_IXDEFINE,
PP_LINE, PP_MACRO, PP_POP, PP_PUSH, PP_REP, PP_REPL, PP_ROTATE,
PP_UNDEF, PP_XDEFINE
PP_IFNSTR, PP_IFNUM, PP_IFSTR, PP_IMACRO, PP_INCLUDE,
PP_IXDEFINE, PP_LINE,
#ifdef TASM_COMPAT
PP_LOCAL,
#endif
PP_MACRO, PP_POP, PP_PUSH, PP_REP, PP_REPL, PP_ROTATE,
#ifdef TASM_COMPAT
PP_STACKSIZE,
#endif
PP_STRLEN, PP_SUBSTR, PP_UNDEF, PP_XDEFINE
};
#ifdef TASM_COMPAT
/* For TASM compatibility we need to be able to recognise TASM compatible
* conditional compilation directives. Using the NASM pre-processor does
* not work, so we look for them specifically from the following list and
* then jam in the equivalent NASM directive into the input stream.
*/
#ifndef MAX
# define MAX(a,b) ( ((a) > (b)) ? (a) : (b))
#endif
enum {
TM_ARG, TM_ELIF, TM_ELSE, TM_ENDIF, TM_IF, TM_IFDEF, TM_IFDIFI,
TM_IFNDEF, TM_INCLUDE, TM_LOCAL
};
static char *tasm_directives[] = {
"arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
"ifndef", "include", "local"
};
static int StackSize = 4;
static char *StackPointer = "ebp";
static int ArgOffset = 8;
static int LocalOffset = 4;
#endif
static Context *cstk;
static Include *istk;
@ -351,7 +399,7 @@ static Token *expand_mmac_params (Token *tline);
static Token *expand_smacro (Token *tline);
static Token *expand_id (Token *tline);
static Context *get_ctx (char *name, int all_contexts);
static void make_tok_num(Token *tok, long val);
static void make_tok_num(Token *tok, long val);
static void error (int severity, char *fmt, ...);
/*
@ -362,13 +410,72 @@ static void error (int severity, char *fmt, ...);
#define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
#define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
#ifdef TASM_COMPAT
/* Handle TASM specific directives, which do not contain a % in
* front of them. We do it here because I could not find any other
* place to do it for the moment, and it is a hack (ideally it would
* be nice to be able to use the NASM pre-processor to do it).
*/
static char *check_tasm_directive(char *line)
{
int i, j, k, m, len;
char *p = line, *oldline, oldchar;
/* Skip whitespace */
while (isspace(*p) && *p != 0)
p++;
/* Binary search for the directive name */
i = -1;
j = sizeof(tasm_directives) / sizeof(*tasm_directives);
len = 0;
while (!isspace(p [len]) && p [len] != 0)
len++;
if (len) {
oldchar = p [len];
p [len] = 0;
while (j - i > 1) {
k = (j + i) / 2;
m = nasm_stricmp(p, tasm_directives [k]);
if (m == 0) {
/* We have found a directive, so jam a % in front of it
* so that NASM will then recognise it as one if it's own.
*/
p [len] = oldchar;
len = strlen(p);
oldline = line;
line = nasm_malloc(len + 2);
line [0] = '%';
if (k == TM_IFDIFI) {
/* NASM does not recognise IFDIFI, so we convert it to
* %ifdef BOGUS. This is not used in NASM comaptible
* code, but does need to parse for the TASM macro
* package.
*/
strcpy(line + 1,"ifdef BOGUS");
} else {
memcpy(line + 1, p, len + 1);
}
nasm_free(oldline);
return line;
} else if (m < 0) {
j = k;
} else
i = k;
}
p [len] = oldchar;
}
return line;
}
#endif
/*
* The pre-preprocessing stage... This function translates line
* number indications as they emerge from GNU cpp (`# lineno "file"
* flags') into NASM preprocessor line number indications (`%line
* lineno file').
*/
static char *prepreproc(char *line)
static char *prepreproc(char *line)
{
int lineno, fnlen;
char *fname, *oldline;
@ -385,6 +492,10 @@ static char *prepreproc(char *line)
sprintf(line, "%%line %d %.*s", lineno, fnlen, fname);
nasm_free (oldline);
}
#ifdef TASM_COMPAT
if (tasm_compatible_mode)
return check_tasm_directive(line);
#endif
return line;
}
@ -639,7 +750,12 @@ static Token *tokenise (char *line)
type = TOK_STRING;
while (*p && *p != c)
p++;
if (*p) p++;
if (*p) {
p++;
}
else {
error(ERR_WARNING, "unterminated string");
}
}
else if (isnumstart(*p)) {
/*
@ -914,6 +1030,20 @@ static Context *get_ctx (char *name, int all_contexts)
return NULL;
}
#ifdef TASM_COMPAT
/* Add a slash to the end of a path if it is missing. We use the
* forward slash to make it compatible with Unix systems.
*/
static void backslash(char *s)
{
int pos = strlen(s);
if (s[pos-1] != '\\' && s[pos-1] != '/') {
s[pos] = '/';
s[pos+1] = '\0';
}
}
#endif
/*
* Open an include file. This routine must always return a valid
* file pointer if it returns - it's responsible for throwing an
@ -927,9 +1057,20 @@ static FILE *inc_fopen(char *file)
char *prefix = "", *combine;
IncPath *ip = ipath;
static int namelen = 0;
#ifdef TASM_COMPAT
int len = strlen(file);
#endif
while (1) {
#ifdef TASM_COMPAT
combine = nasm_malloc(strlen(prefix)+1+len+1);
strcpy(combine, prefix);
if (prefix[0] != 0)
backslash(combine);
strcat(combine, file);
#else
combine = nasm_strcat(prefix,file);
#endif
fp = fopen(combine, "r");
if (pass == 0 && fp)
{
@ -1241,6 +1382,9 @@ void expand_macros_in_string (char **p)
static int do_directive (Token *tline)
{
int i, j, k, m, nparam, nolist;
#ifdef TASM_COMPAT
int offset;
#endif
char *p, *mname;
Include *inc;
Context *ctx;
@ -1324,6 +1468,201 @@ static int do_directive (Token *tline)
}
switch (i) {
#ifdef TASM_COMPAT
case PP_STACKSIZE:
/* Directive to tell NASM what the default stack size is. The
* default is for a 16-bit stack, and this can be overriden with
* %stacksize large.
* the following form:
*
* ARG arg1:WORD, arg2:DWORD, arg4:QWORD
*/
tline = tline->next;
if (tline && tline->type == TOK_WHITESPACE)
tline = tline->next;
if (!tline || tline->type != TOK_ID) {
error (ERR_NONFATAL,"`%%stacksize' missing size parameter");
free_tlist (origline);
return 3;
}
if (nasm_stricmp(tline->text,"flat") == 0) {
/* All subsequent ARG directives are for a 32-bit stack */
StackSize = 4;
StackPointer = "ebp";
ArgOffset = 8;
LocalOffset = 4;
} else if (nasm_stricmp(tline->text,"large") == 0) {
/* All subsequent ARG directives are for a 16-bit stack,
* far function call.
*/
StackSize = 2;
StackPointer = "bp";
ArgOffset = 4;
LocalOffset = 2;
} else if (nasm_stricmp(tline->text,"small") == 0) {
/* All subsequent ARG directives are for a 16-bit stack,
* far function call. We don't support near functions.
*/
StackSize = 2;
StackPointer = "bp";
ArgOffset = 6;
LocalOffset = 2;
} else {
error (ERR_NONFATAL,"`%%stacksize' invalid size type");
free_tlist (origline);
return 3;
}
free_tlist(origline);
return 3;
case PP_ARG:
/* TASM like ARG directive to define arguments to functions, in
* the following form:
*
* ARG arg1:WORD, arg2:DWORD, arg4:QWORD
*/
offset = ArgOffset;
do {
char *arg,directive[256];
int size = StackSize;
/* Find the argument name */
tline = tline->next;
if (tline && tline->type == TOK_WHITESPACE)
tline = tline->next;
if (!tline || tline->type != TOK_ID) {
error (ERR_NONFATAL,"`%%arg' missing argument parameter");
free_tlist (origline);
return 3;
}
arg = tline->text;
/* Find the argument size type */
tline = tline->next;
if (!tline || tline->type != TOK_OTHER || tline->text[0] != ':') {
error (ERR_NONFATAL,"Syntax error processing `%%arg' directive");
free_tlist (origline);
return 3;
}
tline = tline->next;
if (!tline || tline->type != TOK_ID) {
error (ERR_NONFATAL,"`%%arg' missing size type parameter");
free_tlist (origline);
return 3;
}
/* Allow macro expansion of type parameter */
tt = tokenise(tline->text);
tt = expand_smacro(tt);
if (nasm_stricmp(tt->text,"byte") == 0) {
size = MAX(StackSize,1);
} else if (nasm_stricmp(tt->text,"word") == 0) {
size = MAX(StackSize,2);
} else if (nasm_stricmp(tt->text,"dword") == 0) {
size = MAX(StackSize,4);
} else if (nasm_stricmp(tt->text,"qword") == 0) {
size = MAX(StackSize,8);
} else if (nasm_stricmp(tt->text,"tword") == 0) {
size = MAX(StackSize,10);
} else {
error (ERR_NONFATAL,"Invalid size type for `%%arg' missing directive");
free_tlist (tt);
free_tlist (origline);
return 3;
}
free_tlist (tt);
/* Now define the macro for the argument */
sprintf(directive,"%%define %s (%s+%d)", arg, StackPointer, offset);
do_directive(tokenise(directive));
offset += size;
/* Move to the next argument in the list */
tline = tline->next;
if (tline && tline->type == TOK_WHITESPACE)
tline = tline->next;
} while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
free_tlist (origline);
return 3;
case PP_LOCAL:
/* TASM like LOCAL directive to define local variables for a
* function, in the following form:
*
* LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
*
* The '= LocalSize' at the end is ignored by NASM, but is
* required by TASM to define the local parameter size (and used
* by the TASM macro package).
*/
offset = LocalOffset;
do {
char *local,directive[256];
int size = StackSize;
/* Find the argument name */
tline = tline->next;
if (tline && tline->type == TOK_WHITESPACE)
tline = tline->next;
if (!tline || tline->type != TOK_ID) {
error (ERR_NONFATAL,"`%%local' missing argument parameter");
free_tlist (origline);
return 3;
}
local = tline->text;
/* Find the argument size type */
tline = tline->next;
if (!tline || tline->type != TOK_OTHER || tline->text[0] != ':') {
error (ERR_NONFATAL,"Syntax error processing `%%local' directive");
free_tlist (origline);
return 3;
}
tline = tline->next;
if (!tline || tline->type != TOK_ID) {
error (ERR_NONFATAL,"`%%local' missing size type parameter");
free_tlist (origline);
return 3;
}
/* Allow macro expansion of type parameter */
tt = tokenise(tline->text);
tt = expand_smacro(tt);
if (nasm_stricmp(tt->text,"byte") == 0) {
size = MAX(StackSize,1);
} else if (nasm_stricmp(tt->text,"word") == 0) {
size = MAX(StackSize,2);
} else if (nasm_stricmp(tt->text,"dword") == 0) {
size = MAX(StackSize,4);
} else if (nasm_stricmp(tt->text,"qword") == 0) {
size = MAX(StackSize,8);
} else if (nasm_stricmp(tt->text,"tword") == 0) {
size = MAX(StackSize,10);
} else {
error (ERR_NONFATAL,"Invalid size type for `%%local' missing directive");
free_tlist (tt);
free_tlist (origline);
return 3;
}
free_tlist (tt);
/* Now define the macro for the argument */
sprintf(directive,"%%define %s (%s-%d)", local, StackPointer, offset);
do_directive(tokenise(directive));
offset += size;
/* Now define the assign to setup the enter_c macro correctly */
sprintf(directive,"%%assign %%$localsize %%$localsize+%d", size);
do_directive(tokenise(directive));
/* Move to the next argument in the list */
tline = tline->next;
if (tline && tline->type == TOK_WHITESPACE)
tline = tline->next;
} while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
free_tlist (origline);
return 3;
#endif
case PP_CLEAR:
if (tline->next)
@ -1940,6 +2279,178 @@ static int do_directive (Token *tline)
free_tlist (origline);
return 3;
case PP_STRLEN:
tline = tline->next;
skip_white_(tline);
tline = expand_id (tline);
if (!tline || (tline->type != TOK_ID &&
(tline->type != TOK_PREPROC_ID ||
tline->text[1] != '$'))) {
error (ERR_NONFATAL,
"`%%strlen' expects a macro identifier as first parameter");
free_tlist (origline);
return 3;
}
ctx = get_ctx (tline->text, FALSE);
if (!ctx)
smhead = &smacros[hash(tline->text)];
else
smhead = &ctx->localmac;
mname = tline->text;
last = tline;
tline = expand_smacro (tline->next);
last->next = NULL;
t = tline;
while (tok_type_(t, TOK_WHITESPACE))
t = t->next;
/* t should now point to the string */
if (t->type != TOK_STRING) {
error(ERR_NONFATAL,
"`%%strlen` requires string as second parameter");
free_tlist(tline);
free_tlist(origline);
return 3;
}
macro_start = nasm_malloc(sizeof(*macro_start));
macro_start->next = NULL;
make_tok_num(macro_start, strlen(t->text)-2);
macro_start->mac = NULL;
/*
* We now have a macro name, an implicit parameter count of
* zero, and a numeric token to use as an expansion. Create
* and store an SMacro.
*/
if (smacro_defined (ctx, mname, 0, &smac, i == PP_STRLEN)) {
if (!smac)
error (ERR_WARNING,
"single-line macro `%s' defined both with and"
" without parameters", mname);
else {
/*
* We're redefining, so we have to take over an
* existing SMacro structure. This means freeing
* what was already in it.
*/
nasm_free (smac->name);
free_tlist (smac->expansion);
}
}
else {
smac = nasm_malloc(sizeof(SMacro));
smac->next = *smhead;
*smhead = smac;
}
smac->name = nasm_strdup(mname);
smac->casesense = (i == PP_STRLEN);
smac->nparam = 0;
smac->expansion = macro_start;
smac->in_progress = FALSE;
free_tlist (tline);
free_tlist (origline);
return 3;
case PP_SUBSTR:
tline = tline->next;
skip_white_(tline);
tline = expand_id (tline);
if (!tline || (tline->type != TOK_ID &&
(tline->type != TOK_PREPROC_ID ||
tline->text[1] != '$'))) {
error (ERR_NONFATAL,
"`%%substr' expects a macro identifier as first parameter");
free_tlist (origline);
return 3;
}
ctx = get_ctx (tline->text, FALSE);
if (!ctx)
smhead = &smacros[hash(tline->text)];
else
smhead = &ctx->localmac;
mname = tline->text;
last = tline;
tline = expand_smacro (tline->next);
last->next = NULL;
t = tline->next;
while (tok_type_(t, TOK_WHITESPACE))
t = t->next;
/* t should now point to the string */
if (t->type != TOK_STRING) {
error(ERR_NONFATAL,
"`%%substr` requires string as second parameter");
free_tlist(tline);
free_tlist(origline);
return 3;
}
tt = t->next;
tptr = &tt;
tokval.t_type = TOKEN_INVALID;
evalresult = evaluate (ppscan, tptr, &tokval, NULL, pass, error, NULL);
if (!evalresult) {
free_tlist(tline);
free_tlist(origline);
return 3;
}
if (!is_simple(evalresult)) {
error(ERR_NONFATAL,
"non-constant value given to `%%substr`");
free_tlist(tline);
free_tlist(origline);
return 3;
}
macro_start = nasm_malloc(sizeof(*macro_start));
macro_start->next = NULL;
macro_start->text = nasm_strdup("'''");
if (evalresult->value > 0 && evalresult->value < strlen(t->text)-1) {
macro_start->text[1] = t->text[evalresult->value];
}
else {
macro_start->text[2] = '\0';
}
macro_start->type = TOK_STRING;
macro_start->mac = NULL;
/*
* We now have a macro name, an implicit parameter count of
* zero, and a numeric token to use as an expansion. Create
* and store an SMacro.
*/
if (smacro_defined (ctx, mname, 0, &smac, i == PP_SUBSTR)) {
if (!smac)
error (ERR_WARNING,
"single-line macro `%s' defined both with and"
" without parameters", mname);
else {
/*
* We're redefining, so we have to take over an
* existing SMacro structure. This means freeing
* what was already in it.
*/
nasm_free (smac->name);
free_tlist (smac->expansion);
}
}
else {
smac = nasm_malloc(sizeof(SMacro));
smac->next = *smhead;
*smhead = smac;
}
smac->name = nasm_strdup(mname);
smac->casesense = (i == PP_SUBSTR);
smac->nparam = 0;
smac->expansion = macro_start;
smac->in_progress = FALSE;
free_tlist (tline);
free_tlist (origline);
return 3;
case PP_ASSIGN:
case PP_IASSIGN:
tline = tline->next;

441
proc32.ash Normal file
View File

@ -0,0 +1,441 @@
;--------=========xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=========--------
;
; Copyright (C) 1999 by Andrew Zabolotny
; Miscelaneous NASM macros that makes use of new preprocessor features
;
; This library is free software; you can redistribute it and/or
; modify it under the terms of the GNU Library General Public
; License as published by the Free Software Foundation; either
; version 2 of the License, or (at your option) any later version.
;
; This library is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
; Library General Public License for more details.
;
; You should have received a copy of the GNU Library General Public
; License along with this library; if not, write to the Free
; Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
;
;--------=========xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=========--------
; The macros in this file provides support for writing 32-bit C-callable
; NASM routines. For a short description of every macros see the
; corresponding comment before every one. Simple usage example:
;
; proc sin,1
; targ %$angle
; fld %$angle
; fsin
; endproc sin
%ifndef __PROC32_ASH__
%define __PROC32_ASH__
[WARNING -macro-selfref]
;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
; Summary:
; Mangle a name to be compatible with the C compiler
; Arguments:
; The name
; Example:
; cname (my_func)
;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
%ifdef EXTERNC_UNDERSCORE
%define cname(x) _ %+ x
%else
%define cname(x) x
%endif
;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
; Summary:
; Import an external C procedure definition
; Arguments:
; The name of external C procedure
; Example:
; cextern printf
;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
%macro cextern 1
%xdefine %1 cname(%1)
%ifidni __OUTPUT_FORMAT__,obj
extern %1:wrt FLAT
%else
extern %1
%endif
%endmacro
;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
; Summary:
; Export an C procedure definition
; Arguments:
; The name of C procedure
; Example:
; cglobal my_printf
;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
%macro cglobal 1
%xdefine %1 cname(%1)
global %1
%endmacro
;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
; Summary:
; Misc macros to deal with PIC shared libraries
; Comment:
; Note that we have a different syntax for working with and without
; PIC shared libraries. In a PIC environment we should load first
; the address of the variable into a register and then work through
; that address, i.e: mov eax,myvar; mov [eax],1
; In a non-PIC environment we should directly write: mov myvar,1
; Example:
; extvar myvar
; GetGOT
; %ifdef PIC
; mov ebx,myvar ; get offset of myvar into ebx
; %else
; lea ebx,myvar
; %endif
;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
%ifdef PIC
cextern _GLOBAL_OFFSET_TABLE_
%macro GetGOT 0
%ifdef .$proc.stkofs
%assign .$proc.stkofs .$proc.stkofs+4
%endif
call %$Get_GOT
%$Get_GOT:
pop ebx
add ebx,_GLOBAL_OFFSET_TABLE_ + $$ - %$Get_GOT wrt ..gotpc
%endmacro
%macro extvar 1
cextern %1
%xdefine %1 [ebx+%1 wrt ..got]
%endmacro
%else
%define GetGOT
%macro extvar 1
cextern %1
%endmacro
%endif
;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
; Summary:
; Begin a procedure definition
; For performance reasons we don't use stack frame pointer EBP,
; instead we're using the [esp+xx] addressing. Because of this
; you should be careful when you work with stack pointer.
; The push/pop instructions are macros that are defined to
; deal correctly with these issues.
; Arguments:
; First argument - the procedure name
; Second optional argument - the number of bytes for local variables
; The following arguments could specify the registers that should be
; pushed at beginning of procedure and popped before exiting
; Example:
; proc MyTestProc
; proc MyTestProc,4,ebx,esi,edi
;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
%macro proc 1-3+ 0
cglobal %1
%push %1
align 16
%1:
%xdefine %$proc.name %1
; total size of local arguments
%assign %$proc.locsize (%2+3) & 0xFFFC
; offset from esp to argument
%assign %$proc.argofs 4+%$proc.locsize
; additional offset to args (tracks push/pops)
%assign .$proc.stkofs 0
; offset from esp to local arguments
%assign %$proc.locofs 0
; Now push the registers that we should save
%define %$proc.save %3
%if %$proc.locsize != 0
sub esp,%$proc.locsize
%endif
push %$proc.save
%endmacro
;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
; Summary:
; Declare an argument passed on stack
; This macro defines two additional macros:
; first (with the name given by first argument) - [esp+xx]
; second (with a underscore appended to first argument) - esp+xx
; Arguments:
; First argument defines the procedure argument name
; Second optional parameter defines the size of the argument
; Default value is 4 (a double word)
; Example:
; arg .my_float
; arg .my_double,8
;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
%macro arg 1-2 4
%ifndef %$proc.argofs
%error "`arg' not in a proc context"
%else
; Trick: temporary undefine .$proc.stkofs so that it won't be expanded
%assign %%. .$proc.stkofs
%undef .$proc.stkofs
%xdefine %{1}_ esp+%$proc.argofs+.$proc.stkofs
%xdefine %1 [esp+%$proc.argofs+.$proc.stkofs]
%assign .$proc.stkofs %%.
%assign %$proc.argofs %2+%$proc.argofs
%endif
%endmacro
;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
; Summary:
; Declare an local variable
; first (with the name given by first argument) - [esp+xx]
; second (with a slash prefixing the first argument) - esp+xx
; Arguments:
; First argument defines the procedure argument name
; Second optional parameter defines the size of the argument
; Default value is 4 (a double word)
; Example:
; loc .int_value
; loc .double_value,8
;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
%macro loc 1-2 4
%ifndef %$proc.locofs
%error "`loc' not in a proc context"
%elif %$proc.locofs + %2 > %$proc.locsize
%error "local stack space exceeded"
%else
%assign %%. .$proc.stkofs
%undef .$proc.stkofs
%xdefine %{1}_ esp+%$proc.locofs+.$proc.stkofs
%xdefine %1 [esp+%$proc.locofs+.$proc.stkofs]
%assign .$proc.stkofs %%.
%assign %$proc.locofs %$proc.locofs+%2
%endif
%endmacro
;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
; Summary:
; Get the type of given size into context-local variable %$type
; Arguments:
; Size of type we want (1,2,4,8 or 10)
; Example:
; type 4 ; gives "dword"
; type 10 ; gives "tword"
;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
%macro type 1
%if %1 = 1
%define %$type byte
%elif %1 = 2
%define %$type word
%elif %1 = 4
%define %$type dword
%elif %1 = 8
%define %$type qword
%elif %1 = 10
%define %$type tword
%else
%define %$. %1
%error "unknown type for argument size %$."
%endif
%endmacro
;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
; Summary:
; Same as `arg' but prepends "word", "dword" etc (typed arg)
; first (with the name given by first argument) - dword [esp+xx]
; second (with a slash prefixing the first argument) - esp+xx
; Arguments:
; Same as for `arg'
; Example:
; targ .my_float ; .my_float is now "dword [esp+xxx]"
; targ .my_double,8 ; .my_double is now "qword [esp+xxx]"
;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
%macro targ 1-2 4
%ifndef %$proc.argofs
%error "`targ' not in a proc context"
%else
arg %1,%2
type %2
%assign %%. .$proc.stkofs
%undef .$proc.stkofs
%xdefine %1 %$type %1
%assign .$proc.stkofs %%.
%endif
%endmacro
;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
; Summary:
; Same as `loc' but prepends "word", "dword" etc (typed loc)
; first (with the name given by first argument) - dword [esp+xx]
; second (with a slash prefixing the first argument) - esp+xx
; Arguments:
; Same as for `loc'
; Example:
; tloc int_value
; tloc double_value,8
;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
%macro tloc 1-2 4
%ifndef %$proc.locofs
%error "`tloc' not in a proc context"
%else
loc %1,%2
type %2
%assign %%. .$proc.stkofs
%undef .$proc.stkofs
%xdefine %1 %$type %1
%assign .$proc.stkofs %%.
%endif
%endmacro
;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
; Summary:
; Finish a procedure
; Gives an error if proc/endproc pairs mismatch
; Defines an label called __end_(procedure name)
; which is useful for calculating function size
; Arguments:
; (optional) The name of procedure
; Example:
; endproc MyTestProc
;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
%push tmp ; trick: define a dummy context to avoid error in next line
%macro endproc 0-1 %$proc.name
%ifndef %$proc.argofs
%error "`endproc' not in a proc context"
%elifnidn %$proc.name,%1
%define %$. %1
%error "endproc names mismatch: expected `%$proc.name'"
%error "but got `%$.' instead"
%elif %$proc.locofs < %$proc.locsize
%error "unused local space declared (used %$proc.locofs, requested %$proc.locsize)"
%else
%$exit:
; Now pop the registers that we should restore on exit
pop %$proc.save
%if %$proc.locsize != 0
add esp,%$proc.locsize
%endif
ret
__end_%1:
%pop
%endif
%endmacro
%pop
;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
; Summary:
; A replacement for "push" for use within procedures
; Arguments:
; any number of registers which will be push'ed successively
; Example:
; push eax,ebx,ecx,edx
;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
%macro push 0-*
; dummy comment to avoid problems with "push" on the same line with a label
%rep %0
push %1
%rotate 1
%assign .$proc.stkofs .$proc.stkofs+4
%endrep
%endmacro
;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
; Summary:
; A replacement for "pop" for use within procedures
; Arguments:
; any number of registers which will be pop'ed in reverse order
; Example:
; pop eax,ebx,ecx,edx
;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
%macro pop 0-*
; dummy comment to avoid problems with "pop" on the same line with a label
%rep %0
%rotate -1
pop %1
%assign .$proc.stkofs .$proc.stkofs-4
%endrep
%endmacro
;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
; Summary:
; Replacements for "pushfd" and "popfd" that takes care of esp
; Example:
; pushfd
; popfd
;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
%macro pushfd 0
pushfd
%assign .$proc.stkofs .$proc.stkofs+4
%endmacro
%macro popfd 0
popfd
%assign .$proc.stkofs .$proc.stkofs-4
%endmacro
;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
; Summary:
; Exit from current procedure (optionally on given condition)
; Arguments:
; Either none or a condition code
; Example:
; exit
; exit nz
;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
%macro exit 0-1 mp
j%1 near %$exit
%endmacro
;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
; Summary:
; start an conditional branch
; Arguments:
; A condition code
; second (optional) argument - "short" (by default - "near")
; Example:
; if nz
;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
%macro if 1-2 near
; dummy comment to avoid problems with "if" on the same line with a label
%push if
j%-1 %2 %$elseif
%endmacro
;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
; Summary:
; define the "else" branch of a conditional statement
; Arguments:
; optionaly: "short" if jmp to endif is less than 128 bytes away
; Example:
; else
;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
%macro else 0-1
%ifnctx if
%error "`else' without matching `if'"
%else
jmp %1 %$endif
%$elseif:
%define %$elseif_defined
%endif
%endmacro
;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
; Summary:
; Finish am conditional statement
; Arguments:
; none
; Example:
; endif
;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
%macro endif 0
%ifnctx if
%error "`endif' without matching `if'"
%else
%ifndef %$elseif_defined
%$elseif:
%endif
%$endif:
%pop
%endif
%endmacro
%endif ; __PROC32_ASH__

75
rdoff/Makefile.dj Normal file
View File

@ -0,0 +1,75 @@
# Generated automatically from Makefile.in by configure.
#
# Auto-configuring Makefile for RDOFF object file utils; part of 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.
# You may need to adjust these values.
prefix = /djgpp
CC = gcc -s
CFLAGS = -O2 -I..
# You _shouldn't_ need to adjust anything below this line.
exec_prefix = ${prefix}
bindir = ${exec_prefix}/bin
mandir = ${prefix}/man
INSTALL = /usr/bin/install -c
INSTALL_PROGRAM = ${INSTALL}
INSTALL_DATA = ${INSTALL} -m 644
LN_S = ln -s
LDRDFLIBS = rdoff.o ../nasmlib.o symtab.o hash.o collectn.o rdlib.o segtab.o
RDXLIBS = rdoff.o rdfload.o symtab.o hash.o collectn.o
.c.o:
$(CC) -c $(CFLAGS) $*.c
all: rdfdump ldrdf rdx rdflib rdf2bin rdf2com
rdfdump: rdfdump.o
$(CC) -o rdfdump rdfdump.o
ldrdf: ldrdf.o $(LDRDFLIBS)
$(CC) -o ldrdf ldrdf.o $(LDRDFLIBS)
rdx: rdx.o $(RDXLIBS)
$(CC) -o rdx rdx.o $(RDXLIBS)
rdflib: rdflib.o
$(CC) -o rdflib rdflib.o
rdf2bin: rdf2bin.o $(RDXLIBS) nasmlib.o
$(CC) -o rdf2bin rdf2bin.o $(RDXLIBS) nasmlib.o
rdf2com:
$(LN_S) rdf2bin rdf2com
rdf2bin.o: rdf2bin.c
rdfdump.o: rdfdump.c
rdoff.o: rdoff.c rdoff.h
ldrdf.o: ldrdf.c rdoff.h ../nasmlib.h symtab.h collectn.h rdlib.h
symtab.o: symtab.c symtab.h hash.h
collectn.o: collectn.c collectn.h
rdx.o: rdx.c rdoff.h rdfload.h symtab.h
rdfload.o: rdfload.c rdfload.h rdoff.h collectn.h symtab.h
rdlib.o: rdlib.c rdlib.h
rdflib.o: rdflib.c
hash.o: hash.c hash.h
segtab.o: segtab.c segtab.h
nasmlib.o: ../nasmlib.c ../nasmlib.h ../names.c ../nasm.h
$(CC) -c $(CFLAGS) ../nasmlib.c
clean:
rm -f *.o rdfdump ldrdf rdx rdflib rdf2bin rdf2com
install: rdfdump ldrdf rdx rdflib rdf2bin rdf2com
$(INSTALL_PROGRAM) rdfdump $(bindir)/rdfdump
$(INSTALL_PROGRAM) ldrdf $(bindir)/ldrdf
$(INSTALL_PROGRAM) rdx $(bindir)/rdx
$(INSTALL_PROGRAM) rdflib $(bindir)/rdflib
$(INSTALL_PROGRAM) rdf2bin $(bindir)/rdf2bin
cd $(bindir); $(LN_S) rdf2bin rdf2com

76
rdoff/Makefile.emx Normal file
View File

@ -0,0 +1,76 @@
# Generated automatically from Makefile.in by configure.
# $Id$
#
# Auto-configuring Makefile for RDOFF object file utils; part of 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.
top_srcdir = ..
srcdir = .
prefix = /usr/local
exec_prefix = ${prefix}
bindir = ${exec_prefix}/bin
mandir = ${prefix}/man
CC = gcc
CFLAGS = -s -Zomf -O2 -fomit-frame-pointer -Wall -ansi -pedantic -I$(srcdir) -I$(top_srcdir)
LDFLAGS = -s -Zomf -Zexe -Zcrtdll
LIBS = -lgcc
INSTALL = .././install-sh -c
INSTALL_PROGRAM = ${INSTALL}
INSTALL_DATA = ${INSTALL} -m 644
LDRDFLIBS = rdoff.o nasmlib.o symtab.o collectn.o rdlib.o segtab.o hash.o
RDXLIBS = rdoff.o rdfload.o symtab.o collectn.o hash.o
.c.o:
$(CC) -c $(CFLAGS) -o $@ $<
all: rdfdump ldrdf rdx rdflib rdf2bin
rdfdump: rdfdump.o
$(CC) $(LDFLAGS) -o rdfdump rdfdump.o $(LIBS)
ldrdf: ldrdf.o $(LDRDFLIBS)
$(CC) $(LDFLAGS) -o ldrdf ldrdf.o $(LDRDFLIBS) $(LIBS)
rdx: rdx.o $(RDXLIBS)
$(CC) $(LDFLAGS) -o rdx rdx.o $(RDXLIBS) $(LIBS)
rdflib: rdflib.o
$(CC) $(LDFLAGS) -o rdflib rdflib.o $(LIBS)
rdf2bin: rdf2bin.o $(RDXLIBS) nasmlib.o
$(CC) $(LDFLAGS) -o rdf2bin rdf2bin.o $(RDXLIBS) nasmlib.o $(LIBS)
rdf2bin.o: rdf2bin.c
rdfdump.o: rdfdump.c
rdoff.o: rdoff.c rdoff.h
ldrdf.o: ldrdf.c rdoff.h $(top_srcdir)/nasmlib.h symtab.h collectn.h rdlib.h
symtab.o: symtab.c symtab.h
collectn.o: collectn.c collectn.h
rdx.o: rdx.c rdoff.h rdfload.h symtab.h
rdfload.o: rdfload.c rdfload.h rdoff.h collectn.h symtab.h
rdlib.o: rdlib.c rdlib.h
rdflib.o: rdflib.c
segtab.o: segtab.c
nasmlib.o: $(top_srcdir)/nasmlib.c
$(CC) -c $(CFLAGS) -o $@ $(top_srcdir)/nasmlib.c
clean:
rm -f *.o rdfdump ldrdf rdx rdflib rdf2bin rdf2com
spotless: clean
rm -f Makefile
distclean: spotless
install: rdfdump ldrdf rdx rdflib rdf2bin rdf2com
$(INSTALL_PROGRAM) rdfdump $(INSTALLROOT)$(bindir)/rdfdump
$(INSTALL_PROGRAM) ldrdf $(INSTALLROOT)$(bindir)/ldrdf
$(INSTALL_PROGRAM) rdx $(INSTALLROOT)$(bindir)/rdx
$(INSTALL_PROGRAM) rdflib $(INSTALLROOT)$(bindir)/rdflib
$(INSTALL_PROGRAM) rdf2bin $(INSTALLROOT)$(bindir)/rdf2bin
cd $(INSTALLROOT)$(bindir) && rm -f rdf2com && $(LN_S) rdf2bin rdf2com

View File

@ -29,9 +29,9 @@ LDRDFLIBS = rdoff.o nasmlib.o symtab.o collectn.o rdlib.o segtab.o hash.o
RDXLIBS = rdoff.o rdfload.o symtab.o collectn.o hash.o
.c.o:
$(CC) -c $(CFLAGS) -o $@ $<
$(CC) -c $(CFLAGS) $<
all: rdfdump ldrdf rdx rdflib rdf2bin rdf2com
all: rdfdump ldrdf rdx rdflib rdf2bin rdf2com rdf2ihx
rdfdump: rdfdump.o
$(CC) $(LDFLAGS) -o rdfdump rdfdump.o
@ -45,7 +45,10 @@ rdf2bin: rdf2bin.o $(RDXLIBS) nasmlib.o
$(CC) $(LDFLAGS) -o rdf2bin rdf2bin.o $(RDXLIBS) nasmlib.o
rdf2com:
rm -f rdf2com && $(LN_S) rdf2bin rdf2com
rdf2ihx: rdf2ihx.o $(RDXLIBS) nasmlib.o
$(CC) $(LDFLAGS) -o rdf2ihx rdf2ihx.o $(RDXLIBS) nasmlib.o
rdf2ihx.o: rdf2ihx.c
rdf2bin.o: rdf2bin.c
rdfdump.o: rdfdump.c
rdoff.o: rdoff.c rdoff.h
@ -62,17 +65,18 @@ nasmlib.o: $(top_srcdir)/nasmlib.c
$(CC) -c $(CFLAGS) $(top_srcdir)/nasmlib.c
clean:
rm -f *.o rdfdump ldrdf rdx rdflib rdf2bin rdf2com
rm -f *.o rdfdump ldrdf rdx rdflib rdf2bin rdf2com rdf2ihx
spotless: clean
rm -f Makefile
distclean: spotless
install: rdfdump ldrdf rdx rdflib rdf2bin rdf2com
install: rdfdump ldrdf rdx rdflib rdf2bin rdf2com rdf2ihx
$(INSTALL_PROGRAM) rdfdump $(INSTALLROOT)$(bindir)/rdfdump
$(INSTALL_PROGRAM) ldrdf $(INSTALLROOT)$(bindir)/ldrdf
$(INSTALL_PROGRAM) rdx $(INSTALLROOT)$(bindir)/rdx
$(INSTALL_PROGRAM) rdflib $(INSTALLROOT)$(bindir)/rdflib
$(INSTALL_PROGRAM) rdf2bin $(INSTALLROOT)$(bindir)/rdf2bin
$(INSTALL_PROGRAM) rdf2ihx $(INSTALLROOT)$(bindir)/rdf2ihx
cd $(INSTALLROOT)$(bindir) && rm -f rdf2com && $(LN_S) rdf2bin rdf2com

View File

@ -1,57 +1,56 @@
# Makefile for RDOFF object file utils; part of 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 Makefile is designed for use under Unix (probably fairly
# portably).
CC = sc
CCFLAGS = -I..\ -c -a1 -mn -Nc -w2 -w7 -o+time -5
LINK = link
LINKFLAGS = /noi /exet:NT /su:console
OBJ=obj
EXE=.exe
NASMLIB = ..\nasmlib.$(OBJ)
NASMLIB_H = ..\nasmlib.h
LDRDFLIBS = rdoff.$(OBJ) $(NASMLIB) symtab.$(OBJ) collectn.$(OBJ) rdlib.$(OBJ)
RDXLIBS = rdoff.$(OBJ) rdfload.$(OBJ) symtab.$(OBJ) collectn.$(OBJ)
.c.$(OBJ):
$(CC) $(CCFLAGS) $*.c
all : rdfdump$(EXE) ldrdf$(EXE) rdx$(EXE) rdflib$(EXE) rdf2bin$(EXE) rdf2com$(EXE)
rdfdump$(EXE) : rdfdump.$(OBJ)
$(LINK) $(LINKFLAGS) rdfdump.$(OBJ), rdfdump$(EXE);
ldrdf$(EXE) : ldrdf.$(OBJ) $(LDRDFLIBS)
$(LINK) $(LINKFLAGS) ldrdf.$(OBJ) $(LDRDFLIBS), ldrdf$(EXE);
rdx$(EXE) : rdx.$(OBJ) $(RDXLIBS)
$(LINK) $(LINKFLAGS) rdx.$(OBJ) $(RDXLIBS), rdx$(EXE);
rdflib$(EXE) : rdflib.$(OBJ)
$(LINK) $(LINKFLAGS) rdflib.$(OBJ), rdflib$(EXE);
rdf2bin$(EXE) : rdf2bin.$(OBJ) $(RDXLIBS) $(NASMLIB)
$(LINK) $(LINKFLAGS) rdf2bin.$(OBJ) $(RDXLIBS) $(NASMLIB), rdf2bin$(EXE);
rdf2com$(EXE) : rdf2bin$(EXE)
copy rdf2bin$(EXE) rdf2com$(EXE)
rdf2bin.$(OBJ) : rdf2bin.c
rdfdump.$(OBJ) : rdfdump.c
rdoff.$(OBJ) : rdoff.c rdoff.h
ldrdf.$(OBJ) : ldrdf.c rdoff.h $(NASMLIB_H) symtab.h collectn.h rdlib.h
symtab.$(OBJ) : symtab.c symtab.h
collectn.$(OBJ) : collectn.c collectn.h
rdx.$(OBJ) : rdx.c rdoff.h rdfload.h symtab.h
rdfload.$(OBJ) : rdfload.c rdfload.h rdoff.h collectn.h symtab.h
rdlib.$(OBJ) : rdlib.c rdlib.h
rdflib.$(OBJ) : rdflib.c
clean :
del *.$(OBJ) rdfdump$(EXE) ldrdf$(EXE) rdx$(EXE) rdflib$(EXE) rdf2bin$(EXE)

# Makefile for RDOFF object file utils; part of 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 Makefile is designed for use under Unix (probably fairly
# portably).
CC = sc
CCFLAGS = -I..\ -c -a1 -mn -Nc -w2 -w7 -o+time -5
LINK = link
LINKFLAGS = /noi /exet:NT /su:console
OBJ=obj
EXE=.exe
NASMLIB = ..\nasmlib.$(OBJ)
NASMLIB_H = ..\nasmlib.h
LDRDFLIBS = rdoff.$(OBJ) $(NASMLIB) symtab.$(OBJ) collectn.$(OBJ) rdlib.$(OBJ)
RDXLIBS = rdoff.$(OBJ) rdfload.$(OBJ) symtab.$(OBJ) collectn.$(OBJ)
.c.$(OBJ):
$(CC) $(CCFLAGS) $*.c
all : rdfdump$(EXE) ldrdf$(EXE) rdx$(EXE) rdflib$(EXE) rdf2bin$(EXE) rdf2com$(EXE)
rdfdump$(EXE) : rdfdump.$(OBJ)
$(LINK) $(LINKFLAGS) rdfdump.$(OBJ), rdfdump$(EXE);
ldrdf$(EXE) : ldrdf.$(OBJ) $(LDRDFLIBS)
$(LINK) $(LINKFLAGS) ldrdf.$(OBJ) $(LDRDFLIBS), ldrdf$(EXE);
rdx$(EXE) : rdx.$(OBJ) $(RDXLIBS)
$(LINK) $(LINKFLAGS) rdx.$(OBJ) $(RDXLIBS), rdx$(EXE);
rdflib$(EXE) : rdflib.$(OBJ)
$(LINK) $(LINKFLAGS) rdflib.$(OBJ), rdflib$(EXE);
rdf2bin$(EXE) : rdf2bin.$(OBJ) $(RDXLIBS) $(NASMLIB)
$(LINK) $(LINKFLAGS) rdf2bin.$(OBJ) $(RDXLIBS) $(NASMLIB), rdf2bin$(EXE);
rdf2com$(EXE) : rdf2bin$(EXE)
copy rdf2bin$(EXE) rdf2com$(EXE)
rdf2bin.$(OBJ) : rdf2bin.c
rdfdump.$(OBJ) : rdfdump.c
rdoff.$(OBJ) : rdoff.c rdoff.h
ldrdf.$(OBJ) : ldrdf.c rdoff.h $(NASMLIB_H) symtab.h collectn.h rdlib.h
symtab.$(OBJ) : symtab.c symtab.h
collectn.$(OBJ) : collectn.c collectn.h
rdx.$(OBJ) : rdx.c rdoff.h rdfload.h symtab.h
rdfload.$(OBJ) : rdfload.c rdfload.h rdoff.h collectn.h symtab.h
rdlib.$(OBJ) : rdlib.c rdlib.h
rdflib.$(OBJ) : rdflib.c
clean :
del *.$(OBJ) rdfdump$(EXE) ldrdf$(EXE) rdx$(EXE) rdflib$(EXE) rdf2bin$(EXE)

View File

@ -4,16 +4,8 @@ RDOFF Utils v0.3
The files contained in this directory are the C source code of a set
of tools (and general purpose library files) for the manipulation of
RDOFF version 2 object files. Note that these programs (with the
exception of 'rdfdump') will NOT work with version 1 object files. See
the subdirectory v1 for programs that perform that task.
Note: If you do not have a v1 subdirectory, you may have unpacked the
ZIP file without specifying the 'restore directory structure' option -
delete these files, and run your ZIP extracter again with this option
turned on ('-d' for PKUNZIP).
RDOFF version 1 is no longer really supported, you should be using
v2 instead now.
exception of 'rdfdump') will NOT work with version 1 object files. Version 1
of RDOFF is no longer supported. You should be using v2 instead now.
There is also a 'Changes' file, which documents the differences between
RDOFF 1 and 2, and an 'rdoff2.txt' file, with complete documentation for the

View File

@ -29,13 +29,14 @@
#include <stdlib.h>
#include <string.h>
#include "multboot.h"
#include "rdoff.h"
#include "symtab.h"
#include "collectn.h"
#include "rdlib.h"
#include "segtab.h"
#define LDRDF_VERSION "1.00 alpha 1"
#define LDRDF_VERSION "1.02"
#define RDF_MAXSEGS 64
/* #define STINGY_MEMORY */
@ -91,6 +92,44 @@ struct librarynode * lastlib = NULL;
/* the symbol table */
void * symtab = NULL;
/* objects search path */
char * objpath = NULL;
/* libraries search path */
char * libpath = NULL;
/* error file */
static FILE * error_file;
#ifdef _MULTBOOT_H
/* loading address for multiboot header */
unsigned MBHloadAddr;
/*
* Tiny code that moves RDF loader to its working memory region:
* mov esi,SOURCE_ADDR ; BE xx xx xx xx
* mov edi,DEST_ADDR ; BF xx xx xx xx
* mov esp,edi ; 89 FC
* push edi ; 57
* mov ecx,RDFLDR_LENGTH/4 ; B9 xx xx xx xx
* cld ; FC
* rep movsd ; F3 A5
* ret ; C3
*/
#define RDFLDR_LENGTH 4096 /* Loader will be moved to unused */
#define RDFLDR_DESTLOC 0xBF000 /* video page */
unsigned char RDFloaderMover[]={
0xBE, 0, 0, 0, 0, 0xBF, 0, 0xF0, 0xB, 0,
0x89, 0xFC, 0x57,
0xB9, 0, 4, 0, 0,
0xFC, 0xF3, 0xA5, 0xC3
};
#endif
/* the header of the output file, built up stage by stage */
rdf_headerbuf * newheader = NULL;
@ -107,7 +146,13 @@ struct ldrdfoptions {
int verbose;
int align;
int warnUnresolved;
int errorUnresolved;
int strip;
int respfile;
int stderr_redir;
int objpath;
int libpath;
int addMBheader;
} options;
int errorcount = 0; /* determines main program exit status */
@ -305,11 +350,26 @@ void processmodule(const char * filename, struct modulenode * mod)
break;
case 3: /* exported symbol */
if (mod->seginfo[(int)hr->e.segment].dest_seg == -1)
continue;
symtab_add(hr->e.label, mod->seginfo[(int)hr->e.segment].dest_seg,
mod->seginfo[(int)hr->e.segment].reloc + hr->e.offset);
{
int destseg;
long destreloc;
if (hr->e.segment == 2)
{
destreloc = bss_length;
if (destreloc % options.align != 0)
destreloc += options.align - (destreloc % options.align);
destseg = 2;
}
else
{
if ((destseg = mod->seginfo[(int)hr->e.segment].dest_seg) == -1)
continue;
destreloc = mod->seginfo[(int)hr->e.segment].reloc;
}
symtab_add(hr->e.label, destseg, destreloc + hr->e.offset);
break;
}
case 5: /* BSS reservation */
/*
@ -353,6 +413,22 @@ void processmodule(const char * filename, struct modulenode * mod)
}
/*
* Look in list for module by its name.
*/
int lookformodule(const char *name)
{
struct modulenode *curr=modules;
while(curr) {
if (!strcmp(name,curr->name)) return 1;
curr = curr->next;
}
return 0;
}
/*
* allocnewseg()
* findsegment()
@ -415,7 +491,7 @@ void symtab_add(const char * symbol, int segment, long offset)
* symbol previously defined
*/
if (segment < 0) return;
fprintf (stderr, "warning: `%s' redefined\n", symbol);
fprintf (error_file, "warning: `%s' redefined\n", symbol);
return;
}
@ -502,6 +578,7 @@ void add_library(const char * name)
}
lastlib = lastlib->next;
}
lastlib->next = NULL;
if (rdl_open(lastlib, name)) {
rdl_perror("ldrdf", name);
errorcount++;
@ -528,7 +605,7 @@ int search_libraries()
void * header;
int segment;
long offset;
int doneanything = 0, keepfile;
int doneanything = 0, pass = 1, keepfile;
rdfheaderrec * hr;
cur = libraries;
@ -536,10 +613,12 @@ int search_libraries()
while (cur)
{
if (options.verbose > 2)
printf("scanning library `%s'...\n", cur->name);
printf("scanning library `%s', pass %d...\n", cur->name, pass);
for (i = 0; rdl_openmodule(cur, i, &f) == 0; i++)
{
if (pass == 2 && lookformodule(f.name)) continue;
if (options.verbose > 3)
printf(" looking in module `%s'\n", f.name);
@ -591,15 +670,25 @@ int search_libraries()
lastmodule = lastmodule->next;
memcpy(&lastmodule->f, &f, sizeof(f));
lastmodule->name = strdup(f.name);
lastmodule->next = NULL;
processmodule(f.name, lastmodule);
break;
}
if (!keepfile)
rdfclose(&f);
{
free(f.name);
f.name = NULL;
f.fp = NULL;
}
}
if (rdl_error != 0 && rdl_error != RDL_ENOTFOUND)
rdl_perror("ldrdf", cur->name);
cur = cur->next;
if (cur == NULL && pass == 1) {
cur = libraries;
pass++;
}
}
return doneanything;
@ -614,8 +703,8 @@ int search_libraries()
*/
void write_output(const char * filename)
{
FILE * f = fopen(filename, "wb");
rdf_headerbuf * rdfheader = rdfnewheader();
FILE * f;
rdf_headerbuf * rdfheader;
struct modulenode * cur;
int i, availableseg, seg, localseg, isrelative;
void * header;
@ -625,18 +714,43 @@ void write_output(const char * filename)
long offset;
byte * data;
if (!f) {
if ((f = fopen(filename, "wb"))==NULL) {
fprintf(stderr, "ldrdf: couldn't open %s for output\n", filename);
exit(1);
}
if (!rdfheader) {
if ((rdfheader=rdfnewheader())==NULL) {
fprintf(stderr, "ldrdf: out of memory\n");
exit(1);
}
/*
* Add multiboot header if appropriate option is specified.
* Multiboot record *MUST* be the first record in output file.
*/
if (options.addMBheader) {
if (options.verbose)
puts("\nadding multiboot header record");
hr = (rdfheaderrec *) malloc(sizeof(struct MultiBootHdrRec));
hr->mbh.type = 9;
hr->mbh.reclen = sizeof(struct tMultiBootHeader)+RDFLDRMOVER_SIZE;
hr->mbh.mb.Magic = MB_MAGIC;
hr->mbh.mb.Flags = MB_FL_KLUDGE;
hr->mbh.mb.Checksum = ~(MB_MAGIC+MB_FL_KLUDGE-1);
hr->mbh.mb.HeaderAddr = MBHloadAddr+16;
hr->mbh.mb.LoadAddr = MBHloadAddr;
hr->mbh.mb.Entry = MBHloadAddr+16+sizeof(struct tMultiBootHeader);
memcpy(hr->mbh.mover,RDFloaderMover,RDFLDRMOVER_SIZE);
rdfaddheader(rdfheader,hr);
free(hr);
}
if (options.verbose)
printf ("\nbuilding output module (%d segments)\n", nsegs);
/*
* Allocate the memory for the segments. We may be better off
* building the output module one segment at a time when running
@ -645,6 +759,8 @@ void write_output(const char * filename)
*/
for (i = 0; i < nsegs; i++)
{
outputseg[i].data=NULL;
if(!outputseg[i].length) continue;
outputseg[i].data = malloc(outputseg[i].length);
if (!outputseg[i].data) {
fprintf(stderr, "ldrdf: out of memory\n");
@ -714,7 +830,7 @@ void write_output(const char * filename)
* and the BSS segment (doh!)
*/
add_seglocation (&segs, 2, 2, cur->bss_reloc);
while ((hr = rdfgetheaderrec(&cur->f)))
{
switch(hr->type) {
@ -786,7 +902,7 @@ void write_output(const char * filename)
case 1:
offset += *data;
if (offset < -127 || offset > 128)
fprintf(stderr, "warning: relocation out of range "
fprintf(error_file, "warning: relocation out of range "
"at %s(%02x:%08lx)\n", cur->name,
(int)hr->r.segment, hr->r.offset);
*data = (char) offset;
@ -794,7 +910,7 @@ void write_output(const char * filename)
case 2:
offset += * (short *)data;
if (offset < -32767 || offset > 32768)
fprintf(stderr, "warning: relocation out of range "
fprintf(error_file, "warning: relocation out of range "
"at %s(%02x:%08lx)\n", cur->name,
(int)hr->r.segment, hr->r.offset);
* (short *)data = (short) offset;
@ -832,8 +948,9 @@ void write_output(const char * filename)
se = symtabFind(symtab, hr->i.label);
if (!se || se->segment == -1) {
if (options.warnUnresolved) {
fprintf(stderr, "warning: unresolved reference to `%s'"
fprintf(error_file, "warning: unresolved reference to `%s'"
" in module `%s'\n", hr->i.label, cur->name);
if (options.errorUnresolved==1) errorcount++;
}
/*
* we need to allocate a segment number for this
@ -900,6 +1017,16 @@ void write_output(const char * filename)
rdfaddheader(rdfheader, hr);
break;
case 8: /* module name */
/*
* insert module name record if export symbols
* are not stripped.
*/
if (options.strip) break;
rdfaddheader(rdfheader, hr);
break;
case 6: /* segment fixup */
/*
* modify the segment numbers if necessary, and
@ -939,7 +1066,7 @@ void write_output(const char * filename)
free(header);
done_seglocations(&segs);
}
}
/*
* combined BSS reservation for the entire results
@ -957,6 +1084,18 @@ void write_output(const char * filename)
if (i == 2) continue;
rdfaddsegment (rdfheader, outputseg[i].length);
}
if (options.addMBheader) {
struct MultiBootHdrRec *mbhrec = (struct MultiBootHdrRec *)(rdfheader->buf->buffer);
unsigned l = membuflength(rdfheader->buf) + 14 +
10*rdfheader->nsegments + rdfheader->seglength;
unsigned *ldraddr = (unsigned *)(mbhrec->mover+1);
mbhrec->mb.LoadEndAddr = MBHloadAddr+l+10+RDFLDR_LENGTH;
mbhrec->mb.BSSendAddr = mbhrec->mb.LoadEndAddr;
*ldraddr = MBHloadAddr+l+10;
}
rdfwriteheader(f, rdfheader);
rdfdoneheader(rdfheader);
/*
@ -996,14 +1135,15 @@ void usage()
printf(" ldrdf [options] object modules ... [-llibrary ...]\n");
printf(" ldrdf -r\n");
printf("options:\n");
printf(" -v[=n] increases verbosity by 1, or sets it to n\n");
printf(" -a nn sets segment alignment value (default 16)\n");
printf(" -s strips exported symbols\n");
printf(" -x warn about unresolved symbols\n");
printf(" -o name write output in file 'name'\n");
printf("\n");
printf("Note: no library searching is performed. Please specify full\n");
printf("paths to all files referenced.\n");
printf(" -v[=n] increases verbosity by 1, or sets it to n\n");
printf(" -a nn sets segment alignment value (default 16)\n");
printf(" -s strips exported symbols\n");
printf(" -x warn about unresolved symbols\n");
printf(" -o name write output in file 'name'\n");
printf(" -j path specify objects search path\n");
printf(" -L path specify libraries search path\n");
printf(" -mbh [address] add multiboot header to output file. Default\n");
printf(" loading address is 0x110000\n");
exit(0);
}
@ -1011,12 +1151,15 @@ int main(int argc, char ** argv)
{
char * outname = "aout.rdf";
int moduleloaded = 0;
char *respstrings[128] = {0, };
options.verbose = 0;
options.align = 16;
options.warnUnresolved = 0;
options.strip = 0;
error_file = stderr;
argc --, argv ++;
if (argc == 0) usage();
while (argc && **argv == '-' && argv[0][1] != 'l')
@ -1041,7 +1184,7 @@ int main(int argc, char ** argv)
case 'a':
options.align = atoi(argv[1]);
if (options.align <= 0) {
fprintf(stderr,
fprintf(stderr,
"ldrdf: -a expects a positive number argument\n");
exit(1);
}
@ -1052,17 +1195,94 @@ int main(int argc, char ** argv)
break;
case 'x':
options.warnUnresolved = 1;
if (argv[0][2]=='e')
options.errorUnresolved = 1;
break;
case 'o':
outname = argv[1];
argv++, argc--;
break;
case 'j':
if (!objpath)
{
options.objpath = 1;
objpath = argv[1];
argv++, argc--;
break;
}
else
{
fprintf(stderr,"ldrdf: more than one objects search path specified\n");
exit(1);
}
case 'L':
if (!libpath)
{
options.libpath = 1;
libpath = argv[1];
argv++, argc--;
break;
}
else
{
fprintf(stderr,"ldrdf: more than one libraries search path specified\n");
exit(1);
}
case '@': {
int i=0;
char buf[256];
FILE *f;
options.respfile = 1;
if (argv[1] != NULL) f = fopen(argv[1],"r");
else
{
fprintf(stderr,"ldrdf: no response file name specified\n");
exit(1);
}
if (f == NULL)
{
fprintf(stderr,"ldrdf: unable to open response file\n");
exit(1);
}
argc-=2;
while(fgets(buf,sizeof(buf)-1,f)!=NULL)
{
char *p;
if (buf[0]=='\n') continue;
if ((p = strchr(buf,'\n')) != 0)
*p=0;
if (i >= 128)
{
fprintf(stderr,"ldrdf: too many input files\n");
exit(1);
}
*(respstrings+i) = newstr(buf);
argc++, i++;
}
goto done;
}
case '2':
options.stderr_redir = 1;
error_file = stdout;
break;
case 'm':
if (argv[0][2] == 'b' && argv[0][3] == 'h') {
if (argv[1][0] != '-') {
MBHloadAddr = atoi(argv[1]);
} else {
MBHloadAddr = MB_DEFAULTLOADADDR;
}
options.addMBheader = 1;
break;
}
default:
usage();
}
argv++, argc--;
}
done:
if (options.verbose > 4) {
printf("ldrdf invoked with options:\n");
printf(" section alignment: %d bytes\n", options.align);
@ -1071,6 +1291,14 @@ int main(int argc, char ** argv)
printf(" strip symbols\n");
if (options.warnUnresolved)
printf(" warn about unresolved symbols\n");
if (options.errorUnresolved)
printf(" error if unresolved symbols\n");
if (options.objpath)
printf(" objects search path: %s\n",objpath);
if (options.libpath)
printf(" libraries search path: %s\n",libpath);
if (options.addMBheader)
printf(" loading address for multiboot header: 0x%X\n",MBHloadAddr);
printf("\n");
}
@ -1082,12 +1310,17 @@ int main(int argc, char ** argv)
exit(1);
}
if (*respstrings) argv = respstrings;
while (argc)
{
if (!strncmp(*argv, "-l", 2)) /* library */
add_library(*argv + 2);
{
if(libpath) add_library(newstrcat(libpath,*argv + 2));
else add_library(*argv + 2);
}
else {
loadmodule(*argv);
if(objpath) loadmodule(newstrcat(objpath,*argv));
else loadmodule(*argv);
moduleloaded = 1;
}
argv++, argc--;
@ -1098,7 +1331,7 @@ int main(int argc, char ** argv)
return 0;
}
search_libraries();
if (options.verbose > 2)
@ -1109,9 +1342,6 @@ int main(int argc, char ** argv)
write_output(outname);
if (errorcount > 0)
exit(1);
if (errorcount > 0) exit(1);
return 0;
}

27
rdoff/multboot.h Normal file
View File

@ -0,0 +1,27 @@
/******************************************************************************
multboot.h - MultiBoot header definitions.
******************************************************************************/
#ifndef _MULTBOOT_H
#define _MULTBOOT_H
#define MB_MAGIC 0x1BADB002
#define MB_FL_PGALIGN 1 /* Align boot modules on page */
#define MB_FL_MEMINFO 2 /* Must pass memory info to OS */
#define MB_FL_KLUDGE 0x10000 /* a.out kludge present */
struct tMultiBootHeader {
unsigned Magic;
unsigned Flags;
unsigned Checksum;
unsigned HeaderAddr;
unsigned LoadAddr;
unsigned LoadEndAddr;
unsigned BSSendAddr;
unsigned Entry;
};
#define MB_DEFAULTLOADADDR 0x110000 /* Default loading address */
#endif

View File

@ -29,7 +29,7 @@ int main(int argc, char **argv)
int tmp;
FILE *of;
char * padding;
int codepad, datapad;
int codepad, datapad, bsspad=0;
if (argc < 2) {
puts("Usage: rdf2bin [-o relocation-origin] [-p segment-alignment] "
@ -58,6 +58,13 @@ int main(int argc, char **argv)
fprintf(stderr,"rdf2bin: invalid parameter: %s\n",*argv);
return 1;
}
} else if (! strcmp(*argv,"-b")) {
argv++, argc--;
bsspad = readnum(*argv, &tmp);
if (tmp) {
fprintf(stderr,"rdf2bin: invalid parameter: %s\n",*argv);
return 1;
}
} else
break;
@ -69,8 +76,7 @@ int main(int argc, char **argv)
}
m = rdfload(*argv);
if (! m)
{
if (! m) {
rdfperror("rdf2bin",*argv);
return 1;
}
@ -119,6 +125,11 @@ int main(int argc, char **argv)
fprintf(stderr,"rdf2bin: error writing to %s\n", *argv);
return 1;
}
if (bsspad) {
void *p = calloc(bsspad-=(m->bssrel - origin),1);
fwrite(p,1,bsspad,of);
}
fclose(of);
return 0;

189
rdoff/rdf2ihx.c Normal file
View File

@ -0,0 +1,189 @@
/* rdf2ihx: convert an RDOFF object file to Intel Hex format. This is based
on rdf2bin. Note that this program only writes 16-bit HEX. */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "rdfload.h"
#include "rdoff.h"
#include "nasmlib.h"
#include "symtab.h"
long origin = 0;
int align = 16;
/* This function writes a single n-byte data record to of. Maximum value
for n is 255. */
static int write_data_record(FILE *of, int ofs, int nbytes,
unsigned char *data)
{
int i, iofs;
unsigned int checksum;
iofs = ofs;
fprintf(of, ":%02X%04X00", nbytes, ofs);
checksum = 0;
for (i=0; i<nbytes; i++) {
fprintf(of, "%02X", data[i]);
ofs++;
checksum += data[i];
}
checksum = checksum + /* current checksum */
nbytes + /* RECLEN (one byte) */
((iofs >> 8) & 0xff) + /* high byte of load offset */
(iofs & 0xff); /* low byte of load offset */
checksum = ~checksum + 1;
fprintf(of, "%02X\n", checksum&0xff);
return(ofs);
}
int main(int argc, char **argv)
{
rdfmodule *m;
int tmp;
FILE *of;
char *padding;
unsigned char *segbin[2];
int pad[2], segn, ofs, i;
long segaddr;
unsigned int checksum;
symtabEnt *s;
if (argc < 2) {
puts("Usage: rdf2ihx [-o relocation-origin] [-p segment-alignment] "
"input-file output-file");
return(1);
}
argv++, argc--;
while (argc > 2) {
if (strcmp(*argv,"-o") == 0) {
argv++, argc--;
origin = readnum(*argv, &tmp);
if (tmp) {
fprintf(stderr,"rdf2ihx: invalid parameter: %s\n",*argv);
return 1;
}
} else if (strcmp(*argv,"-p") == 0) {
argv++, argc--;
align = readnum(*argv, &tmp);
if (tmp) {
fprintf(stderr,"rdf2ihx: invalid parameter: %s\n",*argv);
return 1;
}
} else
break;
argv++, argc--;
}
if (argc < 2) {
puts("rdf2bin: required parameter missing");
return -1;
}
m = rdfload(*argv);
if (!m) {
rdfperror("rdf2bin",*argv);
return 1;
}
printf("relocating %s: origin=%lx, align=%d\n",*argv, origin, align);
m->textrel = origin;
m->datarel = origin + m->f.seg[0].length;
if (m->datarel % align != 0) {
pad[0] = align - (m->datarel % align);
m->datarel += pad[0];
} else {
pad[0] = 0;
}
m->bssrel = m->datarel + m->f.seg[1].length;
if (m->bssrel % align != 0) {
pad[1] = align - (m->bssrel % align);
m->bssrel += pad[1];
} else {
pad[1] = 0;
}
printf("code: %08lx\ndata: %08lx\nbss: %08lx\n",
m->textrel, m->datarel, m->bssrel);
rdf_relocate(m);
argv++;
of = fopen(*argv,"w");
if (!of) {
fprintf(stderr,"rdf2ihx: could not open output file %s\n",*argv);
return(1);
}
padding = malloc(align);
if (!padding) {
fprintf(stderr,"rdf2ihx: out of memory\n");
return(1);
}
/* write extended segment address record */
fprintf(of, ":02000002"); /* Record mark, reclen, load offset & rectyp
fields for ext. seg. address record */
segaddr = ((origin >> 16) & 0xffff); /* segment address */
fprintf(of, "%04X", (unsigned int)(segaddr & 0xffff));
checksum = 0x02 + /* reclen */
0x0000 + /* Load Offset */
0x02 + /* Rectyp */
(segaddr & 0xff) + /* USBA low */
((segaddr >> 8) & 0xff); /* USBA high */
checksum = ~checksum + 1; /* two's-complement the checksum */
fprintf(of, "%02X\n", checksum & 0xff);
/* See if there's a '_main' symbol in the symbol table */
if ((s=symtabFind(m->symtab, "_main")) == NULL) {
printf("No _main symbol found, no start segment address record added\n");
} else {
printf("_main symbol found at %04x:%04x\n", s->segment,
(unsigned int)(s->offset & 0xffff));
/* Create a start segment address record for the _main symbol. */
segaddr = ((s->segment & 0xffff) << 16) + ((s->offset) & 0xffff);
fprintf(of, ":04000003"); /* Record mark, reclen, load offset & rectyp
fields for start seg. addr. record */
fprintf(of, "%08lX", segaddr); /* CS/IP field */
checksum = 0x04 + /* reclen */
0x0000 + /* load offset */
0x03 + /* Rectyp */
(segaddr & 0xff) + /* low-low byte of segaddr */
((segaddr >> 8) & 0xff) + /* low-high byte of segaddr */
((segaddr >> 16) & 0xff) + /* high-low byte of segaddr */
((segaddr >> 24) & 0xff); /* high-high byte of segaddr */
checksum = ~checksum + 1; /* two's complement */
fprintf(of, "%02X\n", checksum & 0xff);
}
/* Now it's time to write data records from the code and data segments in.
This current version doesn't check for segment overflow; proper behavior
should be to output a segment address record for the code and data
segments. Something to do. */
ofs = 0;
segbin[0] = m->t;
segbin[1] = m->d;
for (segn=0; segn<2; segn++) {
int mod, adr;
if (m->f.seg[segn].length == 0)
continue;
for (i=0; i+15<m->f.seg[segn].length; i+=16) {
ofs = write_data_record(of, ofs, 16, &segbin[segn][i]);
}
if ((mod=m->f.seg[segn].length & 0x000f) != 0) {
adr = m->f.seg[segn].length & 0xfff0;
ofs = write_data_record(of, ofs, mod, &segbin[segn][adr]);
}
}
/* output an end of file record */
fprintf(of, ":00000001FF\n");
fclose(of);
return 0;
}

View File

@ -2,6 +2,8 @@
#include <stdlib.h>
#include <string.h>
#include "multboot.h"
FILE *infile;
typedef unsigned short int16;
@ -35,6 +37,7 @@ void print_header(long length, int rdf_version) {
unsigned char reclen;
long o,ll;
int16 rs;
struct tMultiBootHeader *mb;
while (length > 0) {
fread(&t,1,1,infile);
@ -47,7 +50,7 @@ void print_header(long length, int rdf_version) {
fread(&s,1,1,infile);
fread(&o,4,1,infile);
fread(&l,1,1,infile);
fread(&rs,2,1,infile);
fread(&rs,2,1,infile);
printf(" %s: location (%04x:%08lx), length %d, "
"referred seg %04x\n", t == 1 ? "relocation" : "seg relocation",
(int)s,translatelong(o),(int)l,
@ -98,7 +101,8 @@ void print_header(long length, int rdf_version) {
printf(" export: (%04x:%08lx) = %s\n",(int)s,translatelong(o),buf);
if (rdf_version == 1) length -= ll + 6;
break;
case 4: /* DLL record */
case 4: /* DLL and Module records */
case 8:
ll = 0;
if (rdf_version == 1) {
@ -108,10 +112,11 @@ void print_header(long length, int rdf_version) {
}
else
{
for (; ll < reclen - 1; ll++)
for (; ll < reclen; ll++)
fread(&buf[ll],1,1,infile);
}
printf(" dll: %s\n",buf);
if (t==4) printf(" dll: %s\n",buf);
else printf(" module: %s\n",buf);
if (rdf_version == 1) length -= ll + 1;
break;
case 5: /* BSS reservation */
@ -121,9 +126,19 @@ void print_header(long length, int rdf_version) {
if (rdf_version > 1 && reclen != 4)
printf(" warning: reclen != 4\n");
break;
case 9: /* MultiBoot header record */
fread(buf,reclen,1,infile);
mb = (struct tMultiBootHeader *)buf;
printf(" multiboot header: load address=0x%X, size=0x%X, entry=0x%X\n",
mb->LoadAddr, mb->LoadEndAddr - mb->LoadAddr, mb->Entry);
break;
default:
printf(" unrecognised record (type %d",(int)t);
if (rdf_version > 1) printf(", length %d",(int)reclen);
if (rdf_version > 1) {
printf(", length %d",(int)reclen);
fseek(infile,reclen,SEEK_CUR);
}
printf(")\n");
if (rdf_version == 1) length --;
}
@ -158,7 +173,7 @@ int main(int argc,char **argv) {
long headerlength = 0;
long objectlength = 0;
puts("RDOFF Dump utility v2.0 (C) Copyright 1996 Julian R Hall");
puts("RDOFF Dump utility v2.1\n(c) Copyright 1996,99,2000 Julian R Hall, Yuri M Zaporogets");
if (argc < 2) {
fputs("Usage: rdfdump [-v] <filename>\n",stderr);
@ -178,7 +193,7 @@ int main(int argc,char **argv) {
infile = fopen(argv[1],"rb");
if (! infile) {
fprintf(stderr,"rdfdump: Could not open %s",argv[1]);
fprintf(stderr,"rdfdump: Could not open %s\n",argv[1]);
exit(1);
}

View File

@ -29,12 +29,13 @@ extern int rdf_errno;
rdfmodule * rdfload(const char *filename)
{
rdfmodule * f = malloc(sizeof(rdfmodule));
rdfmodule * f;
long bsslength = 0;
char * hdr;
rdfheaderrec *r;
if (f == NULL)
f = malloc(sizeof(rdfmodule));
if (f == NULL)
{
rdf_errno = 6; /* out of memory */
return NULL;
@ -92,7 +93,7 @@ rdfmodule * rdfload(const char *filename)
}
f->b = malloc ( bsslength );
if (! f->b )
if (bsslength && (!f->b))
{
free(f->t);
free(f->d);

View File

@ -24,6 +24,7 @@
#include <string.h>
#include <errno.h>
#include "multboot.h"
#include "rdoff.h"
#define newstr(str) strcpy(malloc(strlen(str) + 1),str)
@ -49,13 +50,14 @@ memorybuffer * newmembuf()
memorybuffer * t;
t = malloc(sizeof(memorybuffer));
if (!t) return NULL;
t->length = 0;
t->next = NULL;
return t;
}
void membufwrite(memorybuffer *b, void *data, int bytes)
void membufwrite(memorybuffer *const b, void *data, int bytes)
{
int16 w;
long l;
@ -276,7 +278,10 @@ int rdfopenhere(rdffile *f, FILE *fp, int *refcount, const char *name)
int rdfclose(rdffile *f)
{
if (! f->refcount || ! --(*f->refcount))
fclose(f->fp);
{
fclose(f->fp);
f->fp = NULL;
}
free(f->name);
return 0;
@ -400,6 +405,10 @@ rdfheaderrec *rdfgetheaderrec(rdffile *f)
RI32(r.b.amount);
break;
case 8: /* Module name record */
RS(r.m.modname,127);
break;
default:
#ifdef STRICT_ERRORS
rdf_errno = 8; /* unknown header record */
@ -420,7 +429,7 @@ void rdfheaderrewind(rdffile *f)
rdf_headerbuf * rdfnewheader(void)
{
rdf_headerbuf * hb = malloc(sizeof(hb));
rdf_headerbuf * hb = malloc(sizeof(rdf_headerbuf));
if (hb == NULL) return NULL;
hb->buf = newmembuf();
@ -468,6 +477,16 @@ int rdfaddheader(rdf_headerbuf * h, rdfheaderrec * r)
membufwrite(h->buf,&r->b.amount,-4);
break ;
case 8: /* Module name */
membufwrite(h->buf,&r->m.modname,strlen(r->m.modname) + 1);
break ;
#ifdef _MULTBOOT_H
case 9: /* MultiBoot header */
membufwrite(h->buf,&r->mbh.mb,sizeof(struct tMultiBootHeader)+RDFLDRMOVER_SIZE);
break ;
#endif
default:
#ifdef STRICT_ERRORS
return (rdf_errno = 8);
@ -509,3 +528,4 @@ void rdfdoneheader(rdf_headerbuf * h)
freemembuf(h->buf);
free(h);
}

View File

@ -9,7 +9,7 @@
* as acknowledgement is given in an appropriate manner to its authors,
* with instructions of how to obtain a copy via ftp.
*/
#ifndef _RDOFF_H
#define _RDOFF_H "RDOFF2 support routines v0.3"
@ -48,7 +48,7 @@ struct ImportRec {
struct ExportRec {
byte type; /* must be 3 */
byte reclen; /* content length */
byte segment; /* segment referred to (0/1) */
byte segment; /* segment referred to (0/1/2) */
long offset; /* offset within segment */
char label[33]; /* zero terminated as above. max len = 32 chars */
};
@ -65,6 +65,28 @@ struct BSSRec {
long amount; /* number of bytes BSS to reserve */
};
struct ModRec {
byte type; /* must be 8 */
byte reclen; /* content length */
char modname[128]; /* module name */
};
#ifdef _MULTBOOT_H
#define RDFLDRMOVER_SIZE 22
struct MultiBootHdrRec {
byte type; /* must be 9 */
byte reclen; /* content length */
#ifdef __GNUC__
struct tMultiBootHeader mb __attribute__ ((packed)); /* MultiBoot header */
#else
struct tMultiBootHeader mb;
#endif
byte mover[RDFLDRMOVER_SIZE]; /* Mover of RDF loader */
};
#endif
/* GenericRec - contains the type and length field, plus a 128 byte
char array 'data', which will probably never be used! */
@ -82,6 +104,10 @@ typedef union RDFHeaderRec {
struct ExportRec e; /* type == 3 */
struct DLLRec d; /* type == 4 */
struct BSSRec b; /* type == 5 */
struct ModRec m; /* type == 8 */
#ifdef _MULTBOOT_H
struct MultiBootHdrRec mbh; /* type == 9 */
#endif
} rdfheaderrec;
struct SegmentHeaderRec {
@ -167,4 +193,7 @@ int rdfaddsegment(rdf_headerbuf *h, long seglength);
int rdfwriteheader(FILE *fp,rdf_headerbuf *h);
void rdfdoneheader(rdf_headerbuf *h);
/* This is needed by linker to write multiboot header record */
int membuflength(memorybuffer *b);
#endif /* _RDOFF_H */

View File

@ -9,6 +9,7 @@
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include "symtab.h"
@ -106,6 +107,7 @@ symtabDump(void *stab, FILE* of)
{
symtab mytab = (symtab)stab;
int i;
char *SegNames[3]={"code","data","bss"};
fprintf(of, "Symbol table is ...\n");
for (i=0; i < SYMTABSIZE; ++i) {
@ -116,7 +118,7 @@ symtabDump(void *stab, FILE* of)
}
while(l) {
fprintf(of, "%-32s %s:%08lx (%ld)\n",l->ent.name,
l->ent.segment ? "data" : "code" ,
SegNames[l->ent.segment],
l->ent.offset, l->ent.flags);
l = l->next;
}

213
scitech.txt Normal file
View File

@ -0,0 +1,213 @@
The Netwide Assembler: NASM
===========================
--------------------------------------------------------------------------------
SciTech MGL Modifications
--------------------------------------------------------------------------------
All changes can be compiled in and out using the TASM_COMPAT macros,
and when compiled without TASM_COMPAT defined we get the exact same
binary as the unmodified 0.98 sources.
standard.mac:
macros.c:
. Added macros to ignore TASM directives before first include
nasm.h:
. Added extern declaration for tasm_compatible_mode
nasm.c:
. Added global variable tasm_compatible_mode
. Added command line switch for TASM compatible mode (-t)
. Changed version command line to reflect when compiled with TASM additions
. Added response file processing to allow all arguments on a single
line (response file is @resp rather than -@resp for NASM format).
labels.c:
. Changes islocal() macro to support TASM style @@local labels.
. Added islocalchar() macro to support TASM style @@local labels.
parser.c:
. Added support for TASM style memory references (ie: mov [DWORD eax],10
rather than the NASM style mov DWORD [eax],10).
preproc.c:
. Added new directives, %arg, %local, %stacksize to directives table
. Added support for TASM style directives without a leading % symbol.
--------------------------------------------------------------------------------
Integrated a block of changes from Andrew Zabolotny <bit@eltech.ru>:
--------------------------------------------------------------------------------
-*- A new keyword %xdefine and its case-insensitive counterpart %ixdefine.
They work almost the same way as %define and %idefine but expand
the definition immediately, not on the invocation. Something like a cross
between %define and %assign. The "x" suffix stands for "eXpand", so
"xdefine" can be deciphered as "expand-and-define". Thus you can do
things like this:
%assign ofs 0
%macro arg 1
%xdefine %1 dword [esp+ofs]
%assign ofs ofs+4
%endmacro
-*- Changed the place where the expansion of %$name macros are expanded.
Now they are converted into ..@ctxnum.name form when detokenizing, so
there are no quirks as before when using %$name arguments to macros,
in macros etc. For example:
%macro abc 1
%define %1 hello
%endm
abc %$here
%$here
Now last line will be expanded into "hello" as expected. This also allows
for lots of goodies, a good example are extended "proc" macros included
in this archive.
-*- Added a check for "cstk" in smacro_defined() before calling get_ctx() -
this allows for things like:
%ifdef %$abc
%endif
to work without warnings even in no context.
-*- Added a check for "cstk" in %if*ctx and %elif*ctx directives -
this allows to use %ifctx without excessive warnings. If there is
no active context, %ifctx goes through "false" branch.
-*- Removed "user error: " prefix with %error directive: it just clobbers the
output and has absolutely no functionality. Besides, this allows to write
macros that does not differ from built-in functions in any way.
-*- Added expansion of string that is output by %error directive. Now you
can do things like:
%define hello(x) Hello, x!
%define %$name andy
%error "hello(%$name)"
Same happened with %include directive.
-*- Now all directives that expect an identifier will try to expand and
concatenate everything without whitespaces in between before usage.
For example, with "unfixed" nasm the commands
%define %$abc hello
%define __%$abc goodbye
__%$abc
would produce "incorrect" output: last line will expand to
hello goodbyehello
Not quite what you expected, eh? :-) The answer is that preprocessor
treats the %define construct as if it would be
%define __ %$abc goodbye
(note the white space between __ and %$abc). After my "fix" it
will "correctly" expand into
goodbye
as expected. Note that I use quotes around words "correct", "incorrect"
etc because this is rather a feature not a bug; however current behaviour
is more logical (and allows more advanced macro usage :-).
Same change was applied to:
%push,%macro,%imacro,%define,%idefine,%xdefine,%ixdefine,
%assign,%iassign,%undef
-*- A new directive [WARNING {+|-}warning-id] have been added. It works only
if the assembly phase is enabled (i.e. it doesn't work with nasm -e).
-*- A new warning type: macro-selfref. By default this warning is disabled;
when enabled NASM warns when a macro self-references itself; for example
the following source:
[WARNING macro-selfref]
%macro push 1-*
%rep %0
push %1
%rotate 1
%endrep
%endmacro
push eax,ebx,ecx
will produce a warning, but if we remove the first line we won't see it
anymore (which is The Right Thing To Do {tm} IMHO since C preprocessor
eats such constructs without warnings at all).
-*- Added a "error" routine to preprocessor which always will set ERR_PASS1
bit in severity_code. This removes annoying repeated errors on first
and second passes from preprocessor.
-*- Added the %+ operator in single-line macros for concatenating two
identifiers. Usage example:
%define _myfunc _otherfunc
%define cextern(x) _ %+ x
cextern (myfunc)
After first expansion, third line will become "_myfunc". After this
expansion is performed again so it becomes "_otherunc".
-*- Now if preprocessor is in a non-emmitting state, no warning or error
will be emmitted. Example:
%if 1
mov eax,ebx
%else
put anything you want between these two brackets,
even macro-parameter references %1 or local labels %$zz
or macro-local labels %%zz - no warning will be emmitted.
%endif
-*- Context-local variables on expansion as a last resort are looked up
in outer contexts. For example, the following piece:
%push outer
%define %$a [esp]
%push inner
%$a
%pop
%pop
will expand correctly the fourth line to [esp]; if we'll define another
%$a inside the "inner" context, it will take precedence over outer
definition. However, this modification has been applied only to
expand_smacro and not to smacro_define: as a consequence expansion
looks in outer contexts, but %ifdef won't look in outer contexts.
This behaviour is needed because we don't want nested contexts to
act on already defined local macros. Example:
%define %$arg1 [esp+4]
test eax,eax
if nz
mov eax,%$arg1
endif
In this example the "if" mmacro enters into the "if" context, so %$arg1
is not valid anymore inside "if". Of course it could be worked around
by using explicitely %$$arg1 but this is ugly IMHO.
-*- Fixed memory leak in %undef. The origline wasn't freed before
exiting on success.
-*- Fixed trap in preprocessor when line expanded to empty set of tokens.
This happens, for example, in the following case:
#define SOMETHING
SOMETHING

View File

@ -96,3 +96,13 @@ __SECT__
[cpu %1]
%endmacro
; Macros to make NASM ignore some TASM directives before the first include
; directive.
%idefine IDEAL
%idefine JUMPS
%idefine P386
%idefine P486
%idefine P586
%idefine END

View File

@ -26,7 +26,7 @@
jmp start ; [6]
end mov ax,0x4c00 ; [1]
endX mov ax,0x4c00 ; [1]
int 0x21
start mov byte [bss_sym],',' ; [1] [8]
@ -49,7 +49,7 @@ start mov byte [bss_sym],',' ; [1] [8]
datasym db 'hello world', 13, 10, '$' ; [2]
bssptr dw bss_sym ; [2] [11]
dataptr dw datasym+5 ; [2] [10]
textptr dw end ; [2] [9]
textptr dw endX ; [2] [9]
SECTION .bss

View File

@ -1,62 +0,0 @@
segment text
bits 16
imul edx,[addr],10
imul eax,20
imul edx,eax,130
push 0x40
push word 0x40
push word 4095
push byte 0x40
push dword 0x40
push dword 4095
add ax,1
add bx,1
cmp cx,0
sub dx,3
sbb si,-1
xor ax,0xffff
xor ax,-1
xor bx,0xffff
xor bx,-1
adc bx,add1
adc bx,-7
adc bx,-128
adc bx,-129
adc bx,addr
adc bx,byte -7
add1: adc bx,word -7
adc bx,add1
resb 256
addr: nop
adc bx,addr
adc eax,5
adc eax,500
adc eax,byte 5
adc ax,4
adc ebx,7
adc ebx,700
adc ebx,byte 7
adc ecx,1
adc eax,1
shr edx,mmm
shr edx,one
adc ebx,byte mmm
m1: adc ebx,mmm
mmm equ 9
m2: adc ebx,mmm
one equ 1
shr edx,mmm
shr edx,one
shr edx,1
tend dw tend
segment data
db 'abc'
db '', 12, 13, 0

View File

@ -1,18 +0,0 @@
USE16
CPU 386
debugdump001:
goo: jmp foo
jc near foo
mov ax,[si+5]
mov ax,[si-7]
mov ax,[si+n]
nop
resb 10
foo: jmp goo
jc goo
jmp short goo
debugdump002: push 0
n equ 3

View File

@ -1,22 +0,0 @@
use32
cpu P3
debugdump001:
goo: jmp foo
; cpu 386
jc near foo
mov ax,[si+5]
mov ax,[si-7]
mov ax,[si+n]
align 16
; cpu 486
bswap edx
; cpu 186
resb 10
foo: jmp goo
jc goo
jmp short goo
debugdump002: push 0
n equ 3

View File

@ -1,45 +0,0 @@
debugdump001:
jc baker
jmp able - 20
jmp able
baker: nop
times 125 nop
able: jmp baker
jmp baker + 20
times 122 nop
jmp able
loc: nop
jc able+20
jmp able1 - 20
jmp able1
baker1: nop
times 126 nop
able1: jmp near baker1
jmp baker1 + 20
times 122 nop
jmp able1
loc1: nop
able2: jmp baker2
times 124 nop
jmp able2
nop
baker2: nop
able3: jmp baker3
times 124 nop
jmp able3
nop
nop
baker3: nop
debugdump099: nop

View File

@ -1,16 +0,0 @@
cpu 186
start: jmp able
xor ax,ax
jc start
jnc able
jc charlie
times 100 nop
able: jc start
times 100 nop
baker: jc start
times 100 nop
charlie: jc baker
jnc able
jmp start
end: db 0

View File

@ -1,16 +0,0 @@
cpu 386
start: jmp able
xor ax,ax
jc start
jnc able
jc charlie
times 100 nop
able: jc start
times 100 nop
baker: jc start
times 100 nop
charlie: jc baker
jnc able
jmp start
end: db 0

View File

@ -1,17 +0,0 @@
use32
cpu 186
start: jmp able
xor ax,ax
jc start
jnc able
jc charlie
times 100 nop
able: jc start
times 100 nop
baker: jc start
times 100 nop
charlie: jc baker
jnc able
jmp start
end: db 0

View File

@ -1,17 +0,0 @@
use32
cpu 386
start: jmp able
xor ax,ax
jc start
jnc able
jc charlie
times 100 nop
able: jc start
times 100 nop
baker: jc start
times 100 nop
charlie: jc baker
jnc able
jmp start
end: db 0

View File

@ -1,43 +0,0 @@
%macro pushm 1-*
%rep %0
%rotate -1
push %1
%endrep
%endmacro
%macro popm 1-*
%rep %0
pop %1
%rotate 1
%endrep
%endmacro
%macro pusha 0
push ax
push cx
push dx
push bx
push bp
mov bp,sp
lea bp,[bp+10]
xchg bp,[bp-10]
push bp
push si
push di
%endmacro
%macro popa 0
pop di
pop si
pop bp
pop bx
pop bx
pop dx
pop cx
pop ax
%endmacro
pushm ax,bx,cx,dx
popm ax,bx,cx,dx
pusha
popa

View File

@ -1,9 +0,0 @@
; test6.asm
; assemble with; nasm -O2 ...
;
%rep 20000
jmp forward
%endrep
forward: dd forward