mirror of
https://github.com/netwide-assembler/nasm.git
synced 2025-08-23 10:33:50 -04: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
|
E: fbkotler@nettaxi.com
|
||||||
D: Bug smashing.
|
D: Bug smashing.
|
||||||
D: Documentation - "KATMAI" and "3DNow!" instructions supported by 0.98
|
D: Documentation - "KATMAI" and "3DNow!" instructions supported by 0.98
|
||||||
|
D: General coordination and moral support.
|
||||||
|
|
||||||
N: Stephen Silver
|
N: Stephen Silver
|
||||||
E: nasm@argentum.freeserve.co.uk
|
E: nasm@argentum.freeserve.co.uk
|
||||||
@ -88,3 +89,8 @@ N: Edward J. Beroset
|
|||||||
E: beroset@mindspring.com
|
E: beroset@mindspring.com
|
||||||
D: added %substr and %strlen
|
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_MAJOR_VER 0
|
||||||
#define NASM_MINOR_VER 98
|
#define NASM_MINOR_VER 98
|
||||||
#define NASM_VER "0.98.25alt"
|
#define NASM_VER "0.98.26"
|
||||||
|
|
||||||
#ifndef NULL
|
#ifndef NULL
|
||||||
#define NULL 0
|
#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