NASM 0.98.26

This commit is contained in:
H. Peter Anvin 2002-04-30 21:08:42 +00:00
parent 9a633fa3b9
commit 005b39c856
50 changed files with 1259 additions and 6085 deletions

View File

@ -27,6 +27,7 @@ N: Frank Kotler
E: fbkotler@nettaxi.com
D: Bug smashing.
D: Documentation - "KATMAI" and "3DNow!" instructions supported by 0.98
D: General coordination and moral support.
N: Stephen Silver
E: nasm@argentum.freeserve.co.uk
@ -88,3 +89,8 @@ N: Edward J. Beroset
E: beroset@mindspring.com
D: added %substr and %strlen
N: Stanislav Karchebny, aka berkus, madfire, daemonhunter
E: madfire@users.sourceforge.net
D: multiple sections support for -fbin format
D: cvs maintenance
D: webpage at http://nasm.2y.net maintenance

6
ChangeLog Normal file
View File

@ -0,0 +1,6 @@
2002-04-11 Stanislav Karchebny <berk@madfire.net>
* Started ChangeLog instead of Changes. ChangeLog is better because all recent changes
are on top of the file, easy for inspection.
Old entries from doc/Changes will eventually be added here.

752
Doxyfile
View File

@ -1,752 +0,0 @@
# Doxyfile 1.2.5
# This file describes the settings to be used by doxygen for a project
#
# All text after a hash (#) is considered a comment and will be ignored
# The format is:
# TAG = value [value, ...]
# For lists items can also be appended using:
# TAG += value [value, ...]
# Values that contain spaces should be placed between quotes (" ")
#---------------------------------------------------------------------------
# General configuration options
#---------------------------------------------------------------------------
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
# by quotes) that should identify the project.
PROJECT_NAME = "NASM - the Netwide Assembler"
# The PROJECT_NUMBER tag can be used to enter a project or revision number.
# This could be handy for archiving the generated documentation or
# if some version control system is used.
PROJECT_NUMBER = 0.98
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.
# If a relative path is entered, it will be relative to the location
# where doxygen was started. If left blank the current directory will be used.
OUTPUT_DIRECTORY = doxy
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all constant output in the proper language.
# The default language is English, other supported languages are:
# Dutch, French, Italian, Czech, Swedish, German, Finnish, Japanese,
# Korean, Hungarian, Norwegian, Spanish, Romanian, Russian, Croatian,
# Polish, Portuguese and Slovene.
OUTPUT_LANGUAGE = English
# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
# documentation are documented, even if no documentation was available.
# Private class members and static file members will be hidden unless
# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
EXTRACT_ALL = YES
# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
# will be included in the documentation.
EXTRACT_PRIVATE = NO
# If the EXTRACT_STATIC tag is set to YES all static members of a file
# will be included in the documentation.
EXTRACT_STATIC = YES
# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
# undocumented members of documented classes, files or namespaces.
# If set to NO (the default) these members will be included in the
# various overviews, but no documentation section is generated.
# This option has no effect if EXTRACT_ALL is enabled.
HIDE_UNDOC_MEMBERS = NO
# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
# undocumented classes that are normally visible in the class hierarchy.
# If set to NO (the default) these class will be included in the various
# overviews. This option has no effect if EXTRACT_ALL is enabled.
HIDE_UNDOC_CLASSES = NO
# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
# include brief member descriptions after the members that are listed in
# the file and class documentation (similar to JavaDoc).
# Set to NO to disable this.
BRIEF_MEMBER_DESC = YES
# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
# the brief description of a member or function before the detailed description.
# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
# brief descriptions will be completely suppressed.
REPEAT_BRIEF = YES
# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
# Doxygen will generate a detailed section even if there is only a brief
# description.
ALWAYS_DETAILED_SEC = NO
# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
# path before files name in the file list and in the header files. If set
# to NO the shortest path that makes the file name unique will be used.
FULL_PATH_NAMES = NO
# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
# can be used to strip a user defined part of the path. Stripping is
# only done if one of the specified strings matches the left-hand part of
# the path. It is allowed to use relative paths in the argument list.
STRIP_FROM_PATH =
# The INTERNAL_DOCS tag determines if documentation
# that is typed after a \internal command is included. If the tag is set
# to NO (the default) then the documentation will be excluded.
# Set it to YES to include the internal documentation.
INTERNAL_DOCS = NO
# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
# generate a class diagram (in Html and LaTeX) for classes with base or
# super classes. Setting the tag to NO turns the diagrams off.
CLASS_DIAGRAMS = YES
# If the SOURCE_BROWSER tag is set to YES then a list of source files will
# be generated. Documented entities will be cross-referenced with these sources.
SOURCE_BROWSER = YES
# Setting the INLINE_SOURCES tag to YES will include the body
# of functions and classes directly in the documentation.
INLINE_SOURCES = NO
# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
# doxygen to hide any special comment blocks from generated source code
# fragments. Normal C and C++ comments will always remain visible.
STRIP_CODE_COMMENTS = YES
# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
# file names in lower case letters. If set to YES upper case letters are also
# allowed. This is useful if you have classes or files whose names only differ
# in case and if your file system supports case sensitive file names. Windows
# users are adviced to set this option to NO.
CASE_SENSE_NAMES = YES
# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
# will show members with their full class and namespace scopes in the
# documentation. If set to YES the scope will be hidden.
HIDE_SCOPE_NAMES = NO
# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
# will generate a verbatim copy of the header file for each class for
# which an include is specified. Set to NO to disable this.
VERBATIM_HEADERS = YES
# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
# will put list of the files that are included by a file in the documentation
# of that file.
SHOW_INCLUDE_FILES = YES
# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
# will interpret the first line (until the first dot) of a JavaDoc-style
# comment as the brief description. If set to NO, the JavaDoc
# comments will behave just like the Qt-style comments (thus requiring an
# explict @brief command for a brief description.
JAVADOC_AUTOBRIEF = NO
# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
# member inherits the documentation from any documented member that it
# reimplements.
INHERIT_DOCS = YES
# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
# is inserted in the documentation for inline members.
INLINE_INFO = YES
# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
# will sort the (detailed) documentation of file and class members
# alphabetically by member name. If set to NO the members will appear in
# declaration order.
SORT_MEMBER_DOCS = YES
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
# tag is set to YES, then doxygen will reuse the documentation of the first
# member in the group (if any) for the other members of the group. By default
# all members of a group must be documented explicitly.
DISTRIBUTE_GROUP_DOC = NO
# The TAB_SIZE tag can be used to set the number of spaces in a tab.
# Doxygen uses this value to replace tabs by spaces in code fragments.
TAB_SIZE = 4
# The ENABLE_SECTIONS tag can be used to enable conditional
# documentation sections, marked by \if sectionname ... \endif.
ENABLED_SECTIONS =
# The GENERATE_TODOLIST tag can be used to enable (YES) or
# disable (NO) the todo list. This list is created by putting \todo
# commands in the documentation.
GENERATE_TODOLIST = YES
# The GENERATE_TESTLIST tag can be used to enable (YES) or
# disable (NO) the test list. This list is created by putting \test
# commands in the documentation.
GENERATE_TESTLIST = YES
# This tag can be used to specify a number of aliases that acts
# as commands in the documentation. An alias has the form "name=value".
# For example adding "sideeffect=\par Side Effects:\n" will allow you to
# put the command \sideeffect (or @sideeffect) in the documentation, which
# will result in a user defined paragraph with heading "Side Effects:".
# You can put \n's in the value part of an alias to insert newlines.
ALIASES =
# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
# the initial value of a variable or define consist of for it to appear in
# the documentation. If the initializer consists of more lines than specified
# here it will be hidden. Use a value of 0 to hide initializers completely.
# The appearance of the initializer of individual variables and defines in the
# documentation can be controlled using \showinitializer or \hideinitializer
# command in the documentation regardless of this setting.
MAX_INITIALIZER_LINES = 30
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
# only. Doxygen will then generate output that is more tailored for C.
# For instance some of the names that are used will be different. The list
# of all members will be omitted, etc.
OPTIMIZE_OUTPUT_FOR_C = NO
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
# The QUIET tag can be used to turn on/off the messages that are generated
# by doxygen. Possible values are YES and NO. If left blank NO is used.
QUIET = NO
# The WARNINGS tag can be used to turn on/off the warning messages that are
# generated by doxygen. Possible values are YES and NO. If left blank
# NO is used.
WARNINGS = YES
# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
# automatically be disabled.
WARN_IF_UNDOCUMENTED = YES
# The WARN_FORMAT tag determines the format of the warning messages that
# doxygen can produce. The string should contain the $file, $line, and $text
# tags, which will be replaced by the file and line number from which the
# warning originated and the warning text.
WARN_FORMAT = "$file:$line: $text"
# The WARN_LOGFILE tag can be used to specify a file to which warning
# and error messages should be written. If left blank the output is written
# to stderr.
WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
# The INPUT tag can be used to specify the files and/or directories that contain
# documented source files. You may enter file names like "myfile.cpp" or
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
INPUT = .
# If the value of the INPUT tag contains directories, you can use the
# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
# and *.h) to filter out the source-files in the directories. If left
# blank all files are included.
FILE_PATTERNS = *.c *.h
# The RECURSIVE tag can be used to turn specify whether or not subdirectories
# should be searched for input files as well. Possible values are YES and NO.
# If left blank NO is used.
RECURSIVE = NO
# The EXCLUDE tag can be used to specify files and/or directories that should
# excluded from the INPUT source files. This way you can easily exclude a
# subdirectory from a directory tree whose root is specified with the INPUT tag.
EXCLUDE =
# If the value of the INPUT tag contains directories, you can use the
# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
# certain files from those directories.
EXCLUDE_PATTERNS =
# The EXAMPLE_PATH tag can be used to specify one or more files or
# directories that contain example code fragments that are included (see
# the \include command).
EXAMPLE_PATH =
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
# and *.h) to filter out the source-files in the directories. If left
# blank all files are included.
EXAMPLE_PATTERNS =
# The IMAGE_PATH tag can be used to specify one or more files or
# directories that contain image that are included in the documentation (see
# the \image command).
IMAGE_PATH =
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
# by executing (via popen()) the command <filter> <input-file>, where <filter>
# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
# input file. Doxygen will then use the output that the filter program writes
# to standard output.
INPUT_FILTER =
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
# INPUT_FILTER) will be used to filter the input files when producing source
# files to browse.
FILTER_SOURCE_FILES = NO
#---------------------------------------------------------------------------
# configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
# of all compounds will be generated. Enable this if the project
# contains a lot of classes, structs, unions or interfaces.
ALPHABETICAL_INDEX = NO
# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
# in which this list will be split (can be a number in the range [1..20])
COLS_IN_ALPHA_INDEX = 5
# In case all classes in a project start with a common prefix, all
# classes will be put under the same header in the alphabetical index.
# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
# should be ignored while generating the index headers.
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# configuration options related to the HTML output
#---------------------------------------------------------------------------
# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
# generate HTML output.
GENERATE_HTML = YES
# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `html' will be used as the default path.
HTML_OUTPUT = html
# The HTML_HEADER tag can be used to specify a personal HTML header for
# each generated HTML page. If it is left blank doxygen will generate a
# standard header.
HTML_HEADER =
# The HTML_FOOTER tag can be used to specify a personal HTML footer for
# each generated HTML page. If it is left blank doxygen will generate a
# standard footer.
HTML_FOOTER =
# The HTML_STYLESHEET tag can be used to specify a user defined cascading
# style sheet that is used by each HTML page. It can be used to
# fine-tune the look of the HTML output. If the tag is left blank doxygen
# will generate a default style sheet
HTML_STYLESHEET =
# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
# files or namespaces will be aligned in HTML using tables. If set to
# NO a bullet list will be used.
HTML_ALIGN_MEMBERS = YES
# If the GENERATE_HTMLHELP tag is set to YES, additional index files
# will be generated that can be used as input for tools like the
# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
# of the generated HTML documentation.
GENERATE_HTMLHELP = NO
# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
# top of each HTML page. The value NO (the default) enables the index and
# the value YES disables it.
DISABLE_INDEX = NO
# This tag can be used to set the number of enum values (range [1..20])
# that doxygen will group on one line in the generated HTML documentation.
ENUM_VALUES_PER_LINE = 4
# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
# generated containing a tree-like index structure (just like the one that
# is generated for HTML Help). For this to work a browser that supports
# JavaScript and frames is required (for instance Netscape 4.0+
# or Internet explorer 4.0+).
GENERATE_TREEVIEW = YES
# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
# used to set the initial width (in pixels) of the frame in which the tree
# is shown.
TREEVIEW_WIDTH = 250
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
#---------------------------------------------------------------------------
# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
# generate Latex output.
GENERATE_LATEX = YES
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `latex' will be used as the default path.
LATEX_OUTPUT = latex
# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
# LaTeX documents. This may be useful for small projects and may help to
# save some trees in general.
COMPACT_LATEX = NO
# The PAPER_TYPE tag can be used to set the paper type that is used
# by the printer. Possible values are: a4, a4wide, letter, legal and
# executive. If left blank a4wide will be used.
PAPER_TYPE = a4wide
# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
# packages that should be included in the LaTeX output.
EXTRA_PACKAGES =
# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
# the generated latex document. The header should contain everything until
# the first chapter. If it is left blank doxygen will generate a
# standard header. Notice: only use this tag if you know what you are doing!
LATEX_HEADER =
# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
# is prepared for conversion to pdf (using ps2pdf). The pdf file will
# contain links (just like the HTML output) instead of page references
# This makes the output suitable for online browsing using a pdf viewer.
PDF_HYPERLINKS = NO
# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
# plain latex in the generated Makefile. Set this option to YES to get a
# higher quality PDF documentation.
USE_PDFLATEX = NO
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
# command to the generated LaTeX files. This will instruct LaTeX to keep
# running if errors occur, instead of asking the user for help.
# This option is also used when generating formulas in HTML.
LATEX_BATCHMODE = NO
#---------------------------------------------------------------------------
# configuration options related to the RTF output
#---------------------------------------------------------------------------
# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
# The RTF output is optimised for Word 97 and may not look very pretty with
# other RTF readers or editors.
GENERATE_RTF = YES
# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `rtf' will be used as the default path.
RTF_OUTPUT = rtf
# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
# RTF documents. This may be useful for small projects and may help to
# save some trees in general.
COMPACT_RTF = NO
# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
# will contain hyperlink fields. The RTF file will
# contain links (just like the HTML output) instead of page references.
# This makes the output suitable for online browsing using a WORD or other.
# programs which support those fields.
# Note: wordpad (write) and others do not support links.
RTF_HYPERLINKS = NO
# Load stylesheet definitions from file. Syntax is similar to doxygen's
# config file, i.e. a series of assigments. You only have to provide
# replacements, missing definitions are set to their default value.
RTF_STYLESHEET_FILE =
#---------------------------------------------------------------------------
# configuration options related to the man page output
#---------------------------------------------------------------------------
# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
# generate man pages
GENERATE_MAN = YES
# The MAN_OUTPUT tag is used to specify where the man pages will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `man' will be used as the default path.
MAN_OUTPUT = man
# The MAN_EXTENSION tag determines the extension that is added to
# the generated man pages (default is the subroutine's section .3)
MAN_EXTENSION = .3
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
# evaluate all C-preprocessor directives found in the sources and include
# files.
ENABLE_PREPROCESSING = YES
# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
# names in the source code. If set to NO (the default) only conditional
# compilation will be performed. Macro expansion can be done in a controlled
# way by setting EXPAND_ONLY_PREDEF to YES.
MACRO_EXPANSION = NO
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
# then the macro expansion is limited to the macros specified with the
# PREDEFINED and EXPAND_AS_PREDEFINED tags.
EXPAND_ONLY_PREDEF = NO
# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
# in the INCLUDE_PATH (see below) will be search if a #include is found.
SEARCH_INCLUDES = YES
# The INCLUDE_PATH tag can be used to specify one or more directories that
# contain include files that are not input files but should be processed by
# the preprocessor.
INCLUDE_PATH =
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
# patterns (like *.h and *.hpp) to filter out the header-files in the
# directories. If left blank, the patterns specified with FILE_PATTERNS will
# be used.
INCLUDE_FILE_PATTERNS =
# The PREDEFINED tag can be used to specify one or more macro names that
# are defined before the preprocessor is started (similar to the -D option of
# gcc). The argument of the tag is a list of macros of the form: name
# or name=definition (no spaces). If the definition and the = are
# omitted =1 is assumed.
PREDEFINED =
# If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then
# this tag can be used to specify a list of macro names that should be expanded.
# The macro definition that is found in the sources will be used.
# Use the PREDEFINED tag if you want to use a different macro definition.
EXPAND_AS_DEFINED =
#---------------------------------------------------------------------------
# Configuration::addtions related to external references
#---------------------------------------------------------------------------
# The TAGFILES tag can be used to specify one or more tagfiles.
TAGFILES =
# When a file name is specified after GENERATE_TAGFILE, doxygen will create
# a tag file that is based on the input files it reads.
GENERATE_TAGFILE =
# If the ALLEXTERNALS tag is set to YES all external classes will be listed
# in the class index. If set to NO only the inherited external classes
# will be listed.
ALLEXTERNALS = NO
# The PERL_PATH should be the absolute path and name of the perl script
# interpreter (i.e. the result of `which perl').
PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
# available from the path. This tool is part of Graphviz, a graph visualization
# toolkit from AT&T and Lucent Bell Labs. The other options in this section
# have no effect if this option is set to NO (the default)
HAVE_DOT = NO
# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
# will generate a graph for each documented class showing the direct and
# indirect inheritance relations. Setting this tag to YES will force the
# the CLASS_DIAGRAMS tag to NO.
CLASS_GRAPH = YES
# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
# will generate a graph for each documented class showing the direct and
# indirect implementation dependencies (inheritance, containment, and
# class references variables) of the class with other documented classes.
COLLABORATION_GRAPH = YES
# If the ENABLE_PREPROCESSING, INCLUDE_GRAPH, and HAVE_DOT tags are set to
# YES then doxygen will generate a graph for each documented file showing
# the direct and indirect include dependencies of the file with other
# documented files.
INCLUDE_GRAPH = YES
# If the ENABLE_PREPROCESSING, INCLUDED_BY_GRAPH, and HAVE_DOT tags are set to
# YES then doxygen will generate a graph for each documented header file showing
# the documented files that directly or indirectly include this file
INCLUDED_BY_GRAPH = YES
# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
# will graphical hierarchy of all classes instead of a textual one.
GRAPHICAL_HIERARCHY = YES
# The tag DOT_PATH can be used to specify the path where the dot tool can be
# found. If left blank, it is assumed the dot tool can be found on the path.
DOT_PATH =
# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
# (in pixels) of the graphs generated by dot. If a graph becomes larger than
# this value, doxygen will try to truncate the graph, so that it fits within
# the specified constraint. Beware that most browsers cannot cope with very
# large images.
MAX_DOT_GRAPH_WIDTH = 1024
# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
# (in pixels) of the graphs generated by dot. If a graph becomes larger than
# this value, doxygen will try to truncate the graph, so that it fits within
# the specified constraint. Beware that most browsers cannot cope with very
# large images.
MAX_DOT_GRAPH_HEIGHT = 1024
# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
# generate a legend page explaining the meaning of the various boxes and
# arrows in the dot generated graphs.
GENERATE_LEGEND = YES
#---------------------------------------------------------------------------
# Configuration::addtions related to the search engine
#---------------------------------------------------------------------------
# The SEARCHENGINE tag specifies whether or not a search engine should be
# used. If set to NO the values of all tags below this one will be ignored.
SEARCHENGINE = NO
# The CGI_NAME tag should be the name of the CGI script that
# starts the search engine (doxysearch) with the correct parameters.
# A script with this name will be generated by doxygen.
CGI_NAME = search.cgi
# The CGI_URL tag should be the absolute URL to the directory where the
# cgi binaries are located. See the documentation of your http daemon for
# details.
CGI_URL =
# The DOC_URL tag should be the absolute URL to the directory where the
# documentation is located. If left blank the absolute path to the
# documentation, with file:// prepended to it, will be used.
DOC_URL =
# The DOC_ABSPATH tag should be the absolute path to the directory where the
# documentation is located. If left blank the directory on the local machine
# will be used.
DOC_ABSPATH =
# The BIN_ABSPATH tag must point to the directory where the doxysearch binary
# is installed.
BIN_ABSPATH = /usr/local/bin/
# The EXT_DOC_PATHS tag can be used to specify one or more paths to
# documentation generated for other projects. This allows doxysearch to search
# the documentation for these projects as well.
EXT_DOC_PATHS =

4
Mkfiles/README Normal file
View File

@ -0,0 +1,4 @@
These are pre-created Makefiles for various platforms, use them if
GNU autoconf/automake packages are not supported on your system.
Copy appropriate Makefile to ../Makefile and run make.

27
README Normal file
View File

@ -0,0 +1,27 @@
NASM, the Netwide Assembler.
Version 0.98.26.
Many many developers all over the net respect NASM for what it is
- a widespread (thus netwide), portable (thus netwide!), very
flexible and mature assembler tool with support for many output
formats (thus netwide!!).
Now we have good news for you: NASM is licensed under LGPL.
This means its development is open to even wider society of
programmers wishing to improve their lovely assembler.
The NASM project is now situated at SourceForge.net, the most
famous Open Source development center on The Net.
Visit our development page at http://nasm.2y.net and our
SF project at http://sf.net/projects/nasm
The NASM documentation is in process of severe re-arrangement
(especially the License issues with sourcecode, the old
license can be found in doc/License), all files from previous
releases that didn't go thru the process yet are placed in doc/
subdirectory. Look there if you don't find a file you need here.
With best regards,
NASM crew.

