NASM 0.98p3.5
[nasm.git] / internal.doc
blob8a73aa110b5628ad605aca9297673c7cd85f19dd
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
9 look like:
11                   +--- preproc.c ----+
12                   |                  |
13                   +---- parser.c ----+
14                   |        |         |
15                   |     float.c      |
16                   |                  |
17                   +--- assemble.c ---+
18                   |        |         |
19         nasm.c ---+     insnsa.c     +--- nasmlib.c
20                   |                  |
21                   +--- listing.c ----+
22                   |                  |
23                   +---- labels.c ----+
24                   |                  |
25                   +--- outform.c ----+
26                   |                  |
27                   +----- *out.c -----+
29 In other words, each of `preproc.c', `parser.c', `assemble.c',
30 `labels.c', `listing.c', `outform.c' and each of the output format
31 modules `*out.c' are independent modules, which do not directly
32 inter-communicate except through the main program.
34 The Netwide *Disassembler* is not intended to be particularly
35 portable or reusable or anything, however. So I won't bother
36 documenting it here. :-)
38 nasmlib.c
39 ---------
41 This is a library module; it contains simple library routines which
42 may be referenced by all other modules. Among these are a set of
43 wrappers around the standard `malloc' routines, which will report a
44 fatal error if they run out of memory, rather than returning NULL.
46 preproc.c
47 ---------
49 This contains a macro preprocessor, which takes a file name as input
50 and returns a sequence of preprocessed source lines. The only symbol
51 exported from the module is `nasmpp', which is a data structure of
52 type `Preproc', declared in nasm.h. This structure contains pointers
53 to all the functions designed to be callable from outside the
54 module.
56 parser.c
57 --------
59 This contains a source-line parser. It parses `canonical' assembly
60 source lines, containing some combination of the `label', `opcode',
61 `operand' and `comment' fields: it does not process directives or
62 macros. It exports two functions: `parse_line' and `cleanup_insn'.
64 `parse_line' is the main parser function: you pass it a source line
65 in ASCII text form, and it returns you an `insn' structure
66 containing all the details of the instruction on that line. The
67 parameters it requires are:
69 - The location (segment, offset) where the instruction on this line
70   will eventually be placed. This is necessary in order to evaluate
71   expressions containing the Here token, `$'.
73 - A function which can be called to retrieve the value of any
74   symbols the source line references.
76 - Which pass the assembler is on: an undefined symbol only causes an
77   error condition on pass two.
79 - The source line to be parsed.
81 - A structure to fill with the results of the parse.
83 - A function which can be called to report errors.
85 Some instructions (DB, DW, DD for example) can require an arbitrary
86 amount of storage, and so some of the members of the resulting
87 `insn' structure will be dynamically allocated. The other function
88 exported by `parser.c' is `cleanup_insn', which can be called to
89 deallocate any dynamic storage associated with the results of a
90 parse.
92 names.c
93 -------
95 This doesn't count as a module - it defines a few arrays which are
96 shared between NASM and NDISASM, so it's a separate file which is
97 #included by both parser.c and disasm.c.
99 float.c
100 -------
102 This is essentially a library module: it exports one function,
103 `float_const', which converts an ASCII representation of a
104 floating-point number into an x86-compatible binary representation,
105 without using any built-in floating-point arithmetic (so it will run
106 on any platform, portably). It calls nothing, and is called only by
107 `parser.c'. Note that the function `float_const' must be passed an
108 error reporting routine.
110 assemble.c
111 ----------
113 This module contains the code generator: it translates `insn'
114 structures as returned from the parser module into actual generated
115 code which can be placed in an output file. It exports two
116 functions, `assemble' and `insn_size'.
118 `insn_size' is designed to be called on pass one of assembly: it
119 takes an `insn' structure as input, and returns the amount of space
120 that would be taken up if the instruction described in the structure
121 were to be converted to real machine code. `insn_size' also requires
122 to be told the location (as a segment/offset pair) where the
123 instruction would be assembled, the mode of assembly (16/32 bit
124 default), and a function it can call to report errors.
126 `assemble' is designed to be called on pass two: it takes all the
127 parameters that `insn_size' does, but has an extra parameter which
128 is an output driver. `assemble' actually converts the input
129 instruction into machine code, and outputs the machine code by means
130 of calling the `output' function of the driver.
132 insnsa.c
133 --------
135 This is another library module: it exports one very big array of
136 instruction translations. It has to be a separate module so that DOS
137 compilers, with less memory to spare than typical Unix ones, can
138 cope with it.
140 labels.c
141 --------
143 This module contains a label manager. It exports six functions:
145 `init_labels' should be called before any other function in the
146 module. `cleanup_labels' may be called after all other use of the
147 module has finished, to deallocate storage.
149 `define_label' is called to define new labels: you pass it the name
150 of the label to be defined, and the (segment,offset) pair giving the
151 value of the label. It is also passed an error-reporting function,
152 and an output driver structure (so that it can call the output
153 driver's label-definition function). `define_label' mentally
154 prepends the name of the most recently defined non-local label to
155 any label beginning with a period.
157 `define_label_stub' is designed to be called in pass two, once all
158 the labels have already been defined: it does nothing except to
159 update the "most-recently-defined-non-local-label" status, so that
160 references to local labels in pass two will work correctly.
162 `declare_as_global' is used to declare that a label should be
163 global. It must be called _before_ the label in question is defined.
165 Finally, `lookup_label' attempts to translate a label name into a
166 (segment,offset) pair. It returns non-zero on success.
168 The label manager module is (theoretically :) restartable: after
169 calling `cleanup_labels', you can call `init_labels' again, and
170 start a new assembly with a new set of symbols.
172 listing.c
173 ---------
175 This file contains the listing file generator. The interface to the
176 module is through the one symbol it exports, `nasmlist', which is a
177 structure containing six function pointers. The calling semantics of
178 these functions isn't terribly well thought out, as yet, but it
179 works (just about) so it's going to get left alone for now...
181 outform.c
182 ---------
184 This small module contains a set of routines to manage a list of
185 output formats, and select one given a keyword. It contains three
186 small routines: `ofmt_register' which registers an output driver as
187 part of the managed list, `ofmt_list' which lists the available
188 drivers on stdout, and `ofmt_find' which tries to find the driver
189 corresponding to a given name.
191 The output modules
192 ------------------
194 Each of the output modules, `outbin.o', `outelf.o' and so on,
195 exports only one symbol, which is an output driver data structure
196 containing pointers to all the functions needed to produce output
197 files of the appropriate type.
199 The exception to this is `outcoff.o', which exports _two_ output
200 driver structures, since COFF and Win32 object file formats are very
201 similar and most of the code is shared between them.
203 nasm.c
204 ------
206 This is the main program: it calls all the functions in the above
207 modules, and puts them together to form a working assembler. We
208 hope. :-)
210 Segment Mechanism
211 -----------------
213 In NASM, the term `segment' is used to separate the different
214 sections/segments/groups of which an object file is composed.
215 Essentially, every address NASM is capable of understanding is
216 expressed as an offset from the beginning of some segment.
218 The defining property of a segment is that if two symbols are
219 declared in the same segment, then the distance between them is
220 fixed at assembly time. Hence every externally-declared variable
221 must be declared in its own segment, since none of the locations of
222 these are known, and so no distances may be computed at assembly
223 time.
225 The special segment value NO_SEG (-1) is used to denote an absolute
226 value, e.g. a constant whose value does not depend on relocation,
227 such as the _size_ of a data object.
229 Apart from NO_SEG, segment indices all have their least significant
230 bit clear, if they refer to actual in-memory segments. For each
231 segment of this type, there is an auxiliary segment value, defined
232 to be the same number but with the LSB set, which denotes the
233 segment-base value of that segment, for object formats which support
234 it (Microsoft .OBJ, for example).
236 Hence, if `textsym' is declared in a code segment with index 2, then
237 referencing `SEG textsym' would return zero offset from
238 segment-index 3. Or, in object formats which don't understand such
239 references, it would return an error instead.
241 The next twist is SEG_ABS. Some symbols may be declared with a
242 segment value of SEG_ABS plus a 16-bit constant: this indicates that
243 they are far-absolute symbols, such as the BIOS keyboard buffer
244 under MS-DOS, which always resides at 0040h:001Eh. Far-absolutes are
245 handled with care in the parser, since they are supposed to evaluate
246 simply to their offset part within expressions, but applying SEG to
247 one should yield its segment part. A far-absolute should never find
248 its way _out_ of the parser, unless it is enclosed in a WRT clause,
249 in which case Microsoft 16-bit object formats will want to know
250 about it.
252 Porting Issues
253 --------------
255 We have tried to write NASM in portable ANSI C: we do not assume
256 little-endianness or any hardware characteristics (in order that
257 NASM should work as a cross-assembler for x86 platforms, even when
258 run on other, stranger machines).
260 Assumptions we _have_ made are:
262 - We assume that `short' is at least 16 bits, and `long' at least
263   32. This really _shouldn't_ be a problem, since Kernighan and
264   Ritchie tell us we are entitled to do so.
266 - We rely on having more than 6 characters of significance on
267   externally linked symbols in the NASM sources. This may get fixed
268   at some point. We haven't yet come across a linker brain-dead
269   enough to get it wrong anyway.
271 - We assume that `fopen' using the mode "wb" can be used to write
272   binary data files. This may be wrong on systems like VMS, with a
273   strange file system. Though why you'd want to run NASM on VMS is
274   beyond me anyway.
276 That's it. Subject to those caveats, NASM should be completely
277 portable. If not, we _really_ want to know about it.
279 Porting Non-Issues
280 ------------------
282 The following is _not_ a portability problem, although it looks like
283 one.
285 - When compiling with some versions of DJGPP, you may get errors
286   such as `warning: ANSI C forbids braced-groups within
287   expressions'. This isn't NASM's fault - the problem seems to be
288   that DJGPP's definitions of the <ctype.h> macros include a
289   GNU-specific C extension. So when compiling using -ansi and
290   -pedantic, DJGPP complains about its own header files. It isn't a
291   problem anyway, since it still generates correct code.