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
,
49 r
= *reloctail
= nasm_malloc(sizeof(struct Reloc
));
59 static void bin_init (FILE *afp
, efunc errfunc
, ldfunc ldef
, evalfunc eval
)
63 (void) eval
; /* Don't warn that this parameter is unused */
66 (void) ldef
; /* placate optimisers */
68 start_point
= 0L; /* default */
69 textsect
.contents
= saa_init(1L);
70 datasect
.contents
= saa_init(1L);
71 textsect
.length
= datasect
.length
= 0;
72 textsect
.index
= seg_alloc();
73 datasect
.index
= seg_alloc();
75 bssindex
= seg_alloc();
78 data_align
= bss_align
= 4;
81 static void bin_cleanup (int debuginfo
)
84 long datapos
, datagap
, bsspos
;
88 datapos
= start_point
+ textsect
.length
;
89 datapos
= (datapos
+ data_align
-1) & ~(data_align
-1);
90 datagap
= datapos
- (start_point
+ textsect
.length
);
91 bsspos
= datapos
+ datasect
.length
;
92 bsspos
= (bsspos
+ bss_align
-1) & ~(bss_align
-1);
94 saa_rewind (textsect
.contents
);
95 saa_rewind (datasect
.contents
);
97 for (r
= relocs
; r
; r
= r
->next
)
99 unsigned char *p
, *q
, mydata
[4];
102 saa_fread (r
->target
->contents
, r
->posn
, mydata
, r
->bytes
);
106 l
+= ((long)*p
++) << 8;
108 l
+= ((long)*p
++) << 16;
109 l
+= ((long)*p
++) << 24;
113 if (r
->secref
== textsect
.index
)
115 else if (r
->secref
== datasect
.index
)
117 else if (r
->secref
== bssindex
)
120 if (r
->secrel
== textsect
.index
)
122 else if (r
->secrel
== datasect
.index
)
124 else if (r
->secrel
== bssindex
)
129 else if (r
->bytes
== 2)
133 saa_fwrite (r
->target
->contents
, r
->posn
, mydata
, r
->bytes
);
135 saa_fpwrite (textsect
.contents
, fp
);
136 if (datasect
.length
> 0) {
139 saa_fpwrite (datasect
.contents
, fp
);
142 saa_free (textsect
.contents
);
143 saa_free (datasect
.contents
);
151 static void bin_out (long segto
, void *data
, unsigned long type
,
152 long segment
, long wrt
)
154 unsigned char *p
, mydata
[4];
159 wrt
= NO_SEG
; /* continue to do _something_ */
160 error (ERR_NONFATAL
, "WRT not supported by binary output format");
164 * handle absolute-assembly (structure definitions)
166 if (segto
== NO_SEG
) {
167 if ((type
& OUT_TYPMASK
) != OUT_RESERVE
)
168 error (ERR_NONFATAL
, "attempt to assemble code in [ABSOLUTE]"
173 if (segto
== bssindex
) { /* BSS */
174 if ((type
& OUT_TYPMASK
) != OUT_RESERVE
)
175 error(ERR_WARNING
, "attempt to initialise memory in the"
176 " BSS section: ignored");
178 } else if (segto
== textsect
.index
) {
180 } else if (segto
== datasect
.index
) {
183 error(ERR_WARNING
, "attempt to assemble code in"
184 " segment %d: defaulting to `.text'", segto
);
188 if ((type
& OUT_TYPMASK
) == OUT_ADDRESS
) {
189 if (segment
!= NO_SEG
&&
190 segment
!= textsect
.index
&&
191 segment
!= datasect
.index
&&
192 segment
!= bssindex
) {
194 error(ERR_NONFATAL
, "binary output format does not support"
195 " segment base references");
197 error(ERR_NONFATAL
, "binary output format does not support"
198 " external references");
202 if (segment
!= NO_SEG
)
203 add_reloc (s
, type
& OUT_SIZMASK
, segment
, -1L);
205 if ((type
& OUT_SIZMASK
) == 4)
206 WRITELONG (p
, *(long *)data
);
208 WRITESHORT (p
, *(long *)data
);
209 saa_wbytes (s
->contents
, mydata
, type
& OUT_SIZMASK
);
210 s
->length
+= type
& OUT_SIZMASK
;
212 bsslen
+= type
& OUT_SIZMASK
;
213 } else if ((type
& OUT_TYPMASK
) == OUT_RAWDATA
) {
217 saa_wbytes (s
->contents
, data
, type
);
221 } else if ((type
& OUT_TYPMASK
) == OUT_RESERVE
) {
223 error(ERR_WARNING
, "uninitialised space declared in"
224 " %s section: zeroing",
225 (segto
== textsect
.index
? "code" : "data"));
229 saa_wbytes (s
->contents
, NULL
, type
);
234 else if ((type
& OUT_TYPMASK
) == OUT_REL2ADR
||
235 (type
& OUT_TYPMASK
) == OUT_REL4ADR
)
237 realbytes
= ((type
& OUT_TYPMASK
) == OUT_REL4ADR
? 4 : 2);
238 if (segment
!= NO_SEG
&&
239 segment
!= textsect
.index
&&
240 segment
!= datasect
.index
&&
241 segment
!= bssindex
) {
243 error(ERR_NONFATAL
, "binary output format does not support"
244 " segment base references");
246 error(ERR_NONFATAL
, "binary output format does not support"
247 " external references");
251 add_reloc (s
, realbytes
, segment
, segto
);
254 WRITELONG (p
, *(long*)data
- realbytes
- s
->length
);
256 WRITESHORT (p
, *(long*)data
- realbytes
- s
->length
);
257 saa_wbytes (s
->contents
, mydata
, realbytes
);
258 s
->length
+= realbytes
;
264 static void bin_deflabel (char *name
, long segment
, long offset
,
265 int is_global
, char *special
)
268 (void) segment
; /* Don't warn that this parameter is unused */
269 (void) offset
; /* Don't warn that this parameter is unused */
272 error (ERR_NONFATAL
, "binary format does not support any"
273 " special symbol types");
275 if (name
[0] == '.' && name
[1] == '.' && name
[2] != '@') {
276 error (ERR_NONFATAL
, "unrecognised special symbol `%s'", name
);
280 if (is_global
== 2) {
281 error (ERR_NONFATAL
, "binary output format does not support common"
286 static long bin_secname (char *name
, int pass
, int *bits
)
292 (void) pass
; /* Don't warn that this parameter is unused */
295 * Default is 16 bits.
301 return textsect
.index
;
304 while (*p
&& !isspace(*p
)) p
++;
306 if (!strcmp(name
, ".text")) {
307 sec_index
= textsect
.index
;
309 } else if (!strcmp(name
, ".data")) {
310 sec_index
= datasect
.index
;
311 sec_align
= &data_align
;
312 } else if (!strcmp(name
, ".bss")) {
313 sec_index
= bssindex
;
314 sec_align
= &bss_align
;
319 if (!nasm_strnicmp(p
,"align=",6)) {
320 if (sec_align
== NULL
)
321 error(ERR_NONFATAL
, "cannot specify an alignment to"
322 " the `.text' section");
323 else if (p
[6+strspn(p
+6,"0123456789")])
324 error(ERR_NONFATAL
, "argument to `align' is not numeric");
326 unsigned int align
= atoi(p
+6);
327 if (!align
|| ((align
-1) & align
))
328 error(ERR_NONFATAL
, "argument to `align' is not a"
339 static long bin_segbase (long segment
)
344 static int bin_directive (char *directive
, char *value
, int pass
)
348 (void) pass
; /* Don't warn that this parameter is unused */
350 if (!strcmp(directive
, "org")) {
351 start_point
= readnum (value
, &rn_error
);
353 error (ERR_NONFATAL
, "argument to ORG should be numeric");
359 static void bin_filename (char *inname
, char *outname
, efunc error
)
361 standard_extension (inname
, outname
, "", error
);
364 static char *bin_stdmac
[] = {
365 "%define __SECT__ [section .text]",
366 "%imacro org 1+.nolist",
369 "%macro __NASM_CDecl__ 1",
374 static int bin_set_info(enum geninfo type
, char **val
)
378 struct ofmt of_bin
= {
379 "flat-form binary files (e.g. DOS .COM, .SYS)",