View File

@ -1,100 +0,0 @@
PROLOGUE
One day someone wrote that nasm needs:
> - A good ALIGN mechanism, similar to GAS's. GAS pads out space by
> means of the following (32-bit) instructions:
> 8DB42600000000 lea esi,[esi+0x0]
> 8DB600000000 lea esi,[esi+0x0]
> 8D742600 lea esi,[esi+0x0]
> 8D7600 lea esi,[esi+0x0]
> 8D36 lea esi,[esi]
> 90 nop
> It uses up to two of these instructions to do up to 14-byte pads;
> when more than 14 bytes are needed, it issues a (short) jump to
> the end of the padded section and then NOPs the rest. Come up with
> a similar scheme for 16 bit mode, and also come up with a way to
> use it - internal to the assembler, so that programs using ALIGN
> don't knock over preprocess-only mode.
> Also re-work the macro form so that when given one argument in a
> code section it calls this feature.
Well palign is your friend.
This is a modified version of nasm-0.98.24 that can accept
two new directives.The two new directives that control
the align mechanism are 'palign' and 'p2align'.They are nasm directives
that don't depend on preprocessor but rather align the code while assembling
in a gas-like style.
The syntax of these directives is
[palign n] where '0 <= n <= 6' and
[p2align n] where '0 <= n <=6'
The use of these directives is
[palign n]
Pad the location counter to a particular storage boundary.
The n is a number between 0 and 6 of low-order zero bits the location counter
must have after advancement.
For example `palign 3' advances the location counter until
it a multiple of 8.If the location counter is already a multiple of 8,
no change is needed.
If n=0 then nothing is done
if n => 6 then palign advances the location counter until it a multiple
of 64.For now the maximum is 64 bytes,if you want more use the ALIGN macro.
[p2align n]
This directive do almost the same thing with a little exception.
It will continue aligning until a directive [p2align 0] meet or until
the current section changes.So this piece of code
BITS 32
SECTION .text
[p2align 5]
;some code here
SECTION .data
;some data here
guarantee that all the instructions in the code segment will be aligned
in a 32 byte boundary so than no instruction break the cache line on a
pentium processor.
BUGS
Well my english are very very bad.
This optimization will not work
for now for 16-bit code.
Also there may be a problem with the prefixes like ds,es,rep,lock etc
so this code will work
'rep movsd'
but this may not work
'rep'
'movsd'
if you want to be sure put the prefix in the same line
with the instruction.
Also don't try this in a data or a bss segment.Use the ALIGN macro better
FEEDBACK
If you have any suggestion, comment or found a bug please email me
and i will try to reply immediately.
From your feedback it depends this project to get better as i intend
to implement more things and improve the code in the next version of nasm.
AUTHOR
Panos Minos 03-04-2002
email: <panosminos@mycosmos.gr> , <panosminos1@mycosmos.gr>

View File

@ -1,49 +0,0 @@
README
NASM, the Netwide Assembler
Changes from 0.98 release to 98.03 as of 27-Jul-2000
====================================================
1. Added signed byte optimizations for the 0x81/0x83 class
of instructions: ADC, ADD, AND, CMP, OR, SBB, SUB, XOR:
when used as 'ADD reg16,imm' or 'ADD reg32,imm.' Also
optimization of signed byte form of 'PUSH imm' and 'IMUL
reg,imm'/'IMUL reg,reg,imm.' No size specification is needed.
2. Added multi-pass JMP and Jcc offset optimization. Offsets
on forward references will preferentially use the short form,
without the need to code a specific size (short or near) for
the branch. Added instructions for 'Jcc label' to use the
form 'Jnotcc $+3/JMP label', in cases where a short offset
is out of bounds. If compiling for a 386 or higher CPU, then
the 386 form of Jcc will be used instead.
This feature is controlled by a new command-line switch: "O",
(upper case letter O). "-O0" reverts the assembler to no
extra optimization passes, "-O1" allows up to 5 extra passes,
and "-O2"(default), allows up to 10 extra optimization passes.
3. Added a new directive: 'cpu XXX', where XXX is any of:
8086, 186, 286, 386, 486, 586, pentium, 686, PPro, P2, P3 or
Katmai. All are case insensitive. All instructions will
be selected only if they apply to the selected cpu or lower.
Corrected a couple of bugs in cpu-dependence in 'insns.dat'.
4. Added to 'standard.mac', the "use16" and "use32" forms of
the "bits 16/32" directive. This is nothing new, just conforms
to a lot of other assemblers. (minor)
5. Changed label allocation from 320/32 (10000 labels @ 200K+)
to 32/37 (1000 labels); makes running under DOS much easier.
Since additional label space is allocated dynamically, this
should have no effect on large programs with lots of labels.
The 37 is a prime, believed to be better for hashing. (minor)
6. Integrated patchfile 0.98-0.98.01. I call this version
0.98.03, for historical reasons: 0.98.02 was trashed.
--John Coffman <johninsd@san.rr.com> 27-Jul-2000
(end)

View File

@ -1,82 +0,0 @@
README
NASM, the Netwide Assembler
Changes from 0.98.07 release to 98.09b as of 28-Oct-2001
========================================================
1. More closely compatible with 0.98 when -O0 is implied
or specified. Not strictly identical, since backward
branches in range of short offsets are recognized, and signed
byte values with no explicit size specification will be
assembled as a single byte.
2. More forgiving with the PUSH instruction. 0.98 requires
a size to be specified always. 0.98.09b will imply the size
from the current BITS setting (16 or 32).
3. Changed definition of the optimization flag:
-O0 strict two-pass assembly, JMP and Jcc are
handled more like 0.98, except that back-
ward JMPs are short, if possible.
-O1 strict two-pass assembly, but forward
branches are assembled with code guaranteed
to reach; may produce larger code than
-O0, but will produce successful assembly
more often if branch offset sizes are not
specified.
-O2 multi-pass optimization, minimize branch
offsets; also will minimize signed immed-
iate bytes, overriding size specification.
-O3 like -O2, but more passes taken, if needed
Changes from 0.98 release to 98.03 as of 27-Jul-2000
====================================================
1. Added signed byte optimizations for the 0x81/0x83 class
of instructions: ADC, ADD, AND, CMP, OR, SBB, SUB, XOR:
when used as 'ADD reg16,imm' or 'ADD reg32,imm.' Also
optimization of signed byte form of 'PUSH imm' and 'IMUL
reg,imm'/'IMUL reg,reg,imm.' No size specification is needed.
2. Added multi-pass JMP and Jcc offset optimization. Offsets
on forward references will preferentially use the short form,
without the need to code a specific size (short or near) for
the branch. Added instructions for 'Jcc label' to use the
form 'Jnotcc $+3/JMP label', in cases where a short offset
is out of bounds. If compiling for a 386 or higher CPU, then
the 386 form of Jcc will be used instead.
This feature is controlled by a new command-line switch: "O",
(upper case letter O). "-O0" reverts the assembler to no
extra optimization passes, "-O1" allows up to 5 extra passes,
and "-O2"(default), allows up to 10 extra optimization passes.
3. Added a new directive: 'cpu XXX', where XXX is any of:
8086, 186, 286, 386, 486, 586, pentium, 686, PPro, P2, P3 or
Katmai. All are case insensitive. All instructions will
be selected only if they apply to the selected cpu or lower.
Corrected a couple of bugs in cpu-dependence in 'insns.dat'.
4. Added to 'standard.mac', the "use16" and "use32" forms of
the "bits 16/32" directive. This is nothing new, just conforms
to a lot of other assemblers. (minor)
5. Changed label allocation from 320/32 (10000 labels @ 200K+)
to 32/37 (1000 labels); makes running under DOS much easier.
Since additional label space is allocated dynamically, this
should have no effect on large programs with lots of labels.
The 37 is a prime, believed to be better for hashing. (minor)
6. Integrated patchfile 0.98-0.98.01. I call this version
0.98.03, for historical reasons: 0.98.02 was trashed.
--John Coffman <johninsd@san.rr.com> 27-Jul-2000
(end)

8
TODO Normal file
View File

@ -0,0 +1,8 @@
Things to do (incorporate with doc/Wishlist):
1. i18n via gettext
2. Convert shallow code model to deep code model. Tired of messing between
lots of unrelated files (especially .c/.h stuff).
3. Automated dependency generation for Makefile. Current looks awful and will break
if anything changes.
4. (as result of 2) Move output modules out*.c to output/ subdir. (?)

82
c16.mac
View File

@ -1,82 +0,0 @@
; NASM macro set to make interfacing to 16-bit programs easier -*- nasm -*-
%imacro proc 1 ; begin a procedure definition
%push proc
global %1
%1: push bp
mov bp,sp
%ifdef FARCODE PASCAL ; arguments may start at bp+4 or bp+6
%assign %$arg 6
%define %$firstarg 6
%else
%assign %$arg 4
%define %$firstarg 4
%endif
%define %$procname %1
%endmacro
%imacro arg 0-1 2 ; used with the argument name as a label
%00 equ %$arg
; we could possibly be adding some
; debug information at this point...?
%assign %$arg %1+%$arg
%endmacro
%imacro endproc 0
%ifnctx proc
%error Mismatched `endproc'/`proc'
%else
mov sp,bp
pop bp
%ifdef PASCAL
retf %$arg - %$firstarg
%elifdef FARCODE
retf
%else
retn
%endif
__end_%$procname: ; useful for calculating function size
%pop
%endif
%endmacro

52
c32.mac
View File

@ -1,52 +0,0 @@
; NASM macro set to make interfacing to 32-bit programs easier -*- nasm -*-
%imacro proc 1 ; begin a procedure definition
%push proc
global %1
%1: push ebp
mov ebp,esp
%assign %$arg 8
%define %$procname %1
%endmacro
%imacro arg 0-1 4 ; used with the argument name as a label
%00 equ %$arg
%assign %$arg %1+%$arg
%endmacro
%imacro endproc 0
%ifnctx proc
%error Mismatched `endproc'/`proc'
%else
leave
ret
__end_%$procname: ; useful for calculating function size
%pop
%endif
%endmacro

View File

@ -1,383 +0,0 @@
;This file demonstrates many of the differences between NASM version X and NASM
;version 0.97
;
; changed.asm is copyright (C) 1998 John S. Fine
;
; It may be redistributed under the same conditions as NASM as described in
; Licence file in the NASM archive
;_________________________________
;
; nasm changed.asm -l changed.lst
;
; When assembled without any -d switches, it includes examples which:
; Work correctly in version X
; and Work incorrectly and/or display warnings in version 0.97
; and Do not prevent the generation of output in version 0.97
;
; Not all the differences can be seen in the .lst file. I suggest that you use
; "ndisasm changes" to examine the code actually generated.
;_________________________________
;
; nasm changed.asm -l changed.lst -doldmsg
;
; When assembled with -doldmsg, it adds examples which:
; Work correctly in version X
; and Generate error messages in version 0.97 and do not generate output
;_________________________________
;
; nasm changed.asm -l changed.lst -doldcrash
;
; When assembled with -doldcrash, it adds examples which:
; Work correctly in version X
; and Cause NASM to crash in version 0.97
;_________________________________
;
; nasm changed.asm -l changed.lst -dnewmsg
;
; When assembled with -dnewmsg, it adds examples which:
; Generate error messages in version X
; and Generate wrong output without warning or error message in version 0.97
;-----------------------------------------------------------------------------
; Please note that I have reported the name of the person who made the
; correction based on very limited information. In several cases, I am sure I
; will identify the wrong author. Please send me any corrections; I don't
; intend to insult or exclude anyone.
;-----------------------------------------------------------------------------
; Bug fixed by Simon in assemble()
;
; The following generated "call next" / "call next-1" instead of
; two copies of "call next"
;
times 2 a16 call next
next:
;-----------------------------------------------------------------------------
; Bug fixed by John in parse_line() (and other routines)
;
; This used to jmp to prior.1, when it should be here.1
;
prior:
.1:
here: jmp .1
.1:
;-----------------------------------------------------------------------------
; Bug fixed by John in assemble()
;
; Strings used in dq and dt were not zero filled correctly
;
dq 'b'
;-----------------------------------------------------------------------------
; Bug fixed by Simon in isn_names[]
;
; Was not recognised as an instruction
;
int01 ; Instead of INT1
;-----------------------------------------------------------------------------
; Bug fixed by Jim Hague in ???
;
; Forward references were instruction level rather than per operand
;
shr word [forwardref],1
forwardref:
;-----------------------------------------------------------------------------
; Bug fixed by John in preproc.c
;
; It used to silently discard id characters appended to a multi-line
; macro parameter (such as the x in %1x below).
;
%macro xxx 1
%1: nop
%{1}x: jmp %1x
%endmacro
xxx yyy
;-----------------------------------------------------------------------------
; Bug added by John in preproc.c 0.98-J4, removed by John in 0.98-J5
;
; Tested here to make sure it stays removed
;
%macro TestElse 1
%if %1=0
%elif %1=1
nop
%endif
%endmacro
TestElse 1
%ifdef oldmsg
;***************************************************************
;
; The following examples will generate error messages in 0.97 and will generate
; correct output in the new version.
;-----------------------------------------------------------------------------
; Bug fixed by Simon in isns.dat
;
; The optional "near" was not permitted on JMP and CALL
;
jmp near here
;-----------------------------------------------------------------------------
; Feature added by Simon in stdscan()
;
; You can now use the numeric value of strings in %assign
;
%assign xxx 'ABCD'
dd xxx
;-----------------------------------------------------------------------------
; Feature added by John in add_vectors()
;
; Stranger address expressions are now supported as long as they resolve to
; something valid.
;
mov ax, [eax + ebx + ecx - eax]
;-----------------------------------------------------------------------------
; Bug fixed by Simon in ???
;
; The EQU directive affected local labels in a way that was inconsistent
; between passes
;
.local:
neither equ $
jmp .local
;-----------------------------------------------------------------------------
; Feature added by Jules in parse_line
;
; You can override a size specifier
;
%define arg1 dword [bp+4]
cmp word arg1, 2
;-----------------------------------------------------------------------------
; Bug fixed by John in preproc.c
;
; You could not use a label on the same line with a macro invocation, if the
; macro definition began with a preprocessor directive.
;
struc mytype
.long resd 1
endstruc
lbl istruc mytype
at mytype.long, dd 'ABCD'
iend
;-----------------------------------------------------------------------------
; Warning removed by John in preproc.c
;
; In order to allow macros that extend the definition of instructions, I
; disabled the warning on a multi-line macro referencing itself.
;
%endif ;NASM 0.97 doesn't handle %0 etc. inside false %if
%macro push 1-* ;
%rep %0 ;
push %1 ;
%rotate 1 ;
%endrep ;
%endmacro ;
%ifdef oldmsg ;
push ax,bx
;-----------------------------------------------------------------------------
; Warning removed by John in preproc.c
;
; To support other types of macros that extend the definition of instructions,
; I disabled the warning on a multi-line macro called with the wrong number of
; parameters. PUSH and POP can be extended equally well by either method, but
; other intruction extensions may need one method or the other, so I made both
; work.
;
; Note that neither of these warnings was really needed, because a later stage
; of NASM would almost always give an adequate error message if the macro use
; really was wrong.
;
%endif
%macro pop 2-*
%rep %0
pop %1
%rotate 1
%endrep
%endmacro
%ifdef oldmsg
pop ax,bx
%endif
%ifdef newmsg ;***************************************************************
;-----------------------------------------------------------------------------
; Bug fixed by John in parse_line() (and other routines)
;
; This invalid code used to assemble without errors
;
myself equ myself+1
jmp myself
;-----------------------------------------------------------------------------
; Change made by John in preproc.c
;
; In 0.97, an id that appears as a label on a macro invocation was always
; prepended to the first line of the macro expansion. That caused several
; bugs, but also could be used in tricks like the arg macro in c16.mac and
; c32.mac.
;
; In version X, an id that appears as a label on a macro invocation will
; normally be defined as a label for the address at which the macro is
; invoked, regardless of whether the first line of the macro expansion is
; something that can take a label. The new token %00 may be used for any
; of the situations in which the old prepend behavior was doing something
; tricky but useful. %00 can also be used more than once and in places
; other than the start of the expansion.
;
%endif
%assign arg_off 0
%imacro arg 0-1 2 ;arg defined the old way
equ arg_off
%assign arg_off %1+arg_off
%endmacro
%ifdef newmsg
arg_example arg
%endif
%imacro arg2 0-1 2 ;arg defined the new way
%00 equ arg_off
%assign arg_off %1+arg_off
%endmacro
%ifdef oldmsg
arg_example2 arg2
;-----------------------------------------------------------------------------
; Change made by Jules and John in INSNS.DAT
;
; Various instruction in which the size of an immediate is built-in to the
; instruction set, now allow you to redundantly specify that size as long
; as you specify it correctly
;
AAD byte 5
AAM byte 5
BT bx, byte 3
BTC cx, byte 4
BTR dx, byte 5
BTS si, byte 6
IN eax, byte 0x40
INT byte 21h
OUT byte 70h, ax
RET word 2
RETN word 2
RETF word 4
; note "ENTER" has not been changed yet.
;-----------------------------------------------------------------------------
; Enhancement by hpa in insns.dat et al
;
; Simplified adding new instructions, and added some missing instructions
;
int03 ; Instead of INT3
ud1 ; No documented mnemonic for this one
ud2
sysenter
sysexit
syscall
sysret
fxsave [ebx]
fxrstor [es:ebx+esi*4+0x3000]
;-----------------------------------------------------------------------------
; Enhancement by hpa in insns.dat et al
;
; Actually make SSE work, and use the -p option to ndisasm to select
; one of several aliased opcodes
;
sqrtps xmm0,[ebx+10] ; SSE opcode
paddsiw mm0,[ebx+10] ; Cyrix opcode with the same byte seq.
;-----------------------------------------------------------------------------
; Enhancement by hpa in preproc.c
;
; Support %undef to remoce a single-line macro
;
%define TEST_ME 42
%ifndef TEST_ME
%error "TEST_ME not defined after %define"
%endif
%undef TEST_ME
%ifdef TEST_ME
%error "TEST_ME defined after %undef"
%endif
;-----------------------------------------------------------------------------
; Bug fix by hpa in insns.dat
;
; PSHUFW and PINSRW weren't handling the implicit sizes correctly; all of
; the entries below are (or should be) legal
;
pshufw mm2, mm1, 3
pshufw mm3,[ebx],2
pshufw mm7,[0+edi*8],1
pshufw mm2, mm1, byte 3
pshufw mm3,[ebx],byte 2
pshufw mm7,[0+edi*8],byte 1
pshufw mm2, mm1, 3
pshufw mm3, qword [ebx], 2
pshufw mm7, qword [0+edi*8], 1
pshufw mm2, mm1, byte 3
pshufw mm3, qword [ebx], byte 2
pshufw mm7, qword [0+edi*8], byte 1
pinsrw mm1, [esi], 1
pinsrw mm1, word [esi], 1
pinsrw mm1, [esi], byte 1
pinsrw mm1, word [esi], byte 1
%endif ; oldmsg
%ifdef oldcrash ;*************************************************************
This_label_is_256_characters_long__There_used_to_be_a_bug_in_stdscan_which_made_it_crash_when_it_did_a_keyword_search_on_any_label_longer_than_255_characters__Now_anything_longer_than_MAX_KEYWORD_is_always_a_symbol__It_will_not_even_try_a_keyword_search___
;-----------------------------------------------------------------------------
; Bug fixed by John in preproc.c
;
; Builds of NASM that prohibit dereferencing a NULL pointer used to crash if a
; macro that started with a blank line was invoked with a label
;
%macro empty_macro 0
%endm
emlabel empty_macro
jmp emlabel
;-----------------------------------------------------------------------------
; Enhancement by Conan Brink in preproc.c
;
; Allow %rep to be nested
;
%rep 4
%rep 5
nop
%endrep
%endrep
%endif

542
doc/Changes Normal file
View File

