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.
22 static struct Section
{
27 static long bsslen
, bssindex
;
35 struct Section
*target
;
36 } *relocs
, **reloctail
;
38 static long start_point
;
40 static void add_reloc (struct Section
*s
, long bytes
, long secref
,
44 r
= *reloctail
= nasm_malloc(sizeof(struct Reloc
));
54 static void bin_init (FILE *afp
, efunc errfunc
, ldfunc ldef
) {
58 (void) ldef
; /* placate optimisers */
60 start_point
= 0L; /* default */
61 textsect
.contents
= saa_init(1L);
62 datasect
.contents
= saa_init(1L);
63 textsect
.length
= datasect
.length
= 0;
64 textsect
.index
= seg_alloc();
65 datasect
.index
= seg_alloc();
67 bssindex
= seg_alloc();
72 static void bin_cleanup (void) {
74 long datapos
, dataalign
, bsspos
;
76 datapos
= (start_point
+ textsect
.length
+ 3) & ~3;/* align on 4 bytes */
77 dataalign
= datapos
- (start_point
+ textsect
.length
);
79 saa_rewind (textsect
.contents
);
80 saa_rewind (datasect
.contents
);
82 bsspos
= (datapos
+ datasect
.length
+ 3) & ~3;
84 for (r
= relocs
; r
; r
= r
->next
) {
85 unsigned char *p
, *q
, mydata
[4];
88 saa_fread (r
->target
->contents
, r
->posn
, mydata
, r
->bytes
);
91 l
+= ((long)*p
++) << 8;
93 l
+= ((long)*p
++) << 16;
94 l
+= ((long)*p
++) << 24;
97 if (r
->secref
== textsect
.index
)
99 else if (r
->secref
== datasect
.index
)
101 else if (r
->secref
== bssindex
)
104 if (r
->secrel
== textsect
.index
)
106 else if (r
->secrel
== datasect
.index
)
108 else if (r
->secrel
== bssindex
)
115 saa_fwrite (r
->target
->contents
, r
->posn
, mydata
, r
->bytes
);
117 saa_fpwrite (textsect
.contents
, fp
);
118 if (datasect
.length
> 0) {
119 fwrite ("\0\0\0\0", dataalign
, 1, fp
);
120 saa_fpwrite (datasect
.contents
, fp
);
123 saa_free (textsect
.contents
);
124 saa_free (datasect
.contents
);
132 static void bin_out (long segto
, void *data
, unsigned long type
,
133 long segment
, long wrt
) {
134 unsigned char *p
, mydata
[4];
139 wrt
= NO_SEG
; /* continue to do _something_ */
140 error (ERR_NONFATAL
, "WRT not supported by binary output format");
144 * handle absolute-assembly (structure definitions)
146 if (segto
== NO_SEG
) {
147 if ((type
& OUT_TYPMASK
) != OUT_RESERVE
)
148 error (ERR_NONFATAL
, "attempt to assemble code in [ABSOLUTE]"
153 if (segto
== bssindex
) { /* BSS */
154 if ((type
& OUT_TYPMASK
) != OUT_RESERVE
)
155 error(ERR_WARNING
, "attempt to initialise memory in the"
156 " BSS section: ignored");
158 } else if (segto
== textsect
.index
) {
160 } else if (segto
== datasect
.index
) {
163 error(ERR_WARNING
, "attempt to assemble code in"
164 " segment %d: defaulting to `.text'", segto
);
168 if ((type
& OUT_TYPMASK
) == OUT_ADDRESS
) {
169 if (segment
!= NO_SEG
&&
170 segment
!= textsect
.index
&&
171 segment
!= datasect
.index
&&
172 segment
!= bssindex
) {
174 error(ERR_NONFATAL
, "binary output format does not support"
175 " segment base references");
177 error(ERR_NONFATAL
, "binary output format does not support"
178 " external references");
182 if (segment
!= NO_SEG
)
183 add_reloc (s
, type
& OUT_SIZMASK
, segment
, -1L);
185 if ((type
& OUT_SIZMASK
) == 4)
186 WRITELONG (p
, *(long *)data
);
188 WRITESHORT (p
, *(long *)data
);
189 saa_wbytes (s
->contents
, mydata
, type
& OUT_SIZMASK
);
190 s
->length
+= type
& OUT_SIZMASK
;
192 bsslen
+= type
& OUT_SIZMASK
;
193 } else if ((type
& OUT_TYPMASK
) == OUT_RAWDATA
) {
197 saa_wbytes (s
->contents
, data
, type
);
201 } else if ((type
& OUT_TYPMASK
) == OUT_RESERVE
) {
203 error(ERR_WARNING
, "uninitialised space declared in"
204 " %s section: zeroing",
205 (segto
== textsect
.index
? "code" : "data"));
209 saa_wbytes (s
->contents
, NULL
, type
);
213 } else if ((type
& OUT_TYPMASK
) == OUT_REL2ADR
||
214 (type
& OUT_TYPMASK
) == OUT_REL4ADR
) {
215 realbytes
= ((type
& OUT_TYPMASK
) == OUT_REL4ADR
? 4 : 2);
216 if (segment
!= NO_SEG
&&
217 segment
!= textsect
.index
&&
218 segment
!= datasect
.index
&&
219 segment
!= bssindex
) {
221 error(ERR_NONFATAL
, "binary output format does not support"
222 " segment base references");
224 error(ERR_NONFATAL
, "binary output format does not support"
225 " external references");
229 add_reloc (s
, realbytes
, segment
, segto
);
232 WRITELONG (p
, *(long*)data
- realbytes
- s
->length
);
234 WRITESHORT (p
, *(long*)data
- realbytes
- s
->length
);
235 saa_wbytes (s
->contents
, mydata
, realbytes
);
236 s
->length
+= realbytes
;
242 static void bin_deflabel (char *name
, long segment
, long offset
,
244 if (is_global
== 2) {
245 error (ERR_NONFATAL
, "binary output format does not support common"
250 static long bin_secname (char *name
, int pass
, int *bits
) {
252 * Default is 16 bits.
258 return textsect
.index
;
260 if (!strcmp(name
, ".text"))
261 return textsect
.index
;
262 else if (!strcmp(name
, ".data"))
263 return datasect
.index
;
264 else if (!strcmp(name
, ".bss"))
270 static long bin_segbase (long segment
) {
274 static int bin_directive (char *directive
, char *value
, int pass
) {
277 if (!strcmp(directive
, "org")) {
278 start_point
= readnum (value
, &rn_error
);
280 error (ERR_NONFATAL
, "argument to ORG should be numeric");
286 static void bin_filename (char *inname
, char *outname
, efunc error
) {
287 standard_extension (inname
, outname
, "", error
);
290 struct ofmt of_bin
= {
291 "flat-form binary files (e.g. DOS .COM, .SYS)",