1 /* outbin.c output routines for the Netwide Assembler to produce
2 * flat-form binary files
4 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
5 * Julian Hall. All rights reserved. The software is
6 * redistributable under the licence given in the file "Licence"
7 * distributed in the NASM archive.
24 static struct Section
{
29 static long bsslen
, bssindex
;
37 struct Section
*target
;
38 } *relocs
, **reloctail
;
40 static long data_align
, bss_align
;
42 static long start_point
;
44 static void add_reloc (struct Section
*s
, long bytes
, long secref
,
48 r
= *reloctail
= nasm_malloc(sizeof(struct Reloc
));
58 static void bin_init (FILE *afp
, efunc errfunc
, ldfunc ldef
, evalfunc eval
) {
62 (void) ldef
; /* placate optimisers */
64 start_point
= 0L; /* default */
65 textsect
.contents
= saa_init(1L);
66 datasect
.contents
= saa_init(1L);
67 textsect
.length
= datasect
.length
= 0;
68 textsect
.index
= seg_alloc();
69 datasect
.index
= seg_alloc();
71 bssindex
= seg_alloc();
74 data_align
= bss_align
= 4;
77 static void bin_cleanup (void) {
79 long datapos
, datagap
, bsspos
;
81 datapos
= start_point
+ textsect
.length
;
82 datapos
= (datapos
+ data_align
-1) & ~(data_align
-1);
83 datagap
= datapos
- (start_point
+ textsect
.length
);
84 bsspos
= datapos
+ datasect
.length
;
85 bsspos
= (bsspos
+ bss_align
-1) & ~(bss_align
-1);
87 saa_rewind (textsect
.contents
);
88 saa_rewind (datasect
.contents
);
90 for (r
= relocs
; r
; r
= r
->next
) {
91 unsigned char *p
, *q
, mydata
[4];
94 saa_fread (r
->target
->contents
, r
->posn
, mydata
, r
->bytes
);
98 l
+= ((long)*p
++) << 8;
100 l
+= ((long)*p
++) << 16;
101 l
+= ((long)*p
++) << 24;
105 if (r
->secref
== textsect
.index
)
107 else if (r
->secref
== datasect
.index
)
109 else if (r
->secref
== bssindex
)
112 if (r
->secrel
== textsect
.index
)
114 else if (r
->secrel
== datasect
.index
)
116 else if (r
->secrel
== bssindex
)
121 else if (r
->bytes
== 2)
125 saa_fwrite (r
->target
->contents
, r
->posn
, mydata
, r
->bytes
);
127 saa_fpwrite (textsect
.contents
, fp
);
128 if (datasect
.length
> 0) {
131 saa_fpwrite (datasect
.contents
, fp
);
134 saa_free (textsect
.contents
);
135 saa_free (datasect
.contents
);
143 static void bin_out (long segto
, void *data
, unsigned long type
,
144 long segment
, long wrt
) {
145 unsigned char *p
, mydata
[4];
150 wrt
= NO_SEG
; /* continue to do _something_ */
151 error (ERR_NONFATAL
, "WRT not supported by binary output format");
155 * handle absolute-assembly (structure definitions)
157 if (segto
== NO_SEG
) {
158 if ((type
& OUT_TYPMASK
) != OUT_RESERVE
)
159 error (ERR_NONFATAL
, "attempt to assemble code in [ABSOLUTE]"
164 if (segto
== bssindex
) { /* BSS */
165 if ((type
& OUT_TYPMASK
) != OUT_RESERVE
)
166 error(ERR_WARNING
, "attempt to initialise memory in the"
167 " BSS section: ignored");
169 } else if (segto
== textsect
.index
) {
171 } else if (segto
== datasect
.index
) {
174 error(ERR_WARNING
, "attempt to assemble code in"
175 " segment %d: defaulting to `.text'", segto
);
179 if ((type
& OUT_TYPMASK
) == OUT_ADDRESS
) {
180 if (segment
!= NO_SEG
&&
181 segment
!= textsect
.index
&&
182 segment
!= datasect
.index
&&
183 segment
!= bssindex
) {
185 error(ERR_NONFATAL
, "binary output format does not support"
186 " segment base references");
188 error(ERR_NONFATAL
, "binary output format does not support"
189 " external references");
193 if (segment
!= NO_SEG
)
194 add_reloc (s
, type
& OUT_SIZMASK
, segment
, -1L);
196 if ((type
& OUT_SIZMASK
) == 4)
197 WRITELONG (p
, *(long *)data
);
199 WRITESHORT (p
, *(long *)data
);
200 saa_wbytes (s
->contents
, mydata
, type
& OUT_SIZMASK
);
201 s
->length
+= type
& OUT_SIZMASK
;
203 bsslen
+= type
& OUT_SIZMASK
;
204 } else if ((type
& OUT_TYPMASK
) == OUT_RAWDATA
) {
208 saa_wbytes (s
->contents
, data
, type
);
212 } else if ((type
& OUT_TYPMASK
) == OUT_RESERVE
) {
214 error(ERR_WARNING
, "uninitialised space declared in"
215 " %s section: zeroing",
216 (segto
== textsect
.index
? "code" : "data"));
220 saa_wbytes (s
->contents
, NULL
, type
);
224 } else if ((type
& OUT_TYPMASK
) == OUT_REL2ADR
||
225 (type
& OUT_TYPMASK
) == OUT_REL4ADR
) {
226 realbytes
= ((type
& OUT_TYPMASK
) == OUT_REL4ADR
? 4 : 2);
227 if (segment
!= NO_SEG
&&
228 segment
!= textsect
.index
&&
229 segment
!= datasect
.index
&&
230 segment
!= bssindex
) {
232 error(ERR_NONFATAL
, "binary output format does not support"
233 " segment base references");
235 error(ERR_NONFATAL
, "binary output format does not support"
236 " external references");
240 add_reloc (s
, realbytes
, segment
, segto
);
243 WRITELONG (p
, *(long*)data
- realbytes
- s
->length
);
245 WRITESHORT (p
, *(long*)data
- realbytes
- s
->length
);
246 saa_wbytes (s
->contents
, mydata
, realbytes
);
247 s
->length
+= realbytes
;
253 static void bin_deflabel (char *name
, long segment
, long offset
,
254 int is_global
, char *special
) {
257 error (ERR_NONFATAL
, "binary format does not support any"
258 " special symbol types");
260 if (name
[0] == '.' && name
[1] == '.' && name
[2] != '@') {
261 error (ERR_NONFATAL
, "unrecognised special symbol `%s'", name
);
265 if (is_global
== 2) {
266 error (ERR_NONFATAL
, "binary output format does not support common"
271 static long bin_secname (char *name
, int pass
, int *bits
) {
277 * Default is 16 bits.
283 return textsect
.index
;
286 while (*p
&& !isspace(*p
)) p
++;
288 if (!strcmp(name
, ".text")) {
289 sec_index
= textsect
.index
;
291 } else if (!strcmp(name
, ".data")) {
292 sec_index
= datasect
.index
;
293 sec_align
= &data_align
;
294 } else if (!strcmp(name
, ".bss")) {
295 sec_index
= bssindex
;
296 sec_align
= &bss_align
;
301 if (!nasm_strnicmp(p
,"align=",6)) {
302 if (sec_align
== NULL
)
303 error(ERR_NONFATAL
, "cannot specify an alignment to"
304 " the `.text' section");
305 else if (p
[6+strspn(p
+6,"0123456789")])
306 error(ERR_NONFATAL
, "argument to `align' is not numeric");
308 unsigned int align
= atoi(p
+6);
309 if (!align
|| ((align
-1) & align
))
310 error(ERR_NONFATAL
, "argument to `align' is not a"
321 static long bin_segbase (long segment
) {
325 static int bin_directive (char *directive
, char *value
, int pass
) {
328 if (!strcmp(directive
, "org")) {
329 start_point
= readnum (value
, &rn_error
);
331 error (ERR_NONFATAL
, "argument to ORG should be numeric");
337 static void bin_filename (char *inname
, char *outname
, efunc error
) {
338 standard_extension (inname
, outname
, "", error
);
341 static char *bin_stdmac
[] = {
342 "%define __SECT__ [section .text]",
343 "%imacro org 1+.nolist",
349 struct ofmt of_bin
= {
350 "flat-form binary files (e.g. DOS .COM, .SYS)",