@ -0,0 +1,542 @@
Change log for NASM
===================
This is the Changelog for the official releases; this is a modified
version. For the changes from the official release, see the MODIFIED file.
0.90 released October 1996
--------------------------
First release version. First support for object file output. Other
changes from previous version (0.3x) too numerous to document.
0.91 released November 1996
---------------------------
Loads of bug fixes.
Support for RDF added.
Support for DBG debugging format added.
Support for 32-bit extensions to Microsoft OBJ format added.
Revised for Borland C: some variable names changed, makefile added.
LCC support revised to actually work.
JMP/CALL NEAR/FAR notation added.
`a16', `o16', `a32' and `o32' prefixes added.
Range checking on short jumps implemented.
MMX instruction support added.
Negative floating point constant support added.
Memory handling improved to bypass 64K barrier under DOS.
$ prefix to force treatment of reserved words as identifiers added.
Default-size mechanism for object formats added.
Compile-time configurability added.
`#', `@', `~' and `?' are now valid characters in labels.
`-e' and `-k' options in NDISASM added.
0.92 released January 1997
--------------------------
The FDIVP/FDIVRP and FSUBP/FSUBRP pairs had been inverted: this was
fixed. This also affected the LCC driver.
Fixed a bug regarding 32-bit effective addresses of the form
[other_register+ESP].
Documentary changes, notably documentation of the fact that Borland
Win32 compilers use `obj' rather than `win32' object format.
Fixed the COMENT record in OBJ files, which was formatted
incorrectly.
Fixed a bug causing segfaults in large RDF files.
OBJ format now strips initial periods from segment and group
definitions, in order to avoid complications with the local label
syntax.
Fixed a bug in disassembling far calls and jumps in NDISASM.
Added support for user-defined sections in COFF and ELF files.
Compiled the DOS binaries with a sensible amount of stack, to
prevent stack overflows on any arithmetic expression containing
parentheses.
Fixed a bug in handling of files that do not terminate in a newline.
0.93 released January 1997
--------------------------
This release went out in a great hurry after semi-crippling bugs
were found in 0.92.
Really _did_ fix the stack overflows this time. *blush*
Had problems with EA instruction sizes changing between passes, when
an offset contained a forward reference and so 4 bytes were
allocated for the offset in pass one; by pass two the symbol had
been defined and happened to be a small absolute value, so only 1
byte got allocated, causing instruction size mismatch between passes
and hence incorrect address calculations. Fixed.
Stupid bug in the revised ELF section generation fixed (associated
string-table section for .symtab was hard-coded as 7, even when this
didn't fit with the real section table). Was causing `ld' to
seg-fault under Linux.
Included a new Borland C makefile, Makefile.bc2, donated by Fox
Cutter <lmb@comtch.iea.com>.
0.94 released April 1997
------------------------
Major item: added the macro processor.
Added undocumented instructions SMI, IBTS, XBTS and LOADALL286. Also
reorganised CMPXCHG instruction into early-486 and Pentium forms.
Thanks to Thobias Jones for the information.
Fixed two more stupid bugs in ELF, which were causing `ld' to
continue to seg-fault in a lot of non-trivial cases.
Fixed a seg-fault in the label manager.
Stopped FBLD and FBSTP from _requiring_ the TWORD keyword, which is
the only option for BCD loads/stores in any case.
Ensured FLDCW, FSTCW and FSTSW can cope with the WORD keyword, if
anyone bothers to provide it. Previously they complained unless no
keyword at all was present.
Some forms of FDIV/FDIVR and FSUB/FSUBR were still inverted: a
vestige of a bug that I thought had been fixed in 0.92. This was
fixed, hopefully for good this time...
Another minor phase error (insofar as a phase error can _ever_ be
minor) fixed, this one occurring in code of the form
rol ax,forward_reference
forward_reference equ 1
The number supplied to TIMES is now sanity-checked for positivity,
and also may be greater than 64K (which previously didn't work on
16-bit systems).
Added Watcom C makefiles, and misc/pmw.bat, donated by Dominik Behr.
Added the INCBIN pseudo-opcode.
Due to the advent of the preprocessor, the [INCLUDE] and [INC]
directives have become obsolete. They are still supported in this
version, with a warning, but won't be in the next.
Fixed a bug in OBJ format, which caused incorrect object records to
be output when absolute labels were made global.
Updates to RDOFF subdirectory, and changes to outrdf.c.
0.95 released July 1997
-----------------------
Fixed yet another ELF bug. This one manifested if the user relied on
the default segment, and attempted to define global symbols without
first explicitly declaring the target segment.
Added makefiles (for NASM and the RDF tools) to build Win32 console
apps under Symantec C++. Donated by Mark Junker.
Added `macros.bas' and `insns.bas', QBasic versions of the Perl
scripts that convert `standard.mac' to `macros.c' and convert
`insns.dat' to `insnsa.c' and `insnsd.c'. Also thanks to Mark
Junker.
Changed the diassembled forms of the conditional instructions so
that JB is now emitted as JC, and other similar changes. Suggested
list by Ulrich Doewich.
Added `@' to the list of valid characters to begin an identifier
with.
Documentary changes, notably the addition of the `Common Problems'
section in nasm.doc.
Fixed a bug relating to 32-bit PC-relative fixups in OBJ.
Fixed a bug in perm_copy() in labels.c which was causing exceptions
in cleanup_labels() on some systems.
Positivity sanity check in TIMES argument changed from a warning to
an error following a further complaint.
Changed the acceptable limits on byte and word operands to allow
things like `~10111001b' to work.
Fixed a major problem in the preprocessor which caused seg-faults if
macro definitions contained blank lines or comment-only lines.
Fixed inadequate error checking on the commas separating the
arguments to `db', `dw' etc.
Fixed a crippling bug in the handling of macros with operand counts
defined with a `+' modifier.
Fixed a bug whereby object file formats which stored the input file
name in the output file (such as OBJ and COFF) weren't doing so
correctly when the output file name was specified on the command
line.
Removed [INC] and [INCLUDE] support for good, since they were
obsolete anyway.
Fixed a bug in OBJ which caused all fixups to be output in 16-bit
(old-format) FIXUPP records, rather than putting the 32-bit ones in
FIXUPP32 (new-format) records.
Added, tentatively, OS/2 object file support (as a minor variant on
OBJ).
Updates to Fox Cutter's Borland C makefile, Makefile.bc2.
Removed a spurious second fclose() on the output file.
Added the `-s' command line option to redirect all messages which
would go to stderr (errors, help text) to stdout instead.
Added the `-w' command line option to selectively suppress some
classes of assembly warning messages.
Added the `-p' pre-include and `-d' pre-define command-line options.
Added an include file search path: the `-i' command line option.
Fixed a silly little preprocessor bug whereby starting a line with a
`%!' environment-variable reference caused an `unknown directive'
error.
Added the long-awaited listing file support: the `-l' command line
option.
Fixed a problem with OBJ format whereby, in the absence of any
explicit segment definition, non-global symbols declared in the
implicit default segment generated spurious EXTDEF records in the
output.
Added the NASM environment variable.
From this version forward, Win32 console-mode binaries will be
included in the DOS distribution in addition to the 16-bit binaries.
Added Makefile.vc for this purpose.
Added `return 0;' to test/objlink.c to prevent compiler warnings.
Added the __NASM_MAJOR__ and __NASM_MINOR__ standard defines.
Added an alternative memory-reference syntax in which prefixing an
operand with `&' is equivalent to enclosing it in square brackets,
at the request of Fox Cutter.
Errors in pass two now cause the program to return a non-zero error
code, which they didn't before.
Fixed the single-line macro cycle detection, which didn't work at
all on macros with no parameters (caused an infinite loop). Also
changed the behaviour of single-line macro cycle detection to work
like cpp, so that macros like `extrn' as given in the documentation
can be implemented.
Fixed the implementation of WRT, which was too restrictive in that
you couldn't do `mov ax,[di+abc wrt dgroup]' because (di+abc) wasn't
a relocatable reference.
0.96 released November 1997
---------------------------
Fixed a bug whereby, if `nasm sourcefile' would cause a filename
collision warning and put output into `nasm.out', then `nasm
sourcefile -o outputfile' still gave the warning even though the
`-o' was honoured.
Fixed name pollution under Digital UNIX: one of its header files
defined R_SP, which broke the enum in nasm.h.
Fixed minor instruction table problems: FUCOM and FUCOMP didn't have
two-operand forms; NDISASM didn't recognise the longer register
forms of PUSH and POP (eg FF F3 for PUSH BX); TEST mem,imm32 was
flagged as undocumented; the 32-bit forms of CMOV had 16-bit operand
size prefixes; `AAD imm' and `AAM imm' are no longer flagged as
undocumented because the Intel Architecture reference documents
them.
Fixed a problem with the local-label mechanism, whereby strange
types of symbol (EQUs, auto-defined OBJ segment base symbols)
interfered with the `previous global label' value and screwed up
local labels.
Fixed a bug whereby the stub preprocessor didn't communicate with
the listing file generator, so that the -a and -l options in
conjunction would produce a useless listing file.
Merged `os2' object file format back into `obj', after discovering
that `obj' _also_ shouldn't have a link pass separator in a module
containing a non-trivial MODEND. Flat segments are now declared
using the FLAT attribute. `os2' is no longer a valid object format
name: use `obj'.
Removed the fixed-size temporary storage in the evaluator. Very very
long expressions (like `mov ax,1+1+1+1+...' for two hundred 1s or
so) should now no longer crash NASM.
Fixed a bug involving segfaults on disassembly of MMX instructions,
by changing the meaning of one of the operand-type flags in nasm.h.
This may cause other apparently unrelated MMX problems; it needs to
be tested thoroughly.
Fixed some buffer overrun problems with large OBJ output files.
Thanks to DJ Delorie for the bug report and fix.
Made preprocess-only mode actually listen to the %line markers as it
prints them, so that it can report errors more sanely.
Re-designed the evaluator to keep more sensible track of expressions
involving forward references: can now cope with previously-nightmare
situations such as
mov ax,foo | bar
foo equ 1
bar equ 2
Added the ALIGN and ALIGNB standard macros.
Added PIC support in ELF: use of WRT to obtain the four extra
relocation types needed.
Added the ability for output file formats to define their own
extensions to the GLOBAL, COMMON and EXTERN directives.
Implemented common-variable alignment, and global-symbol type and
size declarations, in ELF.
Implemented NEAR and FAR keywords for common variables, plus
far-common element size specification, in OBJ.
Added a feature whereby EXTERNs and COMMONs in OBJ can be given a
default WRT specification (either a segment or a group).
Transformed the Unix NASM archive into an auto-configuring package.
Added a sanity-check for people applying SEG to things which are
already segment bases: this previously went unnoticed by the SEG
processing and caused OBJ-driver panics later.
Added the ability, in OBJ format, to deal with `MOV EAX,<segment>'
type references: OBJ doesn't directly support dword-size segment
base fixups, but as long as the low two bytes of the constant term
are zero, a word-size fixup can be generated instead and it will
work.
Added the ability to specify sections' alignment requirements in
Win32 object files and pure binary files.
Added preprocess-time expression evaluation: the %assign (and
%iassign) directive and the bare %if (and %elif) conditional. Added
relational operators to the evaluator, for use only in %if
constructs: the standard relationals = < > <= >= <> (and C-like
synonyms == and !=) plus low-precedence logical operators &&, ^^ and
||.
Added a preprocessor repeat construct: %rep / %exitrep / %endrep.
Added the __FILE__ and __LINE__ standard macros.
Added a sanity check for number constants being greater than
0xFFFFFFFF. The warning can be disabled.
Added the %0 token whereby a variadic multi-line macro can tell how
many parameters it's been given in a specific invocation.
Added %rotate, allowing multi-line macro parameters to be cycled.
Added the `*' option for the maximum parameter count on multi-line
macros, allowing them to take arbitrarily many parameters.
Added the ability for the user-level forms of EXTERN, GLOBAL and
COMMON to take more than one argument.
Added the IMPORT and EXPORT directives in OBJ format, to deal with
Windows DLLs.
Added some more preprocessor %if constructs: %ifidn / %ifidni (exact
textual identity), and %ifid / %ifnum / %ifstr (token type testing).
Added the ability to distinguish SHL AX,1 (the 8086 version) from
SHL AX,BYTE 1 (the 286-and-upwards version whose constant happens to
be 1).
Added NetBSD/FreeBSD/OpenBSD's variant of a.out format, complete
with PIC shared library features.
Changed NASM's idiosyncratic handling of FCLEX, FDISI, FENI, FINIT,
FSAVE, FSTCW, FSTENV, and FSTSW to bring it into line with the
otherwise accepted standard. The previous behaviour, though it was a
deliberate feature, was a deliberate feature based on a
misunderstanding. Apologies for the inconvenience.
Improved the flexibility of ABSOLUTE: you can now give it an
expression rather than being restricted to a constant, and it can
take relocatable arguments as well.
Added the ability for a variable to be declared as EXTERN multiple
times, and the subsequent definitions are just ignored.
We now allow instruction prefixes (CS, DS, LOCK, REPZ etc) to be
alone on a line (without a following instruction).
Improved sanity checks on whether the arguments to EXTERN, GLOBAL
and COMMON are valid identifiers.
Added misc/exebin.mac to allow direct generation of .EXE files by
hacking up an EXE header using DB and DW; also added test/binexe.asm
to demonstrate the use of this. Thanks to Yann Guidon for
contributing the EXE header code.
ndisasm forgot to check whether the input file had been successfully
opened. Now it does. Doh!
Added the Cyrix extensions to the MMX instruction set.
Added a hinting mechanism to allow [EAX+EBX] and [EBX+EAX] to be
assembled differently. This is important since [ESI+EBP] and
[EBP+ESI] have different default base segment registers.
Added support for the PharLap OMF extension for 4096-byte segment
alignment.
0.97 released December 1997
---------------------------
This was entirely a bug-fix release to 0.96, which seems to have got
cursed. Silly me.
Fixed stupid mistake in OBJ which caused `MOV EAX,<constant>' to
fail. Caused by an error in the `MOV EAX,<segment>' support.
ndisasm hung at EOF when compiled with lcc on Linux because lcc on
Linux somehow breaks feof(). ndisasm now does not rely on feof().
A heading in the documentation was missing due to a markup error in
the indexing. Fixed.
Fixed failure to update all pointers on realloc() within extended-
operand code in parser.c. Was causing wrong behaviour and seg faults
on lines such as `dd 0.0,0.0,0.0,0.0,...'
Fixed a subtle preprocessor bug whereby invoking one multi-line
macro on the first line of the expansion of another, when the second
had been invoked with a label defined before it, didn't expand the
inner macro.
Added internal.doc back in to the distribution archives - it was
missing in 0.96 *blush*
Fixed bug causing 0.96 to be unable to assemble its own test files,
specifically objtest.asm. *blush again*
Fixed seg-faults and bogus error messages caused by mismatching
%rep and %endrep within multi-line macro definitions.
Fixed a problem with buffer overrun in OBJ, which was causing
corruption at ends of long PUBDEF records.
Separated DOS archives into main-program and documentation to reduce
download size.
0.98 released May 1999
----------------------
Fixed a bug whereby STRUC didn't work at all in RDF.
Fixed a problem with group specification in PUBDEFs in OBJ.
Improved ease of adding new output formats. Contribution due to
Fox Cutter.
Fixed a bug in relocations in the `bin' format: was showing up when
a relocatable reference crossed an 8192-byte boundary in any output
section.
Fixed a bug in local labels: local-label lookups were inconsistent
between passes one and two if an EQU occurred between the definition
of a global label and the subsequent use of a local label local to
that global.
Fixed a seg-fault in the preprocessor (again) which happened when
you use a blank line as the first line of a multi-line macro
definition and then defined a label on the same line as a call to
that macro.
Fixed a stale-pointer bug in the handling of the NASM environment
variable. Thanks to Thomas McWilliams.
ELF had a hard limit on the number of sections which caused
segfaults when transgressed. Fixed.
Added ability for ndisasm to read from stdin by using `-' as the
filename.
ndisasm wasn't outputting the TO keyword. Fixed.
Fixed error cascade on bogus expression in %if - an error in
evaluation was causing the entire %if to be discarded, thus creating
trouble later when the %else or %endif was encountered.
Forward reference tracking was instruction-granular not operand-
granular, which was causing 286-specific code to be generated
needlessly on code of the form `shr word [forwardref],1'. Thanks to
Jim Hague for sending a patch.
All messages now appear on stdout, as sending them to stderr serves
no useful purpose other than to make redirection difficult.
Fixed the problem with EQUs pointing to an external symbol - this
now generates an error message.
Allowed multiple size prefixes to an operand, of which only the first
is taken into account.
Incorporated John Fine's changes, including fixes of a large number
of preprocessor bugs, some small problems in OBJ, and a reworking of
label handling to define labels before their line is assembled, rather
than after.
Reformatted a lot of the source code to be more readable. Included
'coding.txt' as a guideline for how to format code for contributors.
Stopped nested %reps causing a panic - they now cause a slightly more
friendly error message instead.
Fixed floating point constant problems (patch by Pedro Gimeno)
Fixed the return value of insn_size() not being checked for -1, indicating
an error.
Incorporated 3D now instructions.
Fixed the 'mov eax, eax + ebx' bug.
Fixed the GLOBAL EQU bug in ELF. Released developers release 3.
Incorporated John Fine's command line parsing changes
Incorporated David Lindauer's OMF debug support
Made changes for LCC 4.0 support (__NASM_CDecl__, removed register size
specification warning when sizes agree).
Released NASM 0.98 Pre-release 1
fixed bug in outcoff.c to do with truncating section names longer
than 8 characters, referencing beyond end of string; 0.98 pre-release 2
added response file support, improved command line handling, new layout
help screen
fixed limit checking bug, 'OUT byte nn, reg' bug, and a couple of rdoff
related bugs, updated Wishlist; 0.98 Prerelease 3.
See the file "MODIFIED" for changes after 0.98p3.

49
doc/Readme Normal file
View File

@ -0,0 +1,49 @@
NetWide Assembler for the SciTech MGL
-------------------------------------
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.
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.
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:
unset DBG
dmake OPT=1
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.
Licensing issues:
-----------------
For information about how you can distribute and use NASM, see the
file Licence.
The NASM web page is at http://www.cryogen.com/Nasm/
Bug reports specific to the SciTech MGL should be posted to SciTech
Software MGL newsgroups:
news://news.scitechsoft.com/scitech.mgl.developer
Bug reports (and patches if you can) for NASM itself that are not SciTech
MGL related should be sent to the authors at:
Julian Hall <jules@earthcorp.com>
Simon Tatham <anakin@pobox.com>

276
doc/Wishlist Normal file
View File

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

View File

