1 Internals of the Netwide Assembler
2 ==================================
4 The Netwide Assembler is intended to be a modular, re-usable x86
5 assembler, which can be embedded in other programs, for example as
6 the back end to a compiler.
8 The assembler is composed of modules. The interfaces between them
18 nasm.c ---+ | +--- nasmlib.c
27 In other words, each of `preproc.c', `parser.c', `assemble.c',
28 `labels.c', `outform.c' and each of the output format modules
29 `*out.c' are independent modules, which do not inter-communicate
30 except through the main program.
32 The Netwide *Disassembler* is not intended to be particularly
33 portable or reusable or anything, however. So I won't bother
34 documenting it here. :-)
39 This is a library module; it contains simple library routines which
40 may be referenced by all other modules. Among these are a set of
41 wrappers around the standard `malloc' routines, which will report a
42 fatal error if they run out of memory, rather than returning NULL.
47 This contains a macro preprocessor, which takes a file name as input
48 and returns a sequence of preprocessed source lines. The only symbol
49 exported from the module is `nasmpp', which is a data structure of
50 type `Preproc', declared in nasm.h. This structure contains pointers
51 to all the functions designed to be callable from outside the
57 This contains a source-line parser. It parses `canonical' assembly
58 source lines, containing some combination of the `label', `opcode',
59 `operand' and `comment' fields: it does not process directives or
60 macros. It exports two functions: `parse_line' and `cleanup_insn'.
62 `parse_line' is the main parser function: you pass it a source line
63 in ASCII text form, and it returns you an `insn' structure
64 containing all the details of the instruction on that line. The
65 parameters it requires are:
67 - The location (segment, offset) where the instruction on this line
68 will eventually be placed. This is necessary in order to evaluate
69 expressions containing the Here token, `$'.
71 - A function which can be called to retrieve the value of any
72 symbols the source line references.
74 - Which pass the assembler is on: an undefined symbol only causes an
75 error condition on pass two.
77 - The source line to be parsed.
79 - A structure to fill with the results of the parse.
81 - A function which can be called to report errors.
83 Some instructions (DB, DW, DD for example) can require an arbitrary
84 amount of storage, and so some of the members of the resulting
85 `insn' structure will be dynamically allocated. The other function
86 exported by `parser.c' is `cleanup_insn', which can be called to
87 deallocate any dynamic storage associated with the results of a
93 This doesn't count as a module - it defines a few arrays which are
94 shared between NASM and NDISASM, so it's a separate file which is
95 #included by both parser.c and disasm.c.
100 This is essentially a library module: it exports one function,
101 `float_const', which converts an ASCII representation of a
102 floating-point number into an x86-compatible binary representation,
103 without using any built-in floating-point arithmetic (so it will run
104 on any platform, portably). It calls nothing, and is called only by
105 `parser.c'. Note that the function `float_const' must be passed an
106 error reporting routine.
111 This module contains the code generator: it translates `insn'
112 structures as returned from the parser module into actual generated
113 code which can be placed in an output file. It exports two
114 functions, `assemble' and `insn_size'.
116 `insn_size' is designed to be called on pass one of assembly: it
117 takes an `insn' structure as input, and returns the amount of space
118 that would be taken up if the instruction described in the structure
119 were to be converted to real machine code. `insn_size' also requires
120 to be told the location (as a segment/offset pair) where the
121 instruction would be assembled, the mode of assembly (16/32 bit
122 default), and a function it can call to report errors.
124 `assemble' is designed to be called on pass two: it takes all the
125 parameters that `insn_size' does, but has an extra parameter which
126 is an output driver. `assemble' actually converts the input
127 instruction into machine code, and outputs the machine code by means
128 of calling the `output' function of the driver.
133 This is another library module: it exports one very big array of
134 instruction translations. It has to be a separate module so that DOS
135 compilers, with less memory to spare than typical Unix ones, can
141 This module contains a label manager. It exports six functions:
143 `init_labels' should be called before any other function in the
144 module. `cleanup_labels' may be called after all other use of the
145 module has finished, to deallocate storage.
147 `define_label' is called to define new labels: you pass it the name
148 of the label to be defined, and the (segment,offset) pair giving the
149 value of the label. It is also passed an error-reporting function,
150 and an output driver structure (so that it can call the output
151 driver's label-definition function). `define_label' mentally
152 prepends the name of the most recently defined non-local label to
153 any label beginning with a period.
155 `define_label_stub' is designed to be called in pass two, once all
156 the labels have already been defined: it does nothing except to
157 update the "most-recently-defined-non-local-label" status, so that
158 references to local labels in pass two will work correctly.
160 `declare_as_global' is used to declare that a label should be
161 global. It must be called _before_ the label in question is defined.
163 Finally, `lookup_label' attempts to translate a label name into a
164 (segment,offset) pair. It returns non-zero on success.
166 The label manager module is (theoretically :) restartable: after
167 calling `cleanup_labels', you can call `init_labels' again, and
168 start a new assembly with a new set of symbols.
173 This small module contains a set of routines to manage a list of
174 output formats, and select one given a keyword. It contains three
175 small routines: `ofmt_register' which registers an output driver as
176 part of the managed list, `ofmt_list' which lists the available
177 drivers on stdout, and `ofmt_find' which tries to find the driver
178 corresponding to a given name.
183 Each of the output modules, `outbin.o', `outelf.o' and so on,
184 exports only one symbol, which is an output driver data structure
185 containing pointers to all the functions needed to produce output
186 files of the appropriate type.
188 The exception to this is `outcoff.o', which exports _two_ output
189 driver structures, since COFF and Win32 object file formats are very
190 similar and most of the code is shared between them.
195 This is the main program: it calls all the functions in the above
196 modules, and puts them together to form a working assembler. We
202 In NASM, the term `segment' is used to separate the different
203 sections/segments/groups of which an object file is composed.
204 Essentially, every address NASM is capable of understanding is
205 expressed as an offset from the beginning of some segment.
207 The defining property of a segment is that if two symbols are
208 declared in the same segment, then the distance between them is
209 fixed at assembly time. Hence every externally-declared variable
210 must be declared in its own segment, since none of the locations of
211 these are known, and so no distances may be computed at assembly
214 The special segment value NO_SEG (-1) is used to denote an absolute
215 value, e.g. a constant whose value does not depend on relocation,
216 such as the _size_ of a data object.
218 Apart from NO_SEG, segment indices all have their least significant
219 bit clear, if they refer to actual in-memory segments. For each
220 segment of this type, there is an auxiliary segment value, defined
221 to be the same number but with the LSB set, which denotes the
222 segment-base value of that segment, for object formats which support
223 it (Microsoft .OBJ, for example).
225 Hence, if `textsym' is declared in a code segment with index 2, then
226 referencing `SEG textsym' would return zero offset from
227 segment-index 3. Or, in object formats which don't understand such
228 references, it would return an error instead.
230 The next twist is SEG_ABS. Some symbols may be declared with a
231 segment value of SEG_ABS plus a 16-bit constant: this indicates that
232 they are far-absolute symbols, such as the BIOS keyboard buffer
233 under MS-DOS, which always resides at 0040h:001Eh. Far-absolutes are
234 handled with care in the parser, since they are supposed to evaluate
235 simply to their offset part within expressions, but applying SEG to
236 one should yield its segment part. A far-absolute should never find
237 its way _out_ of the parser, unless it is enclosed in a WRT clause,
238 in which case Microsoft 16-bit object formats will want to know
244 We have tried to write NASM in portable ANSI C: we do not assume
245 little-endianness or any hardware characteristics (in order that
246 NASM should work as a cross-assembler for x86 platforms, even when
247 run on other, stranger machines).
249 Assumptions we _have_ made are:
251 - We assume that `short' is at least 16 bits, and `long' at least
252 32. This really _shouldn't_ be a problem, since Kernighan and
253 Ritchie tell us we are entitled to do so.
255 - We rely on having more than 6 characters of significance on
256 externally linked symbols in the NASM sources. This may get fixed
257 at some point. We haven't yet come across a linker brain-dead
258 enough to get it wrong anyway.
260 - We assume that `fopen' using the mode "wb" can be used to write
261 binary data files. This may be wrong on systems like VMS, with a
262 strange file system. Though why you'd want to run NASM on VMS is
265 That's it. Subject to those caveats, NASM should be completely
266 portable. If not, we _really_ want to know about it.
271 The following is _not_ a portability problem, although it looks like
274 - When compiling with some versions of DJGPP, you may get errors
275 such as `warning: ANSI C forbids braced-groups within
276 expressions'. This isn't NASM's fault - the problem seems to be
277 that DJGPP's definitions of the <ctype.h> macros include a
278 GNU-specific C extension. So when compiling using -ansi and
279 -pedantic, DJGPP complains about its own header files. It isn't a
280 problem anyway, since it still generates correct code.