mirror of
https://github.com/netwide-assembler/nasm.git
synced 2025-03-31 18:20:22 +08:00
NASM 0.98.08
This commit is contained in:
parent
af535c16cf
commit
1cd0e2d5bf
90
AUTHORS
Normal file
90
AUTHORS
Normal 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
|
||||
|
43
MODIFIED
43
MODIFIED
@ -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>.
|
||||
|
||||
|
@ -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
145
Mkfiles/Makefile.emx
Normal 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
|
||||
|
@ -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
187
README.1st
Normal 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
76
Readme
@ -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>
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
1032
doc/nasmdoc.src
1032
doc/nasmdoc.src
File diff suppressed because it is too large
Load Diff
37
doc/rdsrc.pl
37
doc/rdsrc.pl
@ -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
287
insns.dat
@ -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
|
||||
|
2
insns.h
2
insns.h
@ -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
108
labels.c
@ -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 "
|
||||
|
3
labels.h
3
labels.h
@ -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,
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -10,5 +10,6 @@
|
||||
#define NASM_LISTING_H
|
||||
|
||||
extern ListGen nasmlist;
|
||||
extern int user_nolist; /* fbk - 9/1/00 */
|
||||
|
||||
#endif
|
||||
|
9
macros.c
9
macros.c
@ -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
285
nasm.c
@ -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
32
nasm.h
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
6
outelf.c
6
outelf.c
@ -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;
|
||||
}
|
||||
|
44
outobj.c
44
outobj.c
@ -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) {
|
||||
|
58
outrdf2.c
58
outrdf2.c
@ -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
|
||||
|
80
parser.c
80
parser.c
@ -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
529
preproc.c
@ -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
441
proc32.ash
Normal 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
75
rdoff/Makefile.dj
Normal 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
76
rdoff/Makefile.emx
Normal 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
|
@ -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
|
||||
|
@ -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)
|
||||
|
||||
|
||||
|
12
rdoff/README
12
rdoff/README
@ -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
|
||||
|
304
rdoff/ldrdf.c
304
rdoff/ldrdf.c
@ -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
27
rdoff/multboot.h
Normal 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
|
@ -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
189
rdoff/rdf2ihx.c
Normal 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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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
213
scitech.txt
Normal 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
|
10
standard.mac
10
standard.mac
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -1,9 +0,0 @@
|
||||
; test6.asm
|
||||
; assemble with; nasm -O2 ...
|
||||
;
|
||||
%rep 20000
|
||||
jmp forward
|
||||
%endrep
|
||||
forward: dd forward
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user