@ -1,114 +0,0 @@
; -*- nasm -*-
; NASM macro file to allow the `bin' output format to generate
; simple .EXE files by constructing the EXE header by hand.
; Adapted from a contribution by Yann Guidon <whygee_corp@hol.fr>
%define EXE_stack_size EXE_realstacksize
%macro EXE_begin 0
ORG 0E0h
section .text
header_start:
db 4Dh,5Ah ; EXE file signature
dw EXE_allocsize % 512
dw (EXE_allocsize + 511) / 512
dw 0 ; relocation information: none
dw (header_end-header_start)/16 ; header size in paragraphs
dw (EXE_absssize + EXE_realstacksize) / 16 ; min extra mem
dw (EXE_absssize + EXE_realstacksize) / 16 ; max extra mem
dw -10h ; Initial SS (before fixup)
dw EXE_endbss + EXE_realstacksize ; Initial SP (1K DPMI+1K STACK)
dw 0 ; (no) Checksum
dw 100h ; Initial IP - start just after the header
dw -10h ; Initial CS (before fixup)
dw 0 ; file offset to relocation table: none
dw 0 ; (no overlay)
align 16,db 0
header_end:
EXE_startcode:
section .data
EXE_startdata:
section .bss
EXE_startbss:
%endmacro
%macro EXE_stack 1
EXE_realstacksize equ %1
%define EXE_stack_size EXE_bogusstacksize ; defeat EQU in EXE_end
%endmacro
%macro EXE_end 0
section .text
EXE_endcode:
section .data
EXE_enddata:
section .bss
alignb 4
EXE_endbss:
EXE_acodesize equ (EXE_endcode-EXE_startcode+3) & (~3)
EXE_datasize equ EXE_enddata-EXE_startdata
EXE_absssize equ (EXE_endbss-EXE_startbss+3) & (~3)
EXE_allocsize equ EXE_acodesize + EXE_datasize
EXE_stack_size equ 0x800 ; default if nothing else was used
%endmacro

View File

@ -1,291 +0,0 @@
Internals of the Netwide Assembler
==================================
The Netwide Assembler is intended to be a modular, re-usable x86
assembler, which can be embedded in other programs, for example as
the back end to a compiler.
The assembler is composed of modules. The interfaces between them
look like:
+--- preproc.c ----+
| |
+---- parser.c ----+
| | |
| float.c |
| |
+--- assemble.c ---+
| | |
nasm.c ---+ insnsa.c +--- nasmlib.c
| |
+--- listing.c ----+
| |
+---- labels.c ----+
| |
+--- outform.c ----+
| |
+----- *out.c -----+
In other words, each of `preproc.c', `parser.c', `assemble.c',
`labels.c', `listing.c', `outform.c' and each of the output format
modules `*out.c' are independent modules, which do not directly
inter-communicate except through the main program.
The Netwide *Disassembler* is not intended to be particularly
portable or reusable or anything, however. So I won't bother
documenting it here. :-)
nasmlib.c
---------
This is a library module; it contains simple library routines which
may be referenced by all other modules. Among these are a set of
wrappers around the standard `malloc' routines, which will report a
fatal error if they run out of memory, rather than returning NULL.
preproc.c
---------
This contains a macro preprocessor, which takes a file name as input
and returns a sequence of preprocessed source lines. The only symbol
exported from the module is `nasmpp', which is a data structure of
type `Preproc', declared in nasm.h. This structure contains pointers
to all the functions designed to be callable from outside the
module.
parser.c
--------
This contains a source-line parser. It parses `canonical' assembly
source lines, containing some combination of the `label', `opcode',
`operand' and `comment' fields: it does not process directives or
macros. It exports two functions: `parse_line' and `cleanup_insn'.
`parse_line' is the main parser function: you pass it a source line
in ASCII text form, and it returns you an `insn' structure
containing all the details of the instruction on that line. The
parameters it requires are:
- The location (segment, offset) where the instruction on this line
will eventually be placed. This is necessary in order to evaluate
expressions containing the Here token, `$'.
- A function which can be called to retrieve the value of any
symbols the source line references.
- Which pass the assembler is on: an undefined symbol only causes an
error condition on pass two.
- The source line to be parsed.
- A structure to fill with the results of the parse.
- A function which can be called to report errors.
Some instructions (DB, DW, DD for example) can require an arbitrary
amount of storage, and so some of the members of the resulting
`insn' structure will be dynamically allocated. The other function
exported by `parser.c' is `cleanup_insn', which can be called to
deallocate any dynamic storage associated with the results of a
parse.
names.c
-------
This doesn't count as a module - it defines a few arrays which are
shared between NASM and NDISASM, so it's a separate file which is
#included by both parser.c and disasm.c.
float.c
-------
This is essentially a library module: it exports one function,
`float_const', which converts an ASCII representation of a
floating-point number into an x86-compatible binary representation,
without using any built-in floating-point arithmetic (so it will run
on any platform, portably). It calls nothing, and is called only by
`parser.c'. Note that the function `float_const' must be passed an
error reporting routine.
assemble.c
----------
This module contains the code generator: it translates `insn'
structures as returned from the parser module into actual generated
code which can be placed in an output file. It exports two
functions, `assemble' and `insn_size'.
`insn_size' is designed to be called on pass one of assembly: it
takes an `insn' structure as input, and returns the amount of space
that would be taken up if the instruction described in the structure
were to be converted to real machine code. `insn_size' also requires
to be told the location (as a segment/offset pair) where the
instruction would be assembled, the mode of assembly (16/32 bit
default), and a function it can call to report errors.
`assemble' is designed to be called on pass two: it takes all the
parameters that `insn_size' does, but has an extra parameter which
is an output driver. `assemble' actually converts the input
instruction into machine code, and outputs the machine code by means
of calling the `output' function of the driver.
insnsa.c
--------
This is another library module: it exports one very big array of
instruction translations. It has to be a separate module so that DOS
compilers, with less memory to spare than typical Unix ones, can
cope with it.
labels.c
--------
This module contains a label manager. It exports six functions:
`init_labels' should be called before any other function in the
module. `cleanup_labels' may be called after all other use of the
module has finished, to deallocate storage.
`define_label' is called to define new labels: you pass it the name
of the label to be defined, and the (segment,offset) pair giving the
value of the label. It is also passed an error-reporting function,
and an output driver structure (so that it can call the output
driver's label-definition function). `define_label' mentally
prepends the name of the most recently defined non-local label to
any label beginning with a period.
`define_label_stub' is designed to be called in pass two, once all
the labels have already been defined: it does nothing except to
update the "most-recently-defined-non-local-label" status, so that
references to local labels in pass two will work correctly.
`declare_as_global' is used to declare that a label should be
global. It must be called _before_ the label in question is defined.
Finally, `lookup_label' attempts to translate a label name into a
(segment,offset) pair. It returns non-zero on success.
The label manager module is (theoretically :) restartable: after
calling `cleanup_labels', you can call `init_labels' again, and
start a new assembly with a new set of symbols.
listing.c
---------
This file contains the listing file generator. The interface to the
module is through the one symbol it exports, `nasmlist', which is a
structure containing six function pointers. The calling semantics of
these functions isn't terribly well thought out, as yet, but it
works (just about) so it's going to get left alone for now...
outform.c
---------
This small module contains a set of routines to manage a list of
output formats, and select one given a keyword. It contains three
small routines: `ofmt_register' which registers an output driver as
part of the managed list, `ofmt_list' which lists the available
drivers on stdout, and `ofmt_find' which tries to find the driver
corresponding to a given name.
The output modules
------------------
Each of the output modules, `outbin.o', `outelf.o' and so on,
exports only one symbol, which is an output driver data structure
containing pointers to all the functions needed to produce output
files of the appropriate type.
The exception to this is `outcoff.o', which exports _two_ output
driver structures, since COFF and Win32 object file formats are very
similar and most of the code is shared between them.
nasm.c
------
This is the main program: it calls all the functions in the above
modules, and puts them together to form a working assembler. We
hope. :-)
Segment Mechanism
-----------------
In NASM, the term `segment' is used to separate the different
sections/segments/groups of which an object file is composed.
Essentially, every address NASM is capable of understanding is
expressed as an offset from the beginning of some segment.
The defining property of a segment is that if two symbols are
declared in the same segment, then the distance between them is
fixed at assembly time. Hence every externally-declared variable
must be declared in its own segment, since none of the locations of
these are known, and so no distances may be computed at assembly
time.
The special segment value NO_SEG (-1) is used to denote an absolute
value, e.g. a constant whose value does not depend on relocation,
such as the _size_ of a data object.
Apart from NO_SEG, segment indices all have their least significant
bit clear, if they refer to actual in-memory segments. For each
segment of this type, there is an auxiliary segment value, defined
to be the same number but with the LSB set, which denotes the
segment-base value of that segment, for object formats which support
it (Microsoft .OBJ, for example).
Hence, if `textsym' is declared in a code segment with index 2, then
referencing `SEG textsym' would return zero offset from
segment-index 3. Or, in object formats which don't understand such
references, it would return an error instead.
The next twist is SEG_ABS. Some symbols may be declared with a
segment value of SEG_ABS plus a 16-bit constant: this indicates that
they are far-absolute symbols, such as the BIOS keyboard buffer
under MS-DOS, which always resides at 0040h:001Eh. Far-absolutes are
handled with care in the parser, since they are supposed to evaluate
simply to their offset part within expressions, but applying SEG to
one should yield its segment part. A far-absolute should never find
its way _out_ of the parser, unless it is enclosed in a WRT clause,
in which case Microsoft 16-bit object formats will want to know
about it.
Porting Issues
--------------
We have tried to write NASM in portable ANSI C: we do not assume
little-endianness or any hardware characteristics (in order that
NASM should work as a cross-assembler for x86 platforms, even when
run on other, stranger machines).
Assumptions we _have_ made are:
- We assume that `short' is at least 16 bits, and `long' at least
32. This really _shouldn't_ be a problem, since Kernighan and
Ritchie tell us we are entitled to do so.
- We rely on having more than 6 characters of significance on
externally linked symbols in the NASM sources. This may get fixed
at some point. We haven't yet come across a linker brain-dead
enough to get it wrong anyway.
- We assume that `fopen' using the mode "wb" can be used to write
binary data files. This may be wrong on systems like VMS, with a
strange file system. Though why you'd want to run NASM on VMS is
beyond me anyway.
That's it. Subject to those caveats, NASM should be completely
portable. If not, we _really_ want to know about it.
Porting Non-Issues
------------------
The following is _not_ a portability problem, although it looks like
one.
- When compiling with some versions of DJGPP, you may get errors
such as `warning: ANSI C forbids braced-groups within
expressions'. This isn't NASM's fault - the problem seems to be
that DJGPP's definitions of the <ctype.h> macros include a
GNU-specific C extension. So when compiling using -ansi and
-pedantic, DJGPP complains about its own header files. It isn't a
problem anyway, since it still generates correct code.

52
lcc/README Normal file
View File

@ -0,0 +1,52 @@
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) by using NASM as a back-end code generator.
This patch has been tested on lcc version 3.6.
To install:
- Copy `x86nasm.md' into the `src' directory of the lcc tree.
- Copy either `lin-elf.c' or `lin-aout.c' into the `etc' directory.
- If you're installing for a.out, edit `x86nasm.md' and change the
conditional after the comment reading "CHANGE THIS FOR a.out" in
the `defsymbol' function from `#if 0' to `#if 1'.
- Make the following changes to `bind.c' in the `src' directory:
- Near the top of the file, add a line that reads
extern Interface x86nasmIR;
- In the `bindings' array, add the lines
"x86-nasm", &x86nasmIR,
"x86/nasm", &x86nasmIR,
(in sensible looking places...)
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...
- 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...)
- 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'.
- 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.
- 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!

2
misc/README Normal file
View File

@ -0,0 +1,2 @@
There are various helpful bits and pieces for NASM,
including but not limited to Simon photograph =)

2
nasm.h
View File

@ -13,7 +13,7 @@
#define NASM_MAJOR_VER 0
#define NASM_MINOR_VER 98
#define NASM_VER "0.98.25alt"
#define NASM_VER "0.98.26"
#ifndef NULL
#define NULL 0

View File

@ -1,199 +0,0 @@
The Netwide Disassembler, NDISASM
=================================
Introduction
============
The Netwide Disassembler is a small companion program to the Netwide
Assembler, NASM. It seemed a shame to have an x86 assembler,
complete with a full instruction table, and not make as much use of
it as possible, so here's a disassembler which shares the
instruction table (and some other bits of code) with NASM.
The Netwide Disassembler does nothing except to produce
disassemblies of _binary_ source files. NDISASM does not have any
understanding of object file formats, like `objdump', and it will
not understand DOS .EXE files like `debug' will. It just
disassembles.
Getting Started: Installation
=============================
See `nasm.doc' for installation instructions. NDISASM, like NASM,
has a man page which you may want to put somewhere useful, if you
are on a Unix system.
Running NDISASM
===============
To disassemble a file, you will typically use a command of the form
ndisasm [-b16 | -b32] filename
NDISASM can disassemble 16 bit code or 32 bit code equally easily,
provided of course that you remember to specify which it is to work
with. If no `-b' switch is present, NDISASM works in 16-bit mode by
default. The `-u' switch (for USE32) also invokes 32-bit mode.
Two more command line options are `-r' which reports the version
number of NDISASM you are running, and `-h' which gives a short
summary of command line options.
COM Files: Specifying an Origin
===============================
To disassemble a DOS .COM file correctly, a disassembler must assume
that the first instruction in the file is loaded at address 0x100,
rather than at zero. NDISASM, which assumes by default that any file
you give it is loaded at zero, will therefore need to be informed of
this.
The `-o' option allows you to declare a different origin for the
file you are disassembling. Its argument may be expressed in any of
the NASM numeric formats: decimal by default, if it begins with `$'
or `0x' or ends in `H' it's hex, if it ends in `Q' it's octal, and
if it ends in `B' it's binary.
Hence, to disassemble a .COM file:
ndisasm -o100h filename.com
will do the trick.
Code Following Data: Synchronisation
====================================
Suppose you are disassembling a file which contains some data which
isn't machine code, and _then_ contains some machine code. NDISASM
will faithfully plough through the data section, producing machine
instructions wherever it can (although most of them will look
bizarre, and some may have unusual prefixes, e.g. `fs or
ax,0x240a'), and generating `db' instructions every so often if it's
totally stumped. Then it will reach the code section.
Supposing NDISASM has just finished generating a strange machine
instruction from part of the data section, and its file position is
now one byte _before_ the beginning of the code section. It's
entirely possible that another spurious instruction will get
generated, starting with the final byte of the data section, and
then the correct first instruction in the code section will not be
seen because the starting point skipped over it. This isn't really
ideal.
To avoid this, you can specify a `synchronisation' point, or indeed
as many synchronisation points as you like (although NDISASM can
only handle 8192 sync points internally). The definition of a sync
point is this: NDISASM guarantees to hit sync points exactly during
disassembly. If it is thinking about generating an instruction which
would cause it to jump over a sync point, it will discard that
instruction and output a `db' instead. So it _will_ start
disassembly exactly from the sync point, and so you _will_ see all
the instructions in your code section.
Sync points are specified using the `-s' option: they are measured
in terms of the program origin, not the file position. So if you
want to synchronise after 32 bytes of a .COM file, you would have to
do
ndisasm -o100h -s120h file.com
rather than
ndisasm -o100h -s20h file.com
As stated above, you can specify multiple sync markers if you need
to, just by repeating the `-s' option.
Mixed Code and Data: Automatic (Intelligent) Synchronisation
============================================================
Suppose you are disassembling the boot sector of a DOS floppy (maybe
it has a virus, and you need to understand the virus so that you
know what kinds of damage it might have done you). Typically, this
will contain a JMP instruction, then some data, then the rest of the
code. So there is a very good chance of NDISASM being misaligned
when the data ends and the code begins. Hence a sync point is
needed.
On the other hand, why should you have to specify the sync point
manually? What you'd do in order to find where the sync point would
be, surely, would be to read the JMP instruction, and then to use
its target address as a sync point. So can NDISASM do that for you?
The answer, of course, is yes: using either of the synonymous
switches `-a' (for automatic sync) or `-i' (for intelligent sync)
will enable auto-sync mode. Auto-sync mode automatically generates a
sync point for any forward-referring PC-relative jump or call
instruction that NDISASM encounters. (Since NDISASM is one-pass, if
it encounters a PC-relative jump whose target has already been
processed, there isn't much it can do about it...)
Only PC-relative jumps are processed, since an absolute jump is
either through a register (in which case NDISASM doesn't know what
the register contains) or involves a segment address (in which case
the target code isn't in the same segment that NDISASM is working
in, and so the sync point can't be placed anywhere useful).
For some kinds of file, this mechanism will automatically put sync
points in all the right places, and save you from having to place
any sync points manually. However, it should be stressed that
auto-sync mode is _not_ guaranteed to catch all the sync points, and
you may still have to place some manually.
Auto-sync mode doesn't prevent you from declaring manual sync
points: it just adds automatically generated ones to the ones you
provide. It's perfectly feasible to specify `-i' _and_ some `-s'
options.
Another caveat with auto-sync mode is that if, by some unpleasant
fluke, something in your data section should disassemble to a
PC-relative call or jump instruction, NDISASM may obediently place a
sync point in a totally random place, for example in the middle of
one of the instructions in your code section. So you may end up with
a wrong disassembly even if you use auto-sync. Again, there isn't
much I can do about this. If you have problems, you'll have to use
manual sync points, or use the `-k' option (documented below) to
suppress disassembly of the data area.
Other Options
=============
The `-e' option skips a header on the file, by ignoring the first N
bytes. This means that the header is _not_ counted towards the
disassembly offset: if you give `-e10 -o10', disassembly will start
at byte 10 in the file, and this will be given offset 10, not 20.
The `-k' option is provided with two comma-separated numeric
arguments, the first of which is an assembly offset and the second
is a number of bytes to skip. This _will_ count the skipped bytes
towards the assembly offset: its use is to suppress disassembly of a
data section which wouldn't contain anything you wanted to see
anyway.
Bugs and Improvements
=====================
There are no known bugs. However, any you find, with patches if
possible, should be sent to <jules@dcs.warwick.ac.uk> or
<anakin@pobox.com>, and we'll try to fix them. Feel free to send
contributions and new features as well.
Future plans include awareness of which processors certain
instructions will run on, and marking of instructions that are too
advanced for some processor (or are FPU instructions, or are
undocumented opcodes, or are privileged protected-mode instructions,
or whatever).
That's All Folks!
=================
I hope NDISASM is of some use to somebody. Including me. :-)
I don't recommend taking NDISASM apart to see how an efficient
disassembler works, because as far as I know, it isn't an efficient
one anyway. You have been warned.
Please feel free to send comments, suggestions, or chat to
<anakin@pobox.com>. As with NASM, no flames please.
- Simon Tatham <anakin@pobox.com>, 21-Nov-96

View File

@ -1,441 +0,0 @@
;--------=========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__

View File

@ -1,63 +0,0 @@
Differences between RDOFF versions 1 & 2
========================================
This document is designed primarily for people maintaining code which
uses RDOFF version 1, and would like to upgrade that code to work
with version 2.
The main changes are summarised here:
Overall format
==============
The overall format has changed somewhat since version 1, in order
to make RDOFF more flexible. After the file type identifier (which
has been changed to 'RDOFF2', obviously), there is now a 4 byte
integer describing the length of the object module. This allows
multiple objects to be concatenated, while the loader can easily
build an index of the locations of each object. This isn't as
pointless as it sounds; I'm using RDOFF in a microkernel operating
system, and this is the ideal way of loading multiple driver modules
at boot time.
There are also no longer a fixed number of segments; instead there
is a list of segments, immediately following the header.
Each segment is preceded by a 10 byte header giving information about
that segment. This header has the following format:
Length Description
2 Type
2 Number
2 Reserved
4 Length
'Type' is a number describing what sort of segment it is (eg text, data,
comment, debug info). See 'rdoff2.txt' for a list of the segment types.
'Number' is the number used to refer to the segment in the header records.
Not all segments will be loaded; it is only intended that one code
and one data segment will be loaded into memory. It is possible, however,
for a loaded segment to contain a reference to an unloaded segment.
This is an error, and should be flagged at load time. Or maybe you should
load the segment... its up to you, really.
The segment's data immediately follows the end of the segment header.
HEADER RECORDS
==============
All of the header records have changed in this version, but not
substantially. Each record type has had a content-length code added,
a single byte immediately following the type byte. This contains the
length of the rest of the record (excluding the type and length bytes,
but including the terminating nulls on any strings in the record).
There are two new record types, Segment Relocation (6), and FAR import (7).
The record formats are identical to Relocation (1) and import (2). They are
only of real use on systems using segmented architectures. Systems using
a flat model should treat FAR import (7) exactly the same as an import (2),
and should either flag segment relocation as an error, or attempt to figure
out whether it is a reference to a code or data symbol, and set the value
referenced to the according selector value. I am opting for the former
approach, and would recommend that others working on 32 bit flat systems
do the same.

75
rdoff/Mkfiles/Makefile.dj Normal file
View File

@ -0,0 +1,75 @@
# Generated automatically from Makefile.in by configure.
#
# Auto-configuring Makefile for RDOFF object file utils; part of the
# Netwide Assembler
#
# The Netwide Assembler is copyright (C) 1996 Simon Tatham and
# Julian Hall. All rights reserved. The software is
# redistributable under the licence given in the file "Licence"
# distributed in the NASM archive.
# You may need to adjust these values.
prefix = /djgpp
CC = gcc -s
CFLAGS = -O2 -I..
# You _shouldn't_ need to adjust anything below this line.
exec_prefix = ${prefix}
bindir = ${exec_prefix}/bin
mandir = ${prefix}/man
INSTALL = /usr/bin/install -c
INSTALL_PROGRAM = ${INSTALL}
INSTALL_DATA = ${INSTALL} -m 644
LN_S = ln -s
LDRDFLIBS = rdoff.o ../nasmlib.o symtab.o hash.o collectn.o rdlib.o segtab.o
RDXLIBS = rdoff.o rdfload.o symtab.o hash.o collectn.o
.c.o:
$(CC) -c $(CFLAGS) $*.c
all: rdfdump ldrdf rdx rdflib rdf2bin rdf2com
rdfdump: rdfdump.o
$(CC) -o rdfdump rdfdump.o
ldrdf: ldrdf.o $(LDRDFLIBS)
$(CC) -o ldrdf ldrdf.o $(LDRDFLIBS)
rdx: rdx.o $(RDXLIBS)
$(CC) -o rdx rdx.o $(RDXLIBS)
rdflib: rdflib.o
$(CC) -o rdflib rdflib.o
rdf2bin: rdf2bin.o $(RDXLIBS) nasmlib.o
$(CC) -o rdf2bin rdf2bin.o $(RDXLIBS) nasmlib.o
rdf2com:
$(LN_S) rdf2bin rdf2com
rdf2bin.o: rdf2bin.c
rdfdump.o: rdfdump.c
rdoff.o: rdoff.c rdoff.h
ldrdf.o: ldrdf.c rdoff.h ../nasmlib.h symtab.h collectn.h rdlib.h
symtab.o: symtab.c symtab.h hash.h
collectn.o: collectn.c collectn.h
rdx.o: rdx.c rdoff.h rdfload.h symtab.h
rdfload.o: rdfload.c rdfload.h rdoff.h collectn.h symtab.h
rdlib.o: rdlib.c rdlib.h
rdflib.o: rdflib.c
hash.o: hash.c hash.h
segtab.o: segtab.c segtab.h
nasmlib.o: ../nasmlib.c ../nasmlib.h ../names.c ../nasm.h
$(CC) -c $(CFLAGS) ../nasmlib.c
clean:
rm -f *.o rdfdump ldrdf rdx rdflib rdf2bin rdf2com
install: rdfdump ldrdf rdx rdflib rdf2bin rdf2com
$(INSTALL_PROGRAM) rdfdump $(bindir)/rdfdump
$(INSTALL_PROGRAM) ldrdf $(bindir)/ldrdf
$(INSTALL_PROGRAM) rdx $(bindir)/rdx
$(INSTALL_PROGRAM) rdflib $(bindir)/rdflib
$(INSTALL_PROGRAM) rdf2bin $(bindir)/rdf2bin
cd $(bindir); $(LN_S) rdf2bin rdf2com

View File

@ -0,0 +1,76 @@
# Generated automatically from Makefile.in by configure.
# $Id$
#
# Auto-configuring Makefile for RDOFF object file utils; part of the
# Netwide Assembler
#
# The Netwide Assembler is copyright (C) 1996 Simon Tatham and
# Julian Hall. All rights reserved. The software is
# redistributable under the licence given in the file "Licence"
# distributed in the NASM archive.
top_srcdir = ..
srcdir = .
prefix = /usr/local
exec_prefix = ${prefix}
bindir = ${exec_prefix}/bin
mandir = ${prefix}/man
CC = gcc
CFLAGS = -s -Zomf -O2 -fomit-frame-pointer -Wall -ansi -pedantic -I$(srcdir) -I$(top_srcdir)
LDFLAGS = -s -Zomf -Zexe -Zcrtdll
LIBS = -lgcc
INSTALL = .././install-sh -c
INSTALL_PROGRAM = ${INSTALL}
INSTALL_DATA = ${INSTALL} -m 644
LDRDFLIBS = rdoff.o nasmlib.o symtab.o collectn.o rdlib.o segtab.o hash.o
RDXLIBS = rdoff.o rdfload.o symtab.o collectn.o hash.o
.c.o:
$(CC) -c $(CFLAGS) -o $@ $<
all: rdfdump ldrdf rdx rdflib rdf2bin
rdfdump: rdfdump.o
$(CC) $(LDFLAGS) -o rdfdump rdfdump.o $(LIBS)
ldrdf: ldrdf.o $(LDRDFLIBS)
$(CC) $(LDFLAGS) -o ldrdf ldrdf.o $(LDRDFLIBS) $(LIBS)
rdx: rdx.o $(RDXLIBS)
$(CC) $(LDFLAGS) -o rdx rdx.o $(RDXLIBS) $(LIBS)
rdflib: rdflib.o
$(CC) $(LDFLAGS) -o rdflib rdflib.o $(LIBS)
rdf2bin: rdf2bin.o $(RDXLIBS) nasmlib.o
$(CC) $(LDFLAGS) -o rdf2bin rdf2bin.o $(RDXLIBS) nasmlib.o $(LIBS)
rdf2bin.o: rdf2bin.c
rdfdump.o: rdfdump.c
rdoff.o: rdoff.c rdoff.h
ldrdf.o: ldrdf.c rdoff.h $(top_srcdir)/nasmlib.h symtab.h collectn.h rdlib.h
symtab.o: symtab.c symtab.h
collectn.o: collectn.c collectn.h
rdx.o: rdx.c rdoff.h rdfload.h symtab.h
rdfload.o: rdfload.c rdfload.h rdoff.h collectn.h symtab.h
rdlib.o: rdlib.c rdlib.h
rdflib.o: rdflib.c
segtab.o: segtab.c
nasmlib.o: $(top_srcdir)/nasmlib.c
$(CC) -c $(CFLAGS) -o $@ $(top_srcdir)/nasmlib.c
clean:
rm -f *.o rdfdump ldrdf rdx rdflib rdf2bin rdf2com
spotless: clean
rm -f Makefile
distclean: spotless
install: rdfdump ldrdf rdx rdflib rdf2bin rdf2com
$(INSTALL_PROGRAM) rdfdump $(INSTALLROOT)$(bindir)/rdfdump
$(INSTALL_PROGRAM) ldrdf $(INSTALLROOT)$(bindir)/ldrdf
$(INSTALL_PROGRAM) rdx $(INSTALLROOT)$(bindir)/rdx
$(INSTALL_PROGRAM) rdflib $(INSTALLROOT)$(bindir)/rdflib
$(INSTALL_PROGRAM) rdf2bin $(INSTALLROOT)$(bindir)/rdf2bin
cd $(INSTALLROOT)$(bindir) && rm -f rdf2com && $(LN_S) rdf2bin rdf2com

56
rdoff/Mkfiles/Makefile.sc Normal file
View File

@ -0,0 +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)

View File

@ -0,0 +1,75 @@
# Generated automatically from Makefile.in by configure.
#
# Auto-configuring Makefile for RDOFF object file utils; part of the
# Netwide Assembler
#
# The Netwide Assembler is copyright (C) 1996 Simon Tatham and
# Julian Hall. All rights reserved. The software is
# redistributable under the licence given in the file "Licence"
# distributed in the NASM archive.
# You may need to adjust these values.
prefix = /usr/local
CC = cc
CFLAGS = -O -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

4
rdoff/Mkfiles/README Normal file
View File

@ -0,0 +1,4 @@
These are pre-created Makefiles for various platforms, use them if
GNU autoconf/automake packages are not supported on your system.
Copy appropriate Makefile to ../Makefile and run make.

View File

@ -1,728 +0,0 @@
/* ldrdf.c RDOFF Object File linker/loader main program
*
* 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.
*/
/* TODO: Make the system skip a module (other than the first) if none
* of the other specified modules contain a reference to it.
* May require the system to make an extra pass of the modules to be
* loaded eliminating those that aren't required.
*
* Support all the existing documented options...
*
* Support libaries (.a files - requires a 'ranlib' type utility)
* (I think I've got this working, so I've upped the version)
*
* -s option to strip resolved symbols from exports. (Could make this an
* external utility)
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "rdoff.h"
#include "nasmlib.h"
#include "symtab.h"
#include "collectn.h"
#include "rdlib.h"
#define LDRDF_VERSION "0.30"
/* global variables - those to set options: */
int verbose = 0; /* reflects setting of command line switch */
int align = 16;
int errors = 0; /* set by functions to cause halt after current
stage of processing */
/* the linked list of modules that must be loaded & linked */
struct modulenode {
rdffile f; /* the file */
long coderel; /* module's code relocation factor */
long datarel; /* module's data relocation factor */
long bssrel; /* module's bss data reloc. factor */
void * header; /* header location, if loaded */
char * name; /* filename */
struct modulenode *next;
};
#define newstr(str) strcpy(malloc(strlen(str) + 1),str)
#define newstrcat(s1,s2) strcat(strcpy(malloc(strlen(s1)+strlen(s2)+1),s1),s2)
struct modulenode *modules = NULL,*lastmodule = NULL;
/* the linked list of libraries to be searched for missing imported
symbols */
struct librarynode * libraries = NULL, * lastlib = NULL;
void *symtab; /* The symbol table */
rdf_headerbuf * newheader ; /* New header to be written to output */
/* loadmodule - find the characteristics of a module and add it to the
* list of those being linked together */
void loadmodule(char *filename)
{
struct modulenode *prev;
if (! modules) {
modules = malloc(sizeof(struct modulenode));
lastmodule = modules;
prev = NULL;
}
else {
lastmodule->next = malloc(sizeof(struct modulenode));
prev = lastmodule;
lastmodule = lastmodule->next;
}
if (! lastmodule) {
fputs("ldrdf: not enough memory\n",stderr);
exit(1);
}
if (rdfopen(&lastmodule->f,filename)) {
rdfperror("ldrdf",filename);
exit(1);
}
lastmodule->header = NULL; /* header hasn't been loaded */
lastmodule->name = filename;
lastmodule->next = NULL;
if (prev) {
lastmodule->coderel = prev->coderel + prev->f.code_len;
if (lastmodule->coderel % align != 0)
lastmodule->coderel += align - (lastmodule->coderel % align);
lastmodule->datarel = prev->datarel + prev->f.data_len;
if (lastmodule->datarel % align != 0)
lastmodule->datarel += align - (lastmodule->datarel % align);
}
else {
lastmodule->coderel = 0;
lastmodule->datarel = 0;
}
if (verbose)
printf("%s code = %08lx (+%04lx), data = %08lx (+%04lx)\n",filename,
lastmodule->coderel,lastmodule->f.code_len,
lastmodule->datarel,lastmodule->f.data_len);
lastmodule->header = malloc(lastmodule->f.header_len);
if (!lastmodule->header) {
fprintf(stderr,"ldrdf: out of memory\n");
exit(1);
}
if (rdfloadseg(&lastmodule->f,RDOFF_HEADER,lastmodule->header))
{
rdfperror("ldrdf",filename);
exit(1);
}
}
/* load_library add a library to list of libraries to search
* for undefined symbols
*/
void load_library(char * name)
{
if (verbose)
printf("adding library %s to search path\n",name);
if (! lastlib) {
lastlib = libraries = malloc(sizeof(struct librarynode));
}
else
{
lastlib->next = malloc(sizeof(struct librarynode));
lastlib = lastlib->next;
}
if (! lastlib) {
fprintf(stderr, "ldrdf: out of memory\n");
exit(1);
}
strcpy (lastlib->name = malloc (1+strlen(name)), name);
lastlib->fp = NULL;
lastlib->referenced = 0;
lastlib->next = NULL;
}
/* build_symbols() step through each module's header, and locate
* exported symbols, placing them in a global table
*/
long bsslength;
void mod_addsymbols(struct modulenode * mod)
{
rdfheaderrec *r;
symtabEnt e;
long cbBss;
mod->bssrel = bsslength;
cbBss = 0;
rdfheaderrewind(&mod->f);
while ((r = rdfgetheaderrec(&mod->f)))
{
if (r->type == 5) /* Allocate BSS */
cbBss += r->b.amount;
if (r->type != 3) continue; /* ignore all but export recs */
e.segment = r->e.segment;
e.offset = r->e.offset +
(e.segment == 0 ? mod->coderel : /* 0 -> code */
e.segment == 1 ? mod->datarel : /* 1 -> data */
mod->bssrel) ; /* 2 -> bss */
e.flags = 0;
e.name = malloc(strlen(r->e.label) + 1);
if (! e.name)
{
fprintf(stderr,"ldrdf: out of memory\n");
exit(1);
}
strcpy(e.name,r->e.label);
symtabInsert(symtab,&e);
}
bsslength += cbBss;
}
void build_symbols()
{
struct modulenode *mod;
if (verbose) printf("building global symbol table:\n");
newheader = rdfnewheader();
symtab = symtabNew();
bsslength = 0; /* keep track of location of BSS symbols */
for (mod = modules; mod; mod = mod->next)
{
mod_addsymbols( mod );
}
if (verbose)
{
symtabDump(symtab,stdout);
printf("BSS length = %ld bytes\n\n",bsslength);
}
}
/* scan_libraries() search through headers of modules for undefined
* symbols, and scan libraries for those symbols,
* adding library modules found to list of modules
* to load. */
void scan_libraries(void)
{
struct modulenode * mod, * nm;
struct librarynode * lib;
rdfheaderrec * r;
int found;
char * tmp;
if (verbose) printf("Scanning libraries for unresolved symbols...\n");
mod = modules;
while (mod)
{
rdfheaderrewind(&mod->f);
while ((r = rdfgetheaderrec(&mod->f)))
{
if (r->type != 2) continue; /* not an import record */
if ( symtabFind (symtab,r->i.label) )
continue; /* symbol already defined */
/* okay, we have an undefined symbol... step through
the libraries now */
if (verbose >= 2) {
printf("undefined symbol '%s'...",r->i.label);
fflush(stdout);
}
lib = libraries;
found = 0;
tmp = newstr(r->i.label);
while (! found && lib)
{
/* move this to an outer loop...! */
nm = malloc(sizeof(struct modulenode));
if (rdl_searchlib(lib,tmp,&nm->f))
{ /* found a module in the library */
/* create a modulenode for it */
if (! nm) {
fprintf(stderr,"ldrdf: out of memory\n");
exit(1);
}
nm->name = newstrcat(lib->name,nm->f.name);
if (verbose >= 2) printf("found in '%s'\n",nm->name);
nm->coderel = lastmodule->coderel + lastmodule->f.code_len;
if (nm->coderel % align != 0)
nm->coderel += align - (nm->coderel % align);
nm->datarel = lastmodule->datarel + lastmodule->f.data_len;
if (nm->datarel % align != 0)
nm->datarel += align - (nm->datarel % align);
nm->header = malloc(nm->f.header_len);
if (! nm->header)
{
fprintf(stderr,"ldrdf: out of memory\n");
exit(1);
}
if (rdfloadseg(&nm->f,RDOFF_HEADER,nm->header))
{
rdfperror("ldrdf",nm->name);
exit(1);
}
nm->next = NULL;
found = 1;
lastmodule->next = nm;
lastmodule = nm;
if (verbose)
printf("%s code = %08lx (+%04lx), data = %08lx "
"(+%04lx)\n",lastmodule->name,
lastmodule->coderel,lastmodule->f.code_len,
lastmodule->datarel,lastmodule->f.data_len);
/* add the module's info to the symbol table */
mod_addsymbols(nm);
}
else
{
if (rdl_error) {
rdl_perror("ldrdf",lib->name);
exit(1);
}
free(nm);
}
lib = lib->next;
}
free(tmp);
if (!found && verbose >= 2) printf("not found\n");
}
mod = mod->next;
}
}
/* load_segments() allocates memory for & loads the code & data segs
* from the RDF modules
*/
char *text,*data;
long textlength,datalength;
void load_segments(void)
{
struct modulenode *mod;
if (!modules) {
fprintf(stderr,"ldrdf: nothing to do\n");
exit(0);
}
if (!lastmodule) {
fprintf(stderr,"ldrdf: panic: module list exists, but lastmodule=NULL\n");
exit(3);
}
if (verbose)
printf("loading modules into memory\n");
/* The following stops 16 bit DOS from crashing whilst attempting to
work using segments > 64K */
if (sizeof(int) == 2) { /* expect a 'code has no effect' warning on 32 bit
platforms... */
if (lastmodule->coderel + lastmodule->f.code_len > 65535 ||
lastmodule->datarel + lastmodule->f.data_len > 65535) {
fprintf(stderr,"ldrdf: segment length has exceeded 64K; use a 32 bit "
"version.\nldrdf: code size = %05lx, data size = %05lx\n",
lastmodule->coderel + lastmodule->f.code_len,
lastmodule->datarel + lastmodule->f.data_len);
exit(1);
}
}
text = malloc(textlength = lastmodule->coderel + lastmodule->f.code_len);
data = malloc(datalength = lastmodule->datarel + lastmodule->f.data_len);
if (!text || !data) {
fprintf(stderr,"ldrdf: out of memory\n");
exit(1);
}
mod = modules;
while (mod) { /* load the segments for each module */
if (verbose >= 2) printf(" loading %s\n",mod->name);
if (rdfloadseg(&mod->f,RDOFF_CODE,&text[mod->coderel]) ||
rdfloadseg(&mod->f,RDOFF_DATA,&data[mod->datarel])) {
rdfperror("ldrdf",mod->name);
exit(1);
}
rdfclose(&mod->f); /* close file; segments remain */
mod = mod->next;
}
}
/* link_segments() step through relocation records in each module's
* header, fixing up references.
*/
void link_segments(void)
{
struct modulenode *mod;
Collection imports;
symtabEnt *s;
long rel,relto;
char *seg;
rdfheaderrec *r;
int bRelative;
if (verbose) printf("linking segments\n");
collection_init(&imports);
for (mod = modules; mod; mod = mod->next) {
if (verbose >= 2) printf("* processing %s\n",mod->name);
rdfheaderrewind(&mod->f);
while((r = rdfgetheaderrec(&mod->f))) {
if (verbose >= 3) printf("record type: %d\n",r->type);
switch(r->type) {
case 1: /* relocation record */
if (r->r.segment >= 64) { /* Relative relocation; */
bRelative = 1; /* need to find location relative */
r->r.segment -= 64; /* to start of this segment */
relto = r->r.segment == 0 ? mod->coderel : mod->datarel;
}
else
{
bRelative = 0; /* non-relative - need to relocate
* at load time */
relto = 0; /* placate optimiser warnings */
}
/* calculate absolute offset of reference, not rel to beginning of
segment */
r->r.offset += r->r.segment == 0 ? mod->coderel : mod->datarel;
/* calculate the relocation factor to apply to the operand -
the base address of one of this modules segments if referred
segment is 0 - 2, or the address of an imported symbol
otherwise. */
if (r->r.refseg == 0) rel = mod->coderel;
else if (r->r.refseg == 1) rel = mod->datarel;
else if (r->r.refseg == 2) rel = mod->bssrel;
else { /* cross module link - find reference */
s = *colln(&imports,r->r.refseg - 2);
if (!s) {
fprintf(stderr,"ldrdf: link to undefined segment %04x in"
" %s:%d\n", r->r.refseg,mod->name,r->r.segment);
errors = 1;
break;
}
rel = s->offset;
r->r.refseg = s->segment; /* change referred segment,
so that new header is
correct */
}
if (bRelative) /* Relative - subtract current segment start */
rel -= relto;
else
{ /* Add new relocation header */
rdfaddheader(newheader,r);
}
/* Work out which segment we're making changes to ... */
if (r->r.segment == 0) seg = text;
else if (r->r.segment == 1) seg = data;
else {
fprintf(stderr,"ldrdf: relocation in unknown segment %d in "
"%s\n", r->r.segment,mod->name);
errors = 1;
break;
}
/* Add the relocation factor to the datum specified: */
if (verbose >= 3)
printf(" - relocating %d:%08lx by %08lx\n",r->r.segment,
r->r.offset,rel);
/**** The following code is non-portable. Rewrite it... ****/
switch(r->r.length) {
case 1:
seg[r->r.offset] += (char) rel;
break;
case 2:
*(int16 *)(seg + r->r.offset) += (int16) rel;
break;
case 4:
*(long *)(seg + r->r.offset) += rel;
break;
}
break;
case 2: /* import record */
s = symtabFind(symtab, r->i.label);
if (s == NULL) {
/* Need to add support for dynamic linkage */
fprintf(stderr,"ldrdf: undefined symbol %s in module %s\n",
r->i.label,mod->name);
errors = 1;
}
else
{
*colln(&imports,r->i.segment - 2) = s;
if (verbose >= 2)
printf("imported %s as %04x\n", r->i.label, r->i.segment);
}
break;
case 3: /* export; dump to output new version */
s = symtabFind(symtab, r->e.label);
if (! s) {
fprintf(stderr,"ldrdf: internal error - undefined symbol %s "
"exported in header of '%s'\n",r->e.label,mod->name);
continue;
}
r->e.offset = s->offset;
rdfaddheader(newheader,r);
break;
case 4: /* DLL record */
rdfaddheader(newheader,r); /* copy straight to output */
break;
}
}
if (rdf_errno != 0) {
rdfperror("ldrdf",mod->name);
exit(1);
}
collection_reset(&imports);
}
}
/* write_output() write linked program out to a file */
void write_output(char *filename)
{
FILE * fp;
rdfheaderrec r;
if (verbose) printf("writing output to '%s'\n",filename);
fp = fopen(filename,"wb");
if (! fp)
{
fprintf(stderr,"ldrdf: could not open '%s' for writing\n",filename);
exit(1);
}
/* add BSS length count to header... */
if (bsslength)
{
r.type = 5;
r.b.amount = bsslength;
rdfaddheader(newheader,&r);
}
/* Write header */
rdfwriteheader(fp,newheader);
rdfdoneheader(newheader);
newheader = NULL;
/* Write text */
if (fwrite(&textlength,1,4,fp) != 4
|| fwrite(text,1,textlength,fp) !=textlength)
{
fprintf(stderr,"ldrdf: error writing %s\n",filename);
exit(1);
}
/* Write data */
if (fwrite(&datalength,1,4,fp) != 4 ||
fwrite(data,1,datalength,fp) != datalength)
{
fprintf (stderr,"ldrdf: error writing %s\n", filename);
exit(1);
}
fclose(fp);
}
/* main program: interpret command line, and pass parameters on to
* individual module loaders & the linker
*
* Command line format:
* ldrdf [-o outfile | -x] [-r xxxx] [-v] [--] infile [infile ...]
*
* Default action is to output a file named 'aout.rdx'. -x specifies
* that the linked object program should be executed, rather than
* written to a file. -r specifies that the object program should
* be prelocated at address 'xxxx'. This option cannot be used
* in conjunction with -x.
*/
const char *usagemsg = "usage:\n"
" ldrdf [-o outfile | -x] [-a x] [-v] [-p x] [--] infile [infile ...]\n"
" [-l<libname> ...]\n\n"
" ldrdf -h displays this message\n"
" ldrdf -r displays version information\n\n"
" -o selects output filename (default is aout.rdx)\n"
" -x causes ldrdx to link & execute rather than write to file\n"
" -a x causes object program to be statically relocated to address 'x'\n"
" -v turns on verbose mode\n"
" -p x causes segments to be aligned (padded) to x byte boundaries\n"
" (default is 16 bytes)\n"
" -l<name> causes 'name' to be linked in as a library. Note no search is\n"
" performed - the entire pathname MUST be specified.\n";
void usage(void)
{
fputs(usagemsg,stderr);
}
int main(int argc,char **argv)
{
char *ofilename = "aout.rdx";
long relocateaddr = -1; /* -1 if no relocation is to occur */
int execute = 0; /* 1 to execute after linking, 0 otherwise */
int procsw = 1; /* set to 0 by '--' */
int tmp;
if (argc == 1) {
usage();
exit(1);
}
/* process command line switches, and add modules specified to linked list
of modules, keeping track of total memory required to load them */
while(argv++,--argc) {
if (procsw && !strcmp(*argv,"-h")) { /* Help command */
usage(); exit(1);
}
else if (procsw && !strcmp(*argv,"-r")) {
printf("ldrdf version %s (%s) (%s)\n",LDRDF_VERSION,_RDOFF_H,
sizeof(int) == 2 ? "16 bit" : "32 bit");
exit(1);
}
else if (procsw && !strcmp(*argv,"-o")) {
ofilename = *++argv;
--argc;
if (execute) {
fprintf(stderr,"ldrdf: -o and -x switches incompatible\n");
exit(1);
}
if (verbose > 1) printf("output filename set to '%s'\n",ofilename);
}
else if (procsw && !strcmp(*argv,"-x")) {
execute++;
if (verbose > 1) printf("will execute linked object\n");
}
else if (procsw && !strcmp(*argv,"-a")) {
relocateaddr = readnum(*++argv,&tmp);
--argc;
if (tmp) {
fprintf(stderr,"ldrdf: error in parameter to '-a' switch: '%s'\n",
*argv);
exit(1);
}
if (execute) {
fprintf(stderr,"ldrdf: -a and -x switches incompatible\n");
exit(1);
}
if (verbose) printf("will relocate to %08lx\n",relocateaddr);
}
else if (procsw && !strcmp(*argv,"-v")) {
verbose++;
if (verbose == 1) printf("verbose mode selected\n");
}
else if (procsw && !strcmp(*argv,"-p")) {
align = readnum(*++argv,&tmp);
--argc;
if (tmp) {
fprintf(stderr,"ldrdf: error in parameter to '-p' switch: '%s'\n",
*argv);
exit(1);
}
if (align != 1 && align != 2 && align != 4 && align != 8 && align != 16
&& align != 32 && align != 256) {
fprintf(stderr,"ldrdf: %d is an invalid alignment factor - must be"
"1,2,4,8,16 or 256\n",align);
exit(1);
}
if (verbose > 1) printf("alignment %d selected\n",align);
}
else if (procsw && !strncmp(*argv,"-l",2)) {
load_library(*argv + 2);
}
else if (procsw && !strcmp(*argv,"--")) {
procsw = 0;
}
else { /* is a filename */
if (verbose > 1) printf("processing module %s\n",*argv);
loadmodule(*argv);
}
}
/* we should be scanning for unresolved references, and removing
unreferenced modules from the list of modules here, so that
we know about the final size once libraries have been linked in */
build_symbols(); /* build a global symbol table... */
scan_libraries(); /* check for imported symbols not in table,
and ensure the relevant library modules
are loaded */
load_segments(); /* having calculated size of reqd segments, load
each rdoff module's segments into memory */
link_segments(); /* step through each module's header, and resolve
references to the global symbol table.
This also does local address fixups. */
if (errors) {
fprintf(stderr,"ldrdf: there were errors - aborted\n");
exit(errors);
}
if (execute) {
fprintf(stderr,"ldrdf: module execution not yet supported\n");
exit(1);
}
if (relocateaddr != -1) {
fprintf(stderr,"ldrdf: static relocation not yet supported\n");
exit(1);
}
write_output(ofilename);
return 0;
}

View File

@ -1,14 +0,0 @@
LIBNAME=$1;
shift;
if [ "$LIBNAME" = "" ]; then
echo 'Usage: makelib <library name> <module> [...]'
fi
rdflib c $LIBNAME
for FILE in $*; do
rdflib a $LIBNAME $FILE $FILE
done

View File

@ -1,5 +0,0 @@
This directory contains programs for working with RDOFF version 1 object
files. RDOFF version 1 is no longer supported - you should now be using
RDOFF2. If you are working with your own code, the changes you will need
to make are very simple, and are outlined in the document Changes in the
nasm/rdoff directory.

View File

@ -1,40 +0,0 @@
/* collectn.c Implements variable length pointer arrays [collections]
*
* This file is public domain.
*/
#include "collectn.h"
#include <stdlib.h>
void collection_init(Collection * c)
{
int i;
for (i = 0; i < 32; i++) c->p[i] = NULL;
c->next = NULL;
}
void ** colln(Collection * c, int index)
{
while (index >= 32) {
index -= 32;
if (c->next == NULL) {
c->next = malloc(sizeof(Collection));
collection_init(c->next);
}
c = c->next;
}
return &(c->p[index]);
}
void collection_reset(Collection *c)
{
int i;
if (c->next) {
collection_reset(c->next);
free(c->next);
}
c->next = NULL;
for (i = 0; i < 32; i++) c->p[i] = NULL;
}

View File

@ -1,22 +0,0 @@
/* collectn.h Header file for 'collection' abstract data type
*
* This file is public domain, and does not come under the NASM license.
* It, along with 'collectn.c' implements what is basically a variable
* length array (of pointers)
*/
#ifndef _COLLECTN_H
#define _COLLECTN_H
typedef struct tagCollection {
void *p[32]; /* array of pointers to objects */
struct tagCollection *next;
} Collection;
void collection_init(Collection * c);
void ** colln(Collection * c, int index);
void collection_reset(Collection * c);
#endif

View File

@ -1,728 +0,0 @@
/* ldrdf.c RDOFF Object File linker/loader main program
*
* 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.
*/
/* TODO: Make the system skip a module (other than the first) if none
* of the other specified modules contain a reference to it.
* May require the system to make an extra pass of the modules to be
* loaded eliminating those that aren't required.
*
* Support all the existing documented options...
*
* Support libaries (.a files - requires a 'ranlib' type utility)
* (I think I've got this working, so I've upped the version)
*
* -s option to strip resolved symbols from exports. (Could make this an
* external utility)
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "rdoff.h"
#include "nasmlib.h"
#include "symtab.h"
#include "collectn.h"
#include "rdlib.h"
#define LDRDF_VERSION "0.30"
/* global variables - those to set options: */
int verbose = 0; /* reflects setting of command line switch */
int align = 16;
int errors = 0; /* set by functions to cause halt after current
stage of processing */
/* the linked list of modules that must be loaded & linked */
struct modulenode {
rdffile f; /* the file */
long coderel; /* module's code relocation factor */
long datarel; /* module's data relocation factor */
long bssrel; /* module's bss data reloc. factor */
void * header; /* header location, if loaded */
char * name; /* filename */
struct modulenode *next;
};
#define newstr(str) strcpy(malloc(strlen(str) + 1),str)
#define newstrcat(s1,s2) strcat(strcpy(malloc(strlen(s1)+strlen(s2)+1),s1),s2)
struct modulenode *modules = NULL,*lastmodule = NULL;
/* the linked list of libraries to be searched for missing imported
symbols */
struct librarynode * libraries = NULL, * lastlib = NULL;
void *symtab; /* The symbol table */
rdf_headerbuf * newheader ; /* New header to be written to output */
/* loadmodule - find the characteristics of a module and add it to the
* list of those being linked together */
void loadmodule(char *filename)
{
struct modulenode *prev;
if (! modules) {
modules = malloc(sizeof(struct modulenode));
lastmodule = modules;
prev = NULL;
}
else {
lastmodule->next = malloc(sizeof(struct modulenode));
prev = lastmodule;
lastmodule = lastmodule->next;
}
if (! lastmodule) {
fputs("ldrdf: not enough memory\n",stderr);
exit(1);
}
if (rdfopen(&lastmodule->f,filename)) {
rdfperror("ldrdf",filename);
exit(1);
}
lastmodule->header = NULL; /* header hasn't been loaded */
lastmodule->name = filename;
lastmodule->next = NULL;
if (prev) {
lastmodule->coderel = prev->coderel + prev->f.code_len;
if (lastmodule->coderel % align != 0)
lastmodule->coderel += align - (lastmodule->coderel % align);
lastmodule->datarel = prev->datarel + prev->f.data_len;
if (lastmodule->datarel % align != 0)
lastmodule->datarel += align - (lastmodule->datarel % align);
}
else {
lastmodule->coderel = 0;
lastmodule->datarel = 0;
}
if (verbose)
printf("%s code = %08lx (+%04lx), data = %08lx (+%04lx)\n",filename,
lastmodule->coderel,lastmodule->f.code_len,
lastmodule->datarel,lastmodule->f.data_len);
lastmodule->header = malloc(lastmodule->f.header_len);
if (!lastmodule->header) {
fprintf(stderr,"ldrdf: out of memory\n");
exit(1);
}
if (rdfloadseg(&lastmodule->f,RDOFF_HEADER,lastmodule->header))
{
rdfperror("ldrdf",filename);
exit(1);
}
}
/* load_library add a library to list of libraries to search
* for undefined symbols
*/
void load_library(char * name)
{
if (verbose)
printf("adding library %s to search path\n",name);
if (! lastlib) {
lastlib = libraries = malloc(sizeof(struct librarynode));
}
else
{
lastlib->next = malloc(sizeof(struct librarynode));
lastlib = lastlib->next;
}
if (! lastlib) {
fprintf(stderr, "ldrdf: out of memory\n");
exit(1);
}
strcpy (lastlib->name = malloc (1+strlen(name)), name);
lastlib->fp = NULL;
lastlib->referenced = 0;
lastlib->next = NULL;
}
/* build_symbols() step through each module's header, and locate
* exported symbols, placing them in a global table
*/
long bsslength;
void mod_addsymbols(struct modulenode * mod)
{
rdfheaderrec *r;
symtabEnt e;
long cbBss;
mod->bssrel = bsslength;
cbBss = 0;
rdfheaderrewind(&mod->f);
while ((r = rdfgetheaderrec(&mod->f)))
{
if (r->type == 5) /* Allocate BSS */
cbBss += r->b.amount;
if (r->type != 3) continue; /* ignore all but export recs */
e.segment = r->e.segment;
e.offset = r->e.offset +
(e.segment == 0 ? mod->coderel : /* 0 -> code */
e.segment == 1 ? mod->datarel : /* 1 -> data */
mod->bssrel) ; /* 2 -> bss */
e.flags = 0;
e.name = malloc(strlen(r->e.label) + 1);
if (! e.name)
{
fprintf(stderr,"ldrdf: out of memory\n");
exit(1);
}
strcpy(e.name,r->e.label);
symtabInsert(symtab,&e);
}
bsslength += cbBss;
}
void build_symbols()
{
struct modulenode *mod;
if (verbose) printf("building global symbol table:\n");
newheader = rdfnewheader();
symtab = symtabNew();
bsslength = 0; /* keep track of location of BSS symbols */
for (mod = modules; mod; mod = mod->next)
{
mod_addsymbols( mod );
}
if (verbose)
{
symtabDump(symtab,stdout);
printf("BSS length = %ld bytes\n\n",bsslength);
}
}
/* scan_libraries() search through headers of modules for undefined
* symbols, and scan libraries for those symbols,
* adding library modules found to list of modules
* to load. */
void scan_libraries(void)
{
struct modulenode * mod, * nm;
struct librarynode * lib;
rdfheaderrec * r;
int found;
char * tmp;
if (verbose) printf("Scanning libraries for unresolved symbols...\n");
mod = modules;
while (mod)
{
rdfheaderrewind(&mod->f);
while ((r = rdfgetheaderrec(&mod->f)))
{
if (r->type != 2) continue; /* not an import record */
if ( symtabFind (symtab,r->i.label) )
continue; /* symbol already defined */
/* okay, we have an undefined symbol... step through
the libraries now */
if (verbose >= 2) {
printf("undefined symbol '%s'...",r->i.label);
fflush(stdout);
}
lib = libraries;
found = 0;
tmp = newstr(r->i.label);
while (! found && lib)
{
/* move this to an outer loop...! */
nm = malloc(sizeof(struct modulenode));
if (rdl_searchlib(lib,tmp,&nm->f))
{ /* found a module in the library */
/* create a modulenode for it */
if (! nm) {
fprintf(stderr,"ldrdf: out of memory\n");
exit(1);
}
nm->name = newstrcat(lib->name,nm->f.name);
if (verbose >= 2) printf("found in '%s'\n",nm->name);
nm->coderel = lastmodule->coderel + lastmodule->f.code_len;
if (nm->coderel % align != 0)
nm->coderel += align - (nm->coderel % align);
nm->datarel = lastmodule->datarel + lastmodule->f.data_len;
if (nm->datarel % align != 0)
nm->datarel += align - (nm->datarel % align);
nm->header = malloc(nm->f.header_len);
if (! nm->header)
{
fprintf(stderr,"ldrdf: out of memory\n");
exit(1);
}
if (rdfloadseg(&nm->f,RDOFF_HEADER,nm->header))
{
rdfperror("ldrdf",nm->name);
exit(1);
}
nm->next = NULL;
found = 1;
lastmodule->next = nm;
lastmodule = nm;
if (verbose)
printf("%s code = %08lx (+%04lx), data = %08lx "
"(+%04lx)\n",lastmodule->name,
lastmodule->coderel,lastmodule->f.code_len,
lastmodule->datarel,lastmodule->f.data_len);
/* add the module's info to the symbol table */
mod_addsymbols(nm);
}
else
{
if (rdl_error) {
rdl_perror("ldrdf",lib->name);
exit(1);
}
free(nm);
}
lib = lib->next;
}
free(tmp);
if (!found && verbose >= 2) printf("not found\n");
}
mod = mod->next;
}
}
/* load_segments() allocates memory for & loads the code & data segs
* from the RDF modules
*/
char *text,*data;
long textlength,datalength;
void load_segments(void)
{
struct modulenode *mod;
if (!modules) {
fprintf(stderr,"ldrdf: nothing to do\n");
exit(0);
}
if (!lastmodule) {
fprintf(stderr,"ldrdf: panic: module list exists, but lastmodule=NULL\n");
exit(3);
}
if (verbose)
printf("loading modules into memory\n");
/* The following stops 16 bit DOS from crashing whilst attempting to
work using segments > 64K */
if (sizeof(int) == 2) { /* expect a 'code has no effect' warning on 32 bit
platforms... */
if (lastmodule->coderel + lastmodule->f.code_len > 65535 ||
lastmodule->datarel + lastmodule->f.data_len > 65535) {
fprintf(stderr,"ldrdf: segment length has exceeded 64K; use a 32 bit "
"version.\nldrdf: code size = %05lx, data size = %05lx\n",
lastmodule->coderel + lastmodule->f.code_len,
lastmodule->datarel + lastmodule->f.data_len);
exit(1);
}
}
text = malloc(textlength = lastmodule->coderel + lastmodule->f.code_len);
data = malloc(datalength = lastmodule->datarel + lastmodule->f.data_len);
if (!text || !data) {
fprintf(stderr,"ldrdf: out of memory\n");
exit(1);
}
mod = modules;
while (mod) { /* load the segments for each module */
if (verbose >= 2) printf(" loading %s\n",mod->name);
if (rdfloadseg(&mod->f,RDOFF_CODE,&text[mod->coderel]) ||
rdfloadseg(&mod->f,RDOFF_DATA,&data[mod->datarel])) {
rdfperror("ldrdf",mod->name);
exit(1);
}
rdfclose(&mod->f); /* close file; segments remain */
mod = mod->next;
}
}
/* link_segments() step through relocation records in each module's
* header, fixing up references.
*/
void link_segments(void)
{
struct modulenode *mod;
Collection imports;
symtabEnt *s;
long rel,relto;
char *seg;
rdfheaderrec *r;
int bRelative;
if (verbose) printf("linking segments\n");
collection_init(&imports);
for (mod = modules; mod; mod = mod->next) {
if (verbose >= 2) printf("* processing %s\n",mod->name);
rdfheaderrewind(&mod->f);
while((r = rdfgetheaderrec(&mod->f))) {
if (verbose >= 3) printf("record type: %d\n",r->type);
switch(r->type) {
case 1: /* relocation record */
if (r->r.segment >= 64) { /* Relative relocation; */
bRelative = 1; /* need to find location relative */
r->r.segment -= 64; /* to start of this segment */
relto = r->r.segment == 0 ? mod->coderel : mod->datarel;
}
else
{
bRelative = 0; /* non-relative - need to relocate
* at load time */
relto = 0; /* placate optimiser warnings */
}
/* calculate absolute offset of reference, not rel to beginning of
segment */
r->r.offset += r->r.segment == 0 ? mod->coderel : mod->datarel;
/* calculate the relocation factor to apply to the operand -
the base address of one of this modules segments if referred
segment is 0 - 2, or the address of an imported symbol
otherwise. */
if (r->r.refseg == 0) rel = mod->coderel;
else if (r->r.refseg == 1) rel = mod->datarel;
else if (r->r.refseg == 2) rel = mod->bssrel;
else { /* cross module link - find reference */
s = *colln(&imports,r->r.refseg - 2);
if (!s) {
fprintf(stderr,"ldrdf: link to undefined segment %04x in"
" %s:%d\n", r->r.refseg,mod->name,r->r.segment);
errors = 1;
break;
}
rel = s->offset;
r->r.refseg = s->segment; /* change referred segment,
so that new header is
correct */
}
if (bRelative) /* Relative - subtract current segment start */
rel -= relto;
else
{ /* Add new relocation header */
rdfaddheader(newheader,r);
}
/* Work out which segment we're making changes to ... */
if (r->r.segment == 0) seg = text;
else if (r->r.segment == 1) seg = data;
else {
fprintf(stderr,"ldrdf: relocation in unknown segment %d in "
"%s\n", r->r.segment,mod->name);
errors = 1;
break;
}
/* Add the relocation factor to the datum specified: */
if (verbose >= 3)
printf(" - relocating %d:%08lx by %08lx\n",r->r.segment,
r->r.offset,rel);
/**** The following code is non-portable. Rewrite it... ****/
switch(r->r.length) {
case 1:
seg[r->r.offset] += (char) rel;
break;
case 2:
*(int16 *)(seg + r->r.offset) += (int16) rel;
break;
case 4:
*(long *)(seg + r->r.offset) += rel;
break;
}
break;
case 2: /* import record */
s = symtabFind(symtab, r->i.label);
if (s == NULL) {
/* Need to add support for dynamic linkage */
fprintf(stderr,"ldrdf: undefined symbol %s in module %s\n",
r->i.label,mod->name);
errors = 1;
}
else
{
*colln(&imports,r->i.segment - 2) = s;
if (verbose >= 2)
printf("imported %s as %04x\n", r->i.label, r->i.segment);
}
break;
case 3: /* export; dump to output new version */
s = symtabFind(symtab, r->e.label);
if (! s) {
fprintf(stderr,"ldrdf: internal error - undefined symbol %s "
"exported in header of '%s'\n",r->e.label,mod->name);
continue;
}
r->e.offset = s->offset;
rdfaddheader(newheader,r);
break;
case 4: /* DLL record */
rdfaddheader(newheader,r); /* copy straight to output */
break;
}
}
if (rdf_errno != 0) {
rdfperror("ldrdf",mod->name);
exit(1);
}
collection_reset(&imports);
}
}
/* write_output() write linked program out to a file */
void write_output(char *filename)
{
FILE * fp;
rdfheaderrec r;
if (verbose) printf("writing output to '%s'\n",filename);
fp = fopen(filename,"wb");
if (! fp)
{
fprintf(stderr,"ldrdf: could not open '%s' for writing\n",filename);
exit(1);
}
/* add BSS length count to header... */
if (bsslength)
{
r.type = 5;
r.b.amount = bsslength;
rdfaddheader(newheader,&r);
}
/* Write header */
rdfwriteheader(fp,newheader);
rdfdoneheader(newheader);
newheader = NULL;
/* Write text */
if (fwrite(&textlength,1,4,fp) != 4
|| fwrite(text,1,textlength,fp) !=textlength)
{
fprintf(stderr,"ldrdf: error writing %s\n",filename);
exit(1);
}
/* Write data */
if (fwrite(&datalength,1,4,fp) != 4 ||
fwrite(data,1,datalength,fp) != datalength)
{
fprintf (stderr,"ldrdf: error writing %s\n", filename);
exit(1);
}
fclose(fp);
}
/* main program: interpret command line, and pass parameters on to
* individual module loaders & the linker
*
* Command line format:
* ldrdf [-o outfile | -x] [-r xxxx] [-v] [--] infile [infile ...]
*
* Default action is to output a file named 'aout.rdx'. -x specifies
* that the linked object program should be executed, rather than
* written to a file. -r specifies that the object program should
* be prelocated at address 'xxxx'. This option cannot be used
* in conjunction with -x.
*/
const char *usagemsg = "usage:\n"
" ldrdf [-o outfile | -x] [-a x] [-v] [-p x] [--] infile [infile ...]\n"
" [-l<libname> ...]\n\n"
" ldrdf -h displays this message\n"
" ldrdf -r displays version information\n\n"
" -o selects output filename (default is aout.rdx)\n"
" -x causes ldrdx to link & execute rather than write to file\n"
" -a x causes object program to be statically relocated to address 'x'\n"
" -v turns on verbose mode\n"
" -p x causes segments to be aligned (padded) to x byte boundaries\n"
" (default is 16 bytes)\n"
" -l<name> causes 'name' to be linked in as a library. Note no search is\n"
" performed - the entire pathname MUST be specified.\n";
void usage(void)
{
fputs(usagemsg,stderr);
}
int main(int argc,char **argv)
{
char *ofilename = "aout.rdx";
long relocateaddr = -1; /* -1 if no relocation is to occur */
int execute = 0; /* 1 to execute after linking, 0 otherwise */
int procsw = 1; /* set to 0 by '--' */
int tmp;
if (argc == 1) {
usage();
exit(1);
}
/* process command line switches, and add modules specified to linked list
of modules, keeping track of total memory required to load them */
while(argv++,--argc) {
if (procsw && !strcmp(*argv,"-h")) { /* Help command */
usage(); exit(1);
}
else if (procsw && !strcmp(*argv,"-r")) {
printf("ldrdf version %s (%s) (%s)\n",LDRDF_VERSION,_RDOFF_H,
sizeof(int) == 2 ? "16 bit" : "32 bit");
exit(1);
}
else if (procsw && !strcmp(*argv,"-o")) {
ofilename = *++argv;
--argc;
if (execute) {
fprintf(stderr,"ldrdf: -o and -x switches incompatible\n");
exit(1);
}
if (verbose > 1) printf("output filename set to '%s'\n",ofilename);
}
else if (procsw && !strcmp(*argv,"-x")) {
execute++;
if (verbose > 1) printf("will execute linked object\n");
}
else if (procsw && !strcmp(*argv,"-a")) {
relocateaddr = readnum(*++argv,&tmp);
--argc;
if (tmp) {
fprintf(stderr,"ldrdf: error in parameter to '-a' switch: '%s'\n",
*argv);
exit(1);
}
if (execute) {
fprintf(stderr,"ldrdf: -a and -x switches incompatible\n");
exit(1);
}
if (verbose) printf("will relocate to %08lx\n",relocateaddr);
}
else if (procsw && !strcmp(*argv,"-v")) {
verbose++;
if (verbose == 1) printf("verbose mode selected\n");
}
else if (procsw && !strcmp(*argv,"-p")) {
align = readnum(*++argv,&tmp);
--argc;
if (tmp) {
fprintf(stderr,"ldrdf: error in parameter to '-p' switch: '%s'\n",
*argv);
exit(1);
}
if (align != 1 && align != 2 && align != 4 && align != 8 && align != 16
&& align != 32 && align != 256) {
fprintf(stderr,"ldrdf: %d is an invalid alignment factor - must be"
"1,2,4,8,16 or 256\n",align);
exit(1);
}
if (verbose > 1) printf("alignment %d selected\n",align);
}
else if (procsw && !strncmp(*argv,"-l",2)) {
load_library(*argv + 2);
}
else if (procsw && !strcmp(*argv,"--")) {
procsw = 0;
}
else { /* is a filename */
if (verbose > 1) printf("processing module %s\n",*argv);
loadmodule(*argv);
}
}
/* we should be scanning for unresolved references, and removing
unreferenced modules from the list of modules here, so that
we know about the final size once libraries have been linked in */
build_symbols(); /* build a global symbol table... */
scan_libraries(); /* check for imported symbols not in table,
and ensure the relevant library modules
are loaded */
load_segments(); /* having calculated size of reqd segments, load
each rdoff module's segments into memory */
link_segments(); /* step through each module's header, and resolve
references to the global symbol table.
This also does local address fixups. */
if (errors) {
fprintf(stderr,"ldrdf: there were errors - aborted\n");
exit(errors);
}
if (execute) {
fprintf(stderr,"ldrdf: module execution not yet supported\n");
exit(1);
}
if (relocateaddr != -1) {
fprintf(stderr,"ldrdf: static relocation not yet supported\n");
exit(1);
}
write_output(ofilename);
return 0;
}

View File

@ -1,99 +0,0 @@
RDOFF: Relocatable Dynamically-linked Object File Format
========================================================
RDOFF was designed initially to test the object-file production
interface to NASM. It soon became apparent that it could be enhanced
for use in serious applications due to its simplicity; code to load
and execute an RDOFF object module is very simple. It also contains
enhancements to allow it to be linked with a dynamic link library at
either run- or load- time, depending on how complex you wish to make
your loader.
The RDOFF format (version 1.1, as produced by NASM v0.91) is defined
as follows:
The first six bytes of the file contain the string 'RDOFF1'. Other
versions of the format may contain other last characters other than
'1' - all little endian versions of the file will always contain an
ASCII character with value greater than 32. If RDOFF is used on a
big-endian machine at some point in the future, the version will be
encoded in decimal rather than ASCII, so will be below 32.
All multi-byte fields follwing this are encoded in either little- or
big-endian format depending on the system described by this version
information. Object files should be encoded in the endianness of
their target machine; files of incorrect endianness will be rejected
by the loader - this means that loaders do not need to convert
endianness, as RDOFF has been designed with simplicity of loading at
the forefront of the design requirements.
The next 4 byte field is the length of the header in bytes. The
header consists of a sequence of variable length records. Each
record's type is identified by the first byte of the record. Record
types 1-4 are currently supported. Record type 5 will be added in
the near future, when I implement BSS segments. Record type 6 may be
to do with debugging, when I get debugging implemented.
Type 1: Relocation
==================
Offset Length Description
0 1 Type (contains 1)
1 1 Segment that contains reference (0 = text, 1 = data)
Add 64 to this number to indicate a relative linkage
to an external symbol (see notes)
2 4 Offset of reference
6 1 Length of reference (1,2 or 4 bytes)
7 2 Segment to which reference is made (0 = text, 1 =
data, 2 = BSS [when implemented]) others are external
symbols.
Total length = 9 bytes
Type 2: Symbol Import
=====================
0 1 Type (2)
1 2 Segment number that will be used in references to this
symbol.
3 ? Null terminated string containing label (up to 32
chars) to match against exports in linkage.
Type 3: Symbol Export
=====================
0 1 Type (3)
1 1 Segment containing object to be exported (0/1/2)
2 4 Offset within segment
6 ? Null terminate string containing label to export (32
char maximum length)
Type 4: Dynamic Link Library
============================
0 1 Type (4)
1 ? Library name (up to 128 chars)
Type 5: Reserve BSS
===================
0 1 Type (5)
1 4 Amount of BSS space to reserve in bytes
Total length: 5 bytes
-----------------------------------------------------------------------------
Following the header is the text (code) segment. This is preceded by
a 4-byte integer, which is its length in bytes. This is followed by
the length of the data segment (also 4 bytes), and finally the data
segment.
Notes
=====
Relative linking: The number stored at the address is offset
required from the imported symbol, with the address of the end of
the instruction subtracted from it. This means that the linker can
simply add the address of the label relative to the beginning of the
current segment to it.

View File

@ -1,125 +0,0 @@
/* rdf2bin: convert an RDOFF object file to flat binary */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "rdfload.h"
#include "rdoff.h"
#include "nasmlib.h"
long origin = 0;
int align = 16;
char *getfilename(char * pathname)
{
char * lastslash = pathname - 1;
char * i = pathname;
while ( *i ) {
if (*i == '/') lastslash = i;
i++;
}
return lastslash + 1;
}
int main(int argc, char **argv)
{
rdfmodule * m;
int tmp;
FILE *of;
char * padding;
int codepad, datapad;
if (argc < 2) {
puts("Usage: rdf2bin [-o relocation-origin] [-p segment-alignment] "
"input-file output-file");
puts(" rdf2com [-p segment-alignment] input-file output-file");
return 1;
}
if (! nasm_stricmp(getfilename(*argv),"rdf2com")) {
origin = 0x100;
}
argv++, argc--;
while (argc > 2) {
if (! strcmp(*argv,"-o")) {
argv++, argc--;
origin = readnum(*argv, &tmp);
if (tmp) {
fprintf(stderr,"rdf2bin: invalid parameter: %s\n",*argv);
return 1;
}
} else if (! strcmp(*argv,"-p")) {
argv++, argc--;
align = readnum(*argv, &tmp);
if (tmp) {
fprintf(stderr,"rdf2bin: 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.code_len;
if (m->datarel % align != 0) {
codepad = align - (m->datarel % align);
m->datarel += codepad;
}
else
codepad = 0;
m->bssrel = m->datarel + m->f.data_len;
if (m->bssrel % align != 0) {
datapad = align - (m->bssrel % align);
m->bssrel += datapad;
}
else
datapad = 0;
printf("code: %08lx\ndata: %08lx\nbss: %08lx\n",
m->textrel, m->datarel, m->bssrel);
rdf_relocate(m);
argv++;
of = fopen(*argv,"wb");
if (!of) {
fprintf(stderr,"rdf2bin: could not open output file %s\n",*argv);
return 1;
}
padding = malloc(align);
if (!padding) {
fprintf(stderr,"rdf2bin: out of memory\n");
return 1;
}
if (fwrite(m->t,1,m->f.code_len,of) != m->f.code_len ||
fwrite(padding,1,codepad,of) != codepad ||
fwrite(m->d,1,m->f.data_len,of) != m->f.data_len)
{
fprintf(stderr,"rdf2bin: error writing to %s\n", *argv);
return 1;
}
fclose(of);
return 0;
}

View File

@ -1,167 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
FILE *infile;
long translatelong(long in) { /* translate from little endian to
local representation */
long r;
unsigned char *i;
i = (unsigned char *)&in;
r = i[3];
r = (r << 8) + i[2];
r = (r << 8) + i[1];
r = (r << 8) + *i;
return r;
}
int translateshort(short in) {
int r;
unsigned char *i;
i = (unsigned char *)&in;
r = (i[1] << 8) + *i;
return r;
}
void print_header(long length) {
char buf[129],t,s,l;
long o,ll;
short rs;
while (length > 0) {
fread(&t,1,1,infile);
switch(t) {
case 1: /* relocation record */
fread(&s,1,1,infile);
fread(&o,4,1,infile);
fread(&l,1,1,infile);
fread(&rs,2,1,infile);
printf(" relocation: location (%04x:%08lx), length %d, "
"referred seg %04x\n",(int)s,translatelong(o),(int)l,
translateshort(rs));
length -= 9;
break;
case 2: /* import record */
fread(&rs,2,1,infile);
ll = 0;
do {
fread(&buf[ll],1,1,infile);
} while (buf[ll++]);
printf(" import: segment %04x = %s\n",translateshort(rs),buf);
length -= ll + 3;
break;
case 3: /* export record */
fread(&s,1,1,infile);
fread(&o,4,1,infile);
ll = 0;
do {
fread(&buf[ll],1,1,infile);
} while (buf[ll++]);
printf(" export: (%04x:%08lx) = %s\n",(int)s,translatelong(o),buf);
length -= ll + 6;
break;
case 4: /* DLL record */
ll = 0;
do {
fread(&buf[ll],1,1,infile);
} while (buf[ll++]);
printf(" dll: %s\n",buf);
length -= ll + 1;
break;
case 5: /* BSS reservation */
fread(&ll,4,1,infile);
printf(" bss reservation: %08lx bytes\n",translatelong(ll));
length -= 5;
break;
default:
printf(" unrecognised record (type %d)\n",(int)t);
length --;
}
}
}
int main(int argc,char **argv) {
char id[7];
long l;
int verbose = 0;
long offset;
puts("RDOFF Dump utility v1.1 (C) Copyright 1996 Julian R Hall");
if (argc < 2) {
fputs("Usage: rdfdump [-v] <filename>\n",stderr);
exit(1);
}
if (! strcmp (argv[1], "-v") )
{
verbose = 1;
if (argc < 3)
{
fputs("required parameter missing\n",stderr);
exit(1);
}
argv++;
}
infile = fopen(argv[1],"rb");
if (! infile) {
fprintf(stderr,"rdfdump: Could not open %s",argv[1]);
exit(1);
}
fread(id,6,1,infile);
if (strncmp(id,"RDOFF",5)) {
fputs("rdfdump: File does not contain valid RDOFF header\n",stderr);
exit(1);
}
printf("File %s: RDOFF version %c\n\n",argv[1],id[5]);
if (id[5] < '1' || id[5] > '1') {
fprintf(stderr,"rdfdump: unknown RDOFF version '%c'\n",id[5]);
exit(1);
}
fread(&l,4,1,infile);
l = translatelong(l);
printf("Header (%ld bytes):\n",l);
print_header(l);
fread(&l,4,1,infile);
l = translatelong(l);
printf("\nText segment length = %ld bytes\n",l);
offset = 0;
while(l--) {
fread(id,1,1,infile);
if (verbose) {
if (offset % 16 == 0)
printf("\n%08lx ", offset);
printf(" %02x",(int) (unsigned char)id[0]);
offset++;
}
}
if (verbose) printf("\n\n");
fread(&l,4,1,infile);
l = translatelong(l);
printf("Data segment length = %ld bytes\n",l);
if (verbose)
{
offset = 0;
while (l--) {
fread(id,1,1,infile);
if (offset % 16 == 0)
printf("\n%08lx ", offset);
printf(" %02x",(int) (unsigned char) id[0]);
offset++;
}
printf("\n");
}
fclose(infile);
return 0;
}

View File

@ -1,235 +0,0 @@
/* rdflib - manipulate RDOFF library files (.rdl) */
/* an rdoff library is simply a sequence of RDOFF object files, each
preceded by the name of the module, an ASCII string of up to 255
characters, terminated by a zero. There may be an optional
directory placed on the end of the file. The format of the
directory will be 'RDL' followed by a version number, followed by
the length of the directory, and then the directory, the format of
which has not yet been designed. */
#include <stdio.h>
#include <errno.h>
#include <string.h>
/* functions supported:
create a library (no extra operands required)
add a module from a library (requires filename and name to give mod.)
remove a module from a library (requires given name)
extract a module from the library (requires given name and filename)
list modules */
const char *usage =
"usage:\n"
" rdflib x libname [extra operands]\n\n"
" where x is one of:\n"
" c - create library\n"
" a - add module (operands = filename module-name)\n"
" r - remove (module-name)\n"
" x - extract (module-name filename)\n"
" t - list\n";
char **_argv;
#define _ENDIANNESS 0 /* 0 for little, 1 for big */
static void longtolocal(long * l)
{
#if _ENDIANNESS
unsigned char t;
unsigned char * p = (unsigned char *) l;
t = p[0];
p[0] = p[3];
p[3] = t;
t = p[1];
p[1] = p[2];
p[2] = p[1];
#endif
}
void copybytes(FILE *fp, FILE *fp2, int n)
{
int i,t;
for (i = 0 ; i < n; i++ )
{
t = fgetc(fp);
if (t == EOF)
{
fprintf(stderr,"ldrdf: premature end of file in '%s'\n",
_argv[2]);
exit(1);
}
if (fp2)
if (fputc(t, fp2) == EOF)
{
fprintf(stderr,"ldrdf: write error\n");
exit(1);
}
}
}
long copylong(FILE *fp, FILE *fp2)
{
long l;
int i,t;
unsigned char * p = (unsigned char *) &l;
for (i = 0 ; i < 4; i++ ) /* skip magic no */
{
t = fgetc(fp);
if (t == EOF)
{
fprintf(stderr,"ldrdf: premature end of file in '%s'\n",
_argv[2]);
exit(1);
}
if (fp2)
if (fputc(t, fp2) == EOF)
{
fprintf(stderr,"ldrdf: write error\n");
exit(1);
}
*p++ = t;
}
longtolocal (&l);
return l;
}
int main(int argc, char **argv)
{
FILE *fp, *fp2;
char *p, buf[256];
int i;
_argv = argv;
if (argc < 3 || !strncmp(argv[1],"-h",2) || !strncmp(argv[1],"--h",3))
{
printf(usage);
exit(1);
}
switch(argv[1][0])
{
case 'c': /* create library */
fp = fopen(argv[2],"wb");
if (! fp) {
fprintf(stderr,"ldrdf: could not open '%s'\n",argv[2]);
perror("ldrdf");
exit(1);
}
fclose(fp);
break;
case 'a': /* add module */
if (argc < 5) {
fprintf(stderr,"ldrdf: required parameter missing\n");
exit(1);
}
fp = fopen(argv[2],"ab");
if (! fp)
{
fprintf(stderr,"ldrdf: could not open '%s'\n",argv[2]);
perror("ldrdf");
exit(1);
}
fp2 = fopen(argv[3],"rb");
if (! fp)
{
fprintf(stderr,"ldrdf: could not open '%s'\n",argv[3]);
perror("ldrdf");
exit(1);
}
p = argv[4];
do {
if ( fputc(*p,fp) == EOF ) {
fprintf(stderr,"ldrdf: write error\n");
exit(1);
}
} while (*p++);
while (! feof (fp2) ) {
i = fgetc (fp2);
if (i == EOF) {
break;
}
if ( fputc(i, fp) == EOF ) {
fprintf(stderr,"ldrdf: write error\n");
exit(1);
}
}
fclose(fp2);
fclose(fp);
break;
case 'x':
if (argc < 5) {
fprintf(stderr,"ldrdf: required parameter missing\n");
exit(1);
}
fp = fopen(argv[2],"rb");
if (! fp)
{
fprintf(stderr,"ldrdf: could not open '%s'\n",argv[2]);
perror("ldrdf");
exit(1);
}
fp2 = NULL;
while (! feof(fp) ) {
/* read name */
p = buf;
while( ( *(p++) = (char) fgetc(fp) ) )
if (feof(fp)) break;
if (feof(fp)) break;
/* check against desired name */
if (! strcmp(buf,argv[3]) )
{
fp2 = fopen(argv[4],"wb");
if (! fp2)
{
fprintf(stderr,"ldrdf: could not open '%s'\n", argv[4]);
perror("ldrdf");
exit(1);
}
}
else
fp2 = NULL;
/* step over the RDOFF file, copying it if fp2 != NULL */
copybytes(fp,fp2,6); /* magic number */
copybytes(fp,fp2, copylong(fp,fp2)); /* header */
copybytes(fp,fp2, copylong(fp,fp2)); /* text */
copybytes(fp,fp2, copylong(fp,fp2)); /* data */
if (fp2)
break;
}
fclose(fp);
if (fp2)
fclose(fp2);
else
{
fprintf(stderr,"ldrdf: module '%s' not found in '%s'\n",
argv[3],argv[2]);
exit(1);
}
break;
default:
fprintf(stderr,"ldrdf: command '%c' not recognised\n",
argv[1][0]);
exit(1);
}
return 0;
}

View File

@ -1,173 +0,0 @@
/* rdfload.c RDOFF Object File loader library
*
* 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.
*
* Permission to use this file in your own projects is granted, as long
* as acknowledgement is given in an appropriate manner to its authors,
* with instructions of how to obtain a copy via ftp.
*/
#include <stdlib.h>
#include <stdio.h>
#include "rdfload.h"
#include "symtab.h"
#include "rdoff.h"
#include "collectn.h"
extern int rdf_errno;
rdfmodule * rdfload(const char *filename)
{
rdfmodule * f = malloc(sizeof(rdfmodule));
long bsslength = 0;
char * hdr;
rdfheaderrec *r;
if (f == NULL)
{
rdf_errno = 6; /* out of memory */
return NULL;
}
f->symtab = symtabNew();
if (!f->symtab)
{
free(f);
rdf_errno = 6;
return NULL;
}
/* open the file */
if ( rdfopen( &(f->f), filename ) ) {
free(f);
return NULL;
}
/* read in text and data segments, and header */
f->t = malloc (f->f.code_len);
f->d = malloc (f->f.data_len); /* BSS seg allocated later */
hdr = malloc (f->f.header_len);
if (! f->t || ! f->d || !hdr) {
rdf_errno = 6;
rdfclose(&f->f);
if (f->t) free(f->t);
if (f->d) free(f->d);
free(f);
return NULL;
}
if ( rdfloadseg (&f->f,RDOFF_HEADER,hdr) ||
rdfloadseg (&f->f,RDOFF_CODE,f->t) ||
rdfloadseg (&f->f,RDOFF_DATA,f->d) )
{
rdfclose(&f->f);
free(f->t);
free(f->d);
free(f);
free(hdr);
return NULL;
}
rdfclose(&f->f);
/* Allocate BSS segment; step through header and count BSS records */
while ( ( r = rdfgetheaderrec (&f->f) ) )
{
if (r->type == 5)
bsslength += r->b.amount;
}
f->b = malloc ( bsslength );
if (! f->b )
{
free(f->t);
free(f->d);
free(f);
free(hdr);
rdf_errno = 6;
return NULL;
}
rdfheaderrewind (&f->f);
f->textrel = (long)f->t;
f->datarel = (long)f->d;
f->bssrel = (long)f->b;
return f;
}
int rdf_relocate(rdfmodule * m)
{
rdfheaderrec * r;
Collection imports;
symtabEnt e;
long rel;
unsigned char * seg;
rdfheaderrewind ( & m->f );
collection_init(&imports);
while ( (r = rdfgetheaderrec ( & m->f ) ) )
{
switch (r->type)
{
case 1: /* Relocation record */
/* calculate relocation factor */
if (r->r.refseg == 0) rel = m->textrel;
else if (r->r.refseg == 1) rel = m->datarel;
else if (r->r.refseg == 2) rel = m->bssrel;
else
/* We currently do not support load-time linkage.
This should be added some time soon... */
return 1; /* return error code */
if ((r->r.segment & 63) == 0) seg = m->t;
else if ((r->r.segment & 63) == 1) seg = m->d;
else
return 1;
/* it doesn't matter in this case that the code is non-portable,
as the entire concept of executing a module like this is
non-portable */
switch(r->r.length) {
case 1:
seg[r->r.offset] += (char) rel;
break;
case 2:
*(int16 *)(seg + r->r.offset) += (int16) rel;
break;
case 4:
*(long *)(seg + r->r.offset) += rel;
break;
}
break;
case 3: /* export record - add to symtab */
e.segment = r->e.segment;
e.offset = r->e.offset +
(e.segment == 0 ? m->textrel : /* 0 -> code */
e.segment == 1 ? m->datarel : /* 1 -> data */
m->bssrel) ; /* 2 -> bss */
e.flags = 0;
e.name = malloc(strlen(r->e.label) + 1);
if (! e.name)
return 1;
strcpy(e.name,r->e.label);
symtabInsert(m->symtab,&e);
break;
}
}
return 0;
}

View File

@ -1,29 +0,0 @@
/* rdfload.h RDOFF Object File loader library header file
*
* 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.
*
* See the file 'rdfload.c' for special license information for this
* file.
*/
#ifndef _RDFLOAD_H
#define _RDFLOAD_H
#include "rdoff.h"
typedef struct RDFModuleStruct {
rdffile f; /* file structure */
unsigned char * t, * d, * b; /* text, data, and bss segments */
long textrel;
long datarel;
long bssrel;
void * symtab;
} rdfmodule;
rdfmodule * rdfload(const char * filename);
int rdf_relocate(rdfmodule * m);
#endif

View File

@ -1,88 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include "rdoff.h"
#include "rdlib.h"
int rdl_error = 0;
char *rdl_errors[3] = {
"no error","could not open file", "invalid file structure",
};
int rdl_searchlib (struct librarynode * lib,
const char * label, rdffile * f)
{
char buf[257];
int i;
void * hdr;
rdfheaderrec * r;
rdl_error = 0;
lib->referenced ++;
if (! lib->fp)
{
lib->fp = fopen(lib->name,"rb");
if (! lib->fp) {
rdl_error = 1;
return 0;
}
}
else
rewind(lib->fp);
while (! feof(lib->fp) )
{
i = 1;
while (fread(buf + i,1,1,lib->fp) == 1 && buf[i] && i < 257)
i++;
buf[0] = ':';
if (feof(lib->fp)) break;
if ( rdfopenhere(f,lib->fp,&lib->referenced,buf) ) {
rdl_error = 2;
return 0;
}
hdr = malloc(f->header_len);
rdfloadseg(f,RDOFF_HEADER,hdr);
while ((r = rdfgetheaderrec(f)))
{
if (r->type != 3) /* not an export */
continue;
if (! strcmp(r->e.label, label) ) /* match! */
{
free(hdr); /* reset to 'just open' */
f->header_loc = NULL; /* state... */
f->header_fp = 0;
return 1;
}
}
/* find start of next module... */
i = f->data_ofs + f->data_len;
rdfclose(f);
fseek(lib->fp,i,SEEK_SET);
}
lib->referenced --;
if (! lib->referenced)
{
fclose(lib->fp);
lib->fp = NULL;
}
return 0;
}
void rdl_perror(const char *apname, const char *filename)
{
fprintf(stderr,"%s:%s:%s\n",apname,filename,rdl_errors[rdl_error]);
}

View File

@ -1,18 +0,0 @@
/* rdlib.h Functions for manipulating librarys of RDOFF object files */
struct librarynode {
char * name;
FILE * fp; /* initialised to NULL - always check*/
int referenced; /* & open if required. Close afterwards */
struct librarynode * next; /* if ! referenced. */
};
extern int rdl_error;
int rdl_searchlib (struct librarynode * lib,
const char * label, rdffile * f);
void rdl_perror(const char *apname, const char *filename);

View File

@ -1,397 +0,0 @@
/* rdoff.c library of routines for manipulating rdoff files
*
* 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.
*/
/* TODO: The functions in this module assume they are running
* on a little-endian machine. This should be fixed to
* make it portable.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "rdoff.h"
#define newstr(str) strcpy(malloc(strlen(str) + 1),str)
#define newstrcat(s1,s2) strcat(strcpy(malloc(strlen(s1) + strlen(s2) + 1), \
s1),s2)
/* ========================================================================
* Code for memory buffers (for delayed writing of header until we know
* how long it is).
* ======================================================================== */
memorybuffer * newmembuf(){
memorybuffer * t;
t = malloc(sizeof(memorybuffer));
t->length = 0;
t->next = NULL;
return t;
}
void membufwrite(memorybuffer *b, void *data, int bytes) {
int16 w;
long l;
if (b->next) { /* memory buffer full - use next buffer */
membufwrite(b->next,data,bytes);
return;
}
if ((bytes < 0 && b->length - bytes > BUF_BLOCK_LEN)
|| (bytes > 0 && b->length + bytes > BUF_BLOCK_LEN)) {
/* buffer full and no next allocated... allocate and initialise next
* buffer */
b->next = newmembuf();
membufwrite(b->next,data,bytes);
}
switch(bytes) {
case -4: /* convert to little-endian */
l = * (long *) data ;
b->buffer[b->length++] = l & 0xFF;
l >>= 8 ;
b->buffer[b->length++] = l & 0xFF;
l >>= 8 ;
b->buffer[b->length++] = l & 0xFF;
l >>= 8 ;
b->buffer[b->length++] = l & 0xFF;
break;
case -2:
w = * (int16 *) data ;
b->buffer[b->length++] = w & 0xFF;
w >>= 8 ;
b->buffer[b->length++] = w & 0xFF;
break;
default:
while(bytes--) {
b->buffer[b->length++] = *(* (unsigned char **) &data);
(* (unsigned char **) &data)++ ;
}
break;
}
}
void membufdump(memorybuffer *b,FILE *fp)
{
if (!b) return;
fwrite (b->buffer, 1, b->length, fp);
membufdump(b->next,fp);
}
int membuflength(memorybuffer *b)
{
if (!b) return 0;
return b->length + membuflength(b->next);
}
void freemembuf(memorybuffer *b)
{
if (!b) return;
freemembuf(b->next);
free(b);
}
/* =========================================================================
General purpose routines and variables used by the library functions
========================================================================= */
long translatelong(long in) { /* translate from little endian to
local representation */
long r;
unsigned char *i;
i = (unsigned char *)&in;
r = i[3];
r = (r << 8) + i[2];
r = (r << 8) + i[1];
r = (r << 8) + *i;
return r;
}
const char *RDOFFId = "RDOFF1"; /* written to the start of RDOFF files */
const char *rdf_errors[7] = {
"no error occurred","could not open file","invalid file format",
"error reading file","unknown error","header not read",
"out of memory"};
int rdf_errno = 0;
/* ========================================================================
The library functions
======================================================================== */
int rdfopen(rdffile *f, const char *name)
{
FILE * fp;
fp = fopen(name,"rb");
if (!fp) return rdf_errno = 1; /* error 1: file open error */
return rdfopenhere(f,fp,NULL,"");
}
int rdfopenhere(rdffile *f, FILE *fp, int *refcount, char *name)
{
char buf[8];
long initpos;
if (translatelong(0x01020304) != 0x01020304)
{ /* fix this to be portable! */
fputs("*** this program requires a little endian machine\n",stderr);
fprintf(stderr,"01020304h = %08lxh\n",translatelong(0x01020304));
exit(3);
}
f->fp = fp;
initpos = ftell(fp);
fread(buf,6,1,f->fp); /* read header */
buf[6] = 0;
if (strcmp(buf,RDOFFId)) {
fclose(f->fp);
return rdf_errno = 2; /* error 2: invalid file format */
}
if (fread(&f->header_len,1,4,f->fp) != 4) {
fclose(f->fp);
return rdf_errno = 3; /* error 3: file read error */
}
f->header_ofs = ftell(f->fp);
if (fseek(f->fp,f->header_len,SEEK_CUR)) {
fclose(f->fp);
return rdf_errno = 2; /* seek past end of file...? */
}
if (fread(&f->code_len,1,4,f->fp) != 4) {
fclose(f->fp);
return rdf_errno = 3;
}
f->code_ofs = ftell(f->fp);
if (fseek(f->fp,f->code_len,SEEK_CUR)) {
fclose(f->fp);
return rdf_errno = 2;
}
if (fread(&f->data_len,1,4,f->fp) != 4) {
fclose(f->fp);
return rdf_errno = 3;
}
f->data_ofs = ftell(f->fp);
fseek(f->fp,initpos,SEEK_SET);
f->header_loc = NULL;
f->name = newstr(name);
f->refcount = refcount;
if (refcount) (*refcount)++;
return 0;
}
int rdfclose(rdffile *f)
{
if (! f->refcount || ! *--f->refcount)
fclose(f->fp);
free(f->name);
return 0;
}
void rdfperror(const char *app,const char *name)
{
fprintf(stderr,"%s:%s: %s\n",app,name,rdf_errors[rdf_errno]);
if (rdf_errno == 1 || rdf_errno == 3)
{
perror(app);
}
}
int rdfloadseg(rdffile *f,int segment,void *buffer)
{
long fpos;
long slen;
switch(segment) {
case RDOFF_HEADER:
fpos = f->header_ofs;
slen = f->header_len;
f->header_loc = (char *)buffer;
f->header_fp = 0;
break;
case RDOFF_CODE:
fpos = f->code_ofs;
slen = f->code_len;
break;
case RDOFF_DATA:
fpos = f->data_ofs;
slen = f->data_len;
break;
default:
fpos = 0;
slen = 0;
}
if (fseek(f->fp,fpos,SEEK_SET))
return rdf_errno = 4;
if (fread(buffer,1,slen,f->fp) != slen)
return rdf_errno = 3;
return 0;
}
/* Macros for reading integers from header in memory */
#define RI8(v) v = f->header_loc[f->header_fp++]
#define RI16(v) { v = (f->header_loc[f->header_fp] + \
(f->header_loc[f->header_fp+1] << 8)); \
f->header_fp += 2; }
#define RI32(v) { v = (f->header_loc[f->header_fp] + \
(f->header_loc[f->header_fp+1] << 8) + \
(f->header_loc[f->header_fp+2] << 16) + \
(f->header_loc[f->header_fp+3] << 24)); \
f->header_fp += 4; }
#define RS(str,max) { for(i=0;i<max;i++){\
RI8(str[i]); if (!str[i]) break;} str[i]=0; }
rdfheaderrec *rdfgetheaderrec(rdffile *f)
{
static rdfheaderrec r;
int i;
if (!f->header_loc) {
rdf_errno = 5;
return NULL;
}
if (f->header_fp >= f->header_len) return 0;
RI8(r.type);
switch(r.type) {
case 1: /* Relocation record */
RI8(r.r.segment);
RI32(r.r.offset);
RI8(r.r.length);
RI16(r.r.refseg);
break;
case 2: /* Imported symbol record */
RI16(r.i.segment);
RS(r.i.label,32);
break;
case 3: /* Exported symbol record */
RI8(r.e.segment);
RI32(r.e.offset);
RS(r.e.label,32);
break;
case 4: /* DLL record */
RS(r.d.libname,127);
break;
case 5: /* BSS reservation record */
RI32(r.b.amount);
break;
default:
rdf_errno = 2; /* invalid file */
return NULL;
}
return &r;
}
void rdfheaderrewind(rdffile *f)
{
f->header_fp = 0;
}
rdf_headerbuf * rdfnewheader(void)
{
return newmembuf();
}
int rdfaddheader(rdf_headerbuf * h, rdfheaderrec * r)
{
switch (r->type)
{
case 1:
membufwrite(h,&r->type,1);
membufwrite(h,&r->r.segment,1);
membufwrite(h,&r->r.offset,-4);
membufwrite(h,&r->r.length,1);
membufwrite(h,&r->r.refseg,-2); /* 9 bytes written */
break;
case 2: /* import */
membufwrite(h,&r->type,1);
membufwrite(h,&r->i.segment,-2);
membufwrite(h,&r->i.label,strlen(r->i.label) + 1);
break ;
case 3: /* export */
membufwrite(h,&r->type,1);
membufwrite(h,&r->e.segment,1);
membufwrite(h,&r->e.offset,-4);
membufwrite(h,&r->e.label,strlen(r->e.label) + 1);
break ;
case 4: /* DLL */
membufwrite(h,&r->type,1);
membufwrite(h,&r->d.libname,strlen(r->d.libname) + 1);
break ;
case 5: /* BSS */
membufwrite(h,&r->type,1);
membufwrite(h,&r->b.amount,-4);
break ;
default:
return (rdf_errno = 2);
}
return 0;
}
int rdfwriteheader(FILE * fp, rdf_headerbuf * h)
{
long l;
fwrite (RDOFFId, 1, strlen(RDOFFId), fp) ;
l = translatelong ( membuflength (h) );
fwrite (&l, 4, 1, fp);
membufdump(h, fp);
return 0; /* no error handling in here... CHANGE THIS! */
}
void rdfdoneheader(rdf_headerbuf * h)
{
freemembuf(h);
}

View File

@ -1,118 +0,0 @@
/* rdoff.h RDOFF Object File manipulation routines header file
*
* 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.
*/
#ifndef _RDOFF_H
#define _RDOFF_H "RDOFF1 support routines v0.1"
typedef short int16; /* not sure if this will be required to be altered
at all... best to typedef it just in case */
/* the records that can be found in the RDOFF header */
struct RelocRec {
char type; /* must be 1 */
char segment; /* only 0 for code, or 1 for data supported,
but add 64 for relative refs (ie do not require
reloc @ loadtime, only linkage) */
long offset; /* from start of segment in which reference is loc'd */
char length; /* 1 2 or 4 bytes */
int16 refseg; /* segment to which reference refers to */
};
struct ImportRec {
char type; /* must be 2 */
int16 segment; /* segment number allocated to the label for reloc
records - label is assumed to be at offset zero
in this segment, so linker must fix up with offset
of segment and of offset within segment */
char label[33]; /* zero terminated... should be written to file until
the zero, but not after it - max len = 32 chars */
};
struct ExportRec {
char type; /* must be 3 */
char segment; /* segment referred to (0/1) */
long offset; /* offset within segment */
char label[33]; /* zero terminated as above. max len = 32 chars */
};
struct DLLRec {
char type; /* must be 4 */
char libname[128]; /* name of library to link with at load time */
};
struct BSSRec {
char type; /* must be 5 */
long amount; /* number of bytes BSS to reserve */
};
typedef union RDFHeaderRec {
char type; /* invariant throughout all below */
struct RelocRec r; /* type == 1 */
struct ImportRec i; /* type == 2 */
struct ExportRec e; /* type == 3 */
struct DLLRec d; /* type == 4 */
struct BSSRec b; /* type == 5 */
} rdfheaderrec;
typedef struct RDFFileInfo {
FILE *fp; /* file descriptor; must be open to use this struct */
int rdoff_ver; /* should be 1; any higher => not guaranteed to work */
long header_len;
long code_len;
long data_len;
long header_ofs;
long code_ofs;
long data_ofs;
char *header_loc; /* keep location of header */
long header_fp; /* current location within header for reading */
char *name; /* name of module in libraries */
int *refcount; /* pointer to reference count on file, or NULL */
} rdffile;
#define BUF_BLOCK_LEN 4088 /* selected to match page size (4096)
* on 80x86 machines for efficiency */
typedef struct memorybuffer {
int length;
char buffer[BUF_BLOCK_LEN];
struct memorybuffer *next;
} memorybuffer;
typedef memorybuffer rdf_headerbuf;
/* segments used by RDOFF, understood by rdoffloadseg */
#define RDOFF_CODE 0
#define RDOFF_DATA 1
#define RDOFF_HEADER -1
/* mask for 'segment' in relocation records to find if relative relocation */
#define RDOFF_RELATIVEMASK 64
/* mask to find actual segment value in relocation records */
#define RDOFF_SEGMENTMASK 63
extern int rdf_errno;
/* RDOFF file manipulation functions */
int rdfopen(rdffile *f,const char *name);
int rdfopenhere(rdffile *f, FILE *fp, int *refcount, char *name);
int rdfclose(rdffile *f);
int rdfloadseg(rdffile *f,int segment,void *buffer);
rdfheaderrec *rdfgetheaderrec(rdffile *f); /* returns static storage */
void rdfheaderrewind(rdffile *f); /* back to start of header */
void rdfperror(const char *app,const char *name);
/* functions to write a new RDOFF header to a file -
use rdfnewheader to allocate a header, rdfaddheader to add records to it,
rdfwriteheader to write 'RDOFF1', length of header, and the header itself
to a file, and then rdfdoneheader to dispose of the header */
rdf_headerbuf *rdfnewheader(void);
int rdfaddheader(rdf_headerbuf *h,rdfheaderrec *r);
int rdfwriteheader(FILE *fp,rdf_headerbuf *h);
void rdfdoneheader(rdf_headerbuf *h);
#endif /* _RDOFF_H */

View File

@ -1,114 +0,0 @@
The RDOFF version 1.1 Object File Format
========================================
I seem to keep writing this document... I don't know what keeps
happening to it. Anyway, this one will hopefully stay around for a
while.
RDOFF is a relocatable object file format whose design goals were
mainly to keep it simple, so that an RDOFF object can be loaded and
executed by a very small piece of code (primarily so that it can be
used by the microkernel of an operating system to store system
modules, which can then go on to load and execute more complex object
files, eg ELF, if so desired), yet still be able to be cope with
everything required by the operating system; linkage of multiple
modules together (possibly with automatic loading of new libraries
that are referred to by the object) at load time, allowing static or
dynamic linking as required by the application.
The overall format of the file is summarised in this table:
Length (bytes) Description
6 Contains the string 'RDOFF1' (little-endian targets),
or 'RDOFF' followed by the single byte 0x01
(big-endian targets).
4 Length of the header section
? Header section (see above for length)
4 Length of code section (.text)
? Code section
4 Length of data section (.data)
? Data section
Segments are referred to as numbers. Imported labels are implicitly
at offset zero from a segment; each is assigned a segment number when
it is imported. Segments in the object file itself are numbered:
0 - text segemnt
1 - data segment
2 - bss segment
The header consists of a sequence of records, each of which is
preceded by a byte to represent its type.
These records are one of the following types:
1: Relocation Record
--------------------
This record points to an address that will need either
relocation or linkage to an external segment when the object
is loaded or linked.
Length Description
1 Type identifier (must be 1)
1 Segment number (0 or 1) plus 64 if the reference is
relative (and thus does not require relocation with
the base of the code, only by the difference between
the start of this segment, and the segment referred to
(see below)
4 Offset from start of segment of item requiring reloc.
1 Length of item (1, 2, or 4 bytes...)
2 Segment number to which reference is made.
2: Import Symbol Record
-----------------------
This record defines a segment to start at the location of a
named symbol; this symbol may need to be fetched from an
external library.
Length Description
1 Type identifier (must be 2)
2 Segment number to allocate
? String containing label (null terminated, max length =
32 chars)
3: Export Symbol Record
-----------------------
This record defines a symbol, to which external modules can
link using the above record type.
Length Description
1 Type identifier (must be 3)
1 Segment containing symbol (0,1 or 2)
4 Offset of symbol within segment
? String containing label (null terminated, max length =
32 chars)
4: Import Library Record
------------------------
This record tells the loader that an extra library should be
loaded and linked to the module at either load- or run-time
(load time is easier, run-time is good, though...)
Length Description
1 Type identifier (must be 4)
? Name of library (null terminated string, max len = 128)
5: Reserve BSS Bytes
--------------------
This record tells the loader how much memory to reserve after
the executable code loaded from the object file for the BSS
segment (referred to as segment number 2).
A loader can safely assume that there will only be one of
these records per module, but the linker probably cannot...
NASM will only output one, but other utilities may be written
that do, and future versions of NASM may output more than one.
Length Description
1 Type identifier (must be 5)
4 Number of bytes to reserve

View File

@ -1,61 +0,0 @@
/* rdx.c RDOFF Object File loader program
*
* 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.
*/
/* note: most of the actual work of this program is done by the modules
"rdfload.c", which loads and relocates the object file, and by "rdoff.c",
which contains general purpose routines to manipulate RDOFF object
files. You can use these files in your own program to load RDOFF objects
and execute the code in them in a similar way to what is shown here. */
#include <stdio.h>
#include <stdlib.h>
#include "rdfload.h"
#include "rdoff.h"
#include "symtab.h"
typedef int (*main_fn) (int,char**); /* Main function prototype */
int main(int argc, char **argv)
{
rdfmodule * m;
main_fn code;
symtabEnt * s;
if (argc < 2)
{
puts("usage: rdf <rdoff-executable> [params]\n");
exit(255);
}
m = rdfload(argv[1]);
if (! m)
{
rdfperror("rdf",argv[1]);
exit(255);
}
rdf_relocate(m); /* in this instance, the default relocation
values will work fine, but they may need changing
in other cases... */
s = symtabFind(m->symtab, "_main");
if (! s)
{
fprintf(stderr,"rdx: could not find symbol '_main' in '%s'\n",argv[1]);
exit(255);
}
code = (main_fn) s->offset;
argv++, argc--; /* remove 'rdx' from command line */
return code(argc,argv); /* execute */
}

View File

@ -1,80 +0,0 @@
/* symtab.c Routines to maintain and manipulate a symbol table
*
* 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include "symtab.h"
/* TODO: Implement a hash table, not this stupid implementation which
is too slow to be of practical use */
/* Private data types */
typedef struct tagSymtab {
symtabEnt ent;
struct tagSymtab * next;
} symtabList;
typedef symtabList * _symtab;
void *symtabNew(void)
{
void *p = malloc(sizeof(_symtab));
if (p == NULL) {
fprintf(stderr,"symtab: out of memory\n");
exit(3);
}
*(_symtab *)p = NULL;
return p;
}
void symtabDone(void *symtab)
{
/* DO SOMETHING HERE! */
}
void symtabInsert(void *symtab,symtabEnt *ent)
{
symtabList *l = malloc(sizeof(symtabList));
if (l == NULL) {
fprintf(stderr,"symtab: out of memory\n");
exit(3);
}
l->ent = *ent;
l->next = *(_symtab *)symtab;
*(_symtab *)symtab = l;
}
symtabEnt *symtabFind(void *symtab,char *name)
{
symtabList *l = *(_symtab *)symtab;
while (l) {
if (!strcmp(l->ent.name,name)) {
return &(l->ent);
}
l = l->next;
}
return NULL;
}
void symtabDump(void *symtab,FILE *of)
{
symtabList *l = *(_symtab *)symtab;
while(l) {
fprintf(of,"%32s %s:%08lx (%ld)\n",l->ent.name,
l->ent.segment ? "data" : "code" ,
l->ent.offset, l->ent.flags);
l = l->next;
}
}

View File

@ -1,22 +0,0 @@
/* symtab.h Header file for symbol table manipulation routines
*
* 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.
*/
typedef struct {
char *name;
long segment;
long offset;
long flags;
} symtabEnt;
void *symtabNew(void);
void symtabDone(void *symtab);
void symtabInsert(void *symtab,symtabEnt *ent);
symtabEnt *symtabFind(void *symtab,char *name);
void symtabDump(void *symtab,FILE *of);

View File

@ -1,213 +0,0 @@
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