mirror of
https://github.com/netwide-assembler/nasm.git
synced 2025-04-12 18:40:23 +08:00
NASM 0.98.26
This commit is contained in:
parent
9a633fa3b9
commit
005b39c856
6
AUTHORS
6
AUTHORS
@ -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
6
ChangeLog
Normal 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
752
Doxyfile
@ -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
4
Mkfiles/README
Normal 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
27
README
Normal 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.
|
100
README.1st
100
README.1st
@ -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>
|
49
README03.txt
49
README03.txt
@ -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)
|
@ -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
8
TODO
Normal 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
82
c16.mac
@ -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
52
c32.mac
@ -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
|
||||
|
383
changed.asm
383
changed.asm
@ -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
542
doc/Changes
Normal 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
49
doc/Readme
Normal 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
276
doc/Wishlist
Normal 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.
|
||||
|
114
exebin.mac
114
exebin.mac
@ -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
|
||||
|
291
internal.doc
291
internal.doc
@ -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
52
lcc/README
Normal 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
2
misc/README
Normal file
@ -0,0 +1,2 @@
|
||||
There are various helpful bits and pieces for NASM,
|
||||
including but not limited to Simon photograph =)
|
2
nasm.h
2
nasm.h
@ -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
|
||||
|
199
ndisasm.doc
199
ndisasm.doc
@ -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
|
441
proc32.ash
441
proc32.ash
@ -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__
|
@ -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
75
rdoff/Mkfiles/Makefile.dj
Normal file
@ -0,0 +1,75 @@
|
||||
# Generated automatically from Makefile.in by configure.
|
||||
#
|
||||
# Auto-configuring Makefile for RDOFF object file utils; part of the
|
||||
# Netwide Assembler
|
||||
#
|
||||
# The Netwide Assembler is copyright (C) 1996 Simon Tatham and
|
||||
# Julian Hall. All rights reserved. The software is
|
||||
# redistributable under the licence given in the file "Licence"
|
||||
# distributed in the NASM archive.
|
||||
|
||||
# You may need to adjust these values.
|
||||
|
||||
prefix = /djgpp
|
||||
CC = gcc -s
|
||||
CFLAGS = -O2 -I..
|
||||
|
||||
# You _shouldn't_ need to adjust anything below this line.
|
||||
|
||||
exec_prefix = ${prefix}
|
||||
bindir = ${exec_prefix}/bin
|
||||
mandir = ${prefix}/man
|
||||
|
||||
INSTALL = /usr/bin/install -c
|
||||
INSTALL_PROGRAM = ${INSTALL}
|
||||
INSTALL_DATA = ${INSTALL} -m 644
|
||||
LN_S = ln -s
|
||||
|
||||
LDRDFLIBS = rdoff.o ../nasmlib.o symtab.o hash.o collectn.o rdlib.o segtab.o
|
||||
RDXLIBS = rdoff.o rdfload.o symtab.o hash.o collectn.o
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $*.c
|
||||
|
||||
all: rdfdump ldrdf rdx rdflib rdf2bin rdf2com
|
||||
|
||||
rdfdump: rdfdump.o
|
||||
$(CC) -o rdfdump rdfdump.o
|
||||
|
||||
ldrdf: ldrdf.o $(LDRDFLIBS)
|
||||
$(CC) -o ldrdf ldrdf.o $(LDRDFLIBS)
|
||||
rdx: rdx.o $(RDXLIBS)
|
||||
$(CC) -o rdx rdx.o $(RDXLIBS)
|
||||
rdflib: rdflib.o
|
||||
$(CC) -o rdflib rdflib.o
|
||||
rdf2bin: rdf2bin.o $(RDXLIBS) nasmlib.o
|
||||
$(CC) -o rdf2bin rdf2bin.o $(RDXLIBS) nasmlib.o
|
||||
rdf2com:
|
||||
$(LN_S) rdf2bin rdf2com
|
||||
|
||||
rdf2bin.o: rdf2bin.c
|
||||
rdfdump.o: rdfdump.c
|
||||
rdoff.o: rdoff.c rdoff.h
|
||||
ldrdf.o: ldrdf.c rdoff.h ../nasmlib.h symtab.h collectn.h rdlib.h
|
||||
symtab.o: symtab.c symtab.h hash.h
|
||||
collectn.o: collectn.c collectn.h
|
||||
rdx.o: rdx.c rdoff.h rdfload.h symtab.h
|
||||
rdfload.o: rdfload.c rdfload.h rdoff.h collectn.h symtab.h
|
||||
rdlib.o: rdlib.c rdlib.h
|
||||
rdflib.o: rdflib.c
|
||||
hash.o: hash.c hash.h
|
||||
segtab.o: segtab.c segtab.h
|
||||
|
||||
nasmlib.o: ../nasmlib.c ../nasmlib.h ../names.c ../nasm.h
|
||||
$(CC) -c $(CFLAGS) ../nasmlib.c
|
||||
|
||||
clean:
|
||||
rm -f *.o rdfdump ldrdf rdx rdflib rdf2bin rdf2com
|
||||
|
||||
install: rdfdump ldrdf rdx rdflib rdf2bin rdf2com
|
||||
$(INSTALL_PROGRAM) rdfdump $(bindir)/rdfdump
|
||||
$(INSTALL_PROGRAM) ldrdf $(bindir)/ldrdf
|
||||
$(INSTALL_PROGRAM) rdx $(bindir)/rdx
|
||||
$(INSTALL_PROGRAM) rdflib $(bindir)/rdflib
|
||||
$(INSTALL_PROGRAM) rdf2bin $(bindir)/rdf2bin
|
||||
cd $(bindir); $(LN_S) rdf2bin rdf2com
|
76
rdoff/Mkfiles/Makefile.emx
Normal file
76
rdoff/Mkfiles/Makefile.emx
Normal file
@ -0,0 +1,76 @@
|
||||
# Generated automatically from Makefile.in by configure.
|
||||
# $Id$
|
||||
#
|
||||
# Auto-configuring Makefile for RDOFF object file utils; part of the
|
||||
# Netwide Assembler
|
||||
#
|
||||
# The Netwide Assembler is copyright (C) 1996 Simon Tatham and
|
||||
# Julian Hall. All rights reserved. The software is
|
||||
# redistributable under the licence given in the file "Licence"
|
||||
# distributed in the NASM archive.
|
||||
|
||||
top_srcdir = ..
|
||||
srcdir = .
|
||||
prefix = /usr/local
|
||||
exec_prefix = ${prefix}
|
||||
bindir = ${exec_prefix}/bin
|
||||
mandir = ${prefix}/man
|
||||
|
||||
CC = gcc
|
||||
CFLAGS = -s -Zomf -O2 -fomit-frame-pointer -Wall -ansi -pedantic -I$(srcdir) -I$(top_srcdir)
|
||||
LDFLAGS = -s -Zomf -Zexe -Zcrtdll
|
||||
LIBS = -lgcc
|
||||
|
||||
INSTALL = .././install-sh -c
|
||||
INSTALL_PROGRAM = ${INSTALL}
|
||||
INSTALL_DATA = ${INSTALL} -m 644
|
||||
|
||||
LDRDFLIBS = rdoff.o nasmlib.o symtab.o collectn.o rdlib.o segtab.o hash.o
|
||||
RDXLIBS = rdoff.o rdfload.o symtab.o collectn.o hash.o
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) -o $@ $<
|
||||
|
||||
all: rdfdump ldrdf rdx rdflib rdf2bin
|
||||
|
||||
rdfdump: rdfdump.o
|
||||
$(CC) $(LDFLAGS) -o rdfdump rdfdump.o $(LIBS)
|
||||
ldrdf: ldrdf.o $(LDRDFLIBS)
|
||||
$(CC) $(LDFLAGS) -o ldrdf ldrdf.o $(LDRDFLIBS) $(LIBS)
|
||||
rdx: rdx.o $(RDXLIBS)
|
||||
$(CC) $(LDFLAGS) -o rdx rdx.o $(RDXLIBS) $(LIBS)
|
||||
rdflib: rdflib.o
|
||||
$(CC) $(LDFLAGS) -o rdflib rdflib.o $(LIBS)
|
||||
rdf2bin: rdf2bin.o $(RDXLIBS) nasmlib.o
|
||||
$(CC) $(LDFLAGS) -o rdf2bin rdf2bin.o $(RDXLIBS) nasmlib.o $(LIBS)
|
||||
|
||||
rdf2bin.o: rdf2bin.c
|
||||
rdfdump.o: rdfdump.c
|
||||
rdoff.o: rdoff.c rdoff.h
|
||||
ldrdf.o: ldrdf.c rdoff.h $(top_srcdir)/nasmlib.h symtab.h collectn.h rdlib.h
|
||||
symtab.o: symtab.c symtab.h
|
||||
collectn.o: collectn.c collectn.h
|
||||
rdx.o: rdx.c rdoff.h rdfload.h symtab.h
|
||||
rdfload.o: rdfload.c rdfload.h rdoff.h collectn.h symtab.h
|
||||
rdlib.o: rdlib.c rdlib.h
|
||||
rdflib.o: rdflib.c
|
||||
segtab.o: segtab.c
|
||||
|
||||
nasmlib.o: $(top_srcdir)/nasmlib.c
|
||||
$(CC) -c $(CFLAGS) -o $@ $(top_srcdir)/nasmlib.c
|
||||
|
||||
clean:
|
||||
rm -f *.o rdfdump ldrdf rdx rdflib rdf2bin rdf2com
|
||||
|
||||
spotless: clean
|
||||
rm -f Makefile
|
||||
|
||||
distclean: spotless
|
||||
|
||||
install: rdfdump ldrdf rdx rdflib rdf2bin rdf2com
|
||||
$(INSTALL_PROGRAM) rdfdump $(INSTALLROOT)$(bindir)/rdfdump
|
||||
$(INSTALL_PROGRAM) ldrdf $(INSTALLROOT)$(bindir)/ldrdf
|
||||
$(INSTALL_PROGRAM) rdx $(INSTALLROOT)$(bindir)/rdx
|
||||
$(INSTALL_PROGRAM) rdflib $(INSTALLROOT)$(bindir)/rdflib
|
||||
$(INSTALL_PROGRAM) rdf2bin $(INSTALLROOT)$(bindir)/rdf2bin
|
||||
cd $(INSTALLROOT)$(bindir) && rm -f rdf2com && $(LN_S) rdf2bin rdf2com
|
56
rdoff/Mkfiles/Makefile.sc
Normal file
56
rdoff/Mkfiles/Makefile.sc
Normal 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)
|
||||
|
||||
|
75
rdoff/Mkfiles/Makefile.unx
Normal file
75
rdoff/Mkfiles/Makefile.unx
Normal file
@ -0,0 +1,75 @@
|
||||
# Generated automatically from Makefile.in by configure.
|
||||
#
|
||||
# Auto-configuring Makefile for RDOFF object file utils; part of the
|
||||
# Netwide Assembler
|
||||
#
|
||||
# The Netwide Assembler is copyright (C) 1996 Simon Tatham and
|
||||
# Julian Hall. All rights reserved. The software is
|
||||
# redistributable under the licence given in the file "Licence"
|
||||
# distributed in the NASM archive.
|
||||
|
||||
# You may need to adjust these values.
|
||||
|
||||
prefix = /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
4
rdoff/Mkfiles/README
Normal 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.
|
728
rdoff/ldrdf1.c
728
rdoff/ldrdf1.c
@ -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;
|
||||
}
|
@ -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
|
||||
|
@ -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.
|
@ -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;
|
||||
}
|
@ -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
|
||||
|
728
rdoff/v1/ldrdf.c
728
rdoff/v1/ldrdf.c
@ -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;
|
||||
}
|
@ -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.
|
@ -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;
|
||||
}
|
@ -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 *)∈
|
||||
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 *)∈
|
||||
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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
@ -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
|
@ -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]);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
397
rdoff/v1/rdoff.c
397
rdoff/v1/rdoff.c
@ -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 *)∈
|
||||
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);
|
||||
}
|
118
rdoff/v1/rdoff.h
118
rdoff/v1/rdoff.h
@ -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 */
|
@ -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
|
||||
|
||||
|
@ -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 */
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
213
scitech.txt
213
scitech.txt
@ -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
|
Loading…
x
Reference in New Issue
Block a user