Mini-HOWTO
Using ASxxxx for Model 100 Development
Willard Goosey
4/16/2016

The ASxxxx suite of 8-bit cross assemblers is one of the only
relocating, linkable-file generating cross assembler for the 8085. (It
also supports just about every other 8-bit CPU ever. For Model 100 we
care about 8085.) It is very powerful, very complicated, and has its
own ways of doing things, apparently inherited from the old DECUS
cross-assemblers.

(Available from http:shop-pdp.net/)

Other software tools required: objcopy(1), one of the standard GNU
binutils, and hex2co from Chris Osburn's personal library on club100.

Producing a single binary from a single source file is pretty straight
forward:
	.bank MLSPACE (base=0xf000,size=0x05ef)
	.area C_seg (cseg,rel,con,bank=MLSPACE)
.include "m100.def"

start::
[boring 8080 code deleted]

	.area d_seg (dseg,rel,con,bank=MLSPACE)
;data area is data, relative, concatable (w other dsegs), 
;       in bank mlspace
mss:  .ascii 'hello world'
   .dw #0x0d0a
   .db #0
;   .end start

But what's the fun of that? The point of an assembler with a linker is
to have linkable binary subroutines that don't need to be edited every
time a binary is built!

Only the linker threw me a curve ball! If you have code with both a
CODE segment and a DATA segment, it *really* wants to put the data
segment in a seperate hex file. Worse both the code and data segments
start at address 0000h! What????

After much hacking, cursing, and eventually reading the docs, I came
up with a scheme that worked:

*main file...
;override default banks...
	.bank _CSEG (BASE=0xF000)
	.area _CODE (cseg,rel,con,bank=_CSEG)
main::
	[more boring 8080 code]
	.area w_DATA (rel,con,bank=_CSEG)
               
msg1::  .asciz 'Input a hex number >'
	[more data definitions boring]


*subroutine file:
        .area _CODE
psuran::        ora a           ;test entry
	[boring code here] 

        .area my_DATA (bank=_CSEG)
seed:   .db 85,85,85

etc....

By forcing all segments to be in the CSEG bank, it all gets put in the
same HEX file, with each segment concatenated on with no address gaps
or overlaps. Even better, with all the actual code in the same _CODE
area, it is all put together, and then the "data" segments are last,
and this pleases my UNIX-trained soul.
 
The only problem with this approach is that the linker creates an Intel HEX
file that is non-continous! While this allowed under the file
specification, hex2co doesn't like it. It is, however, easily fixed
with objcopy(1), a standard GNU binutil.
	objcopy -I ihex -O ihex infile outfile

And I thought I was done! But then I said, "Let's see how Small-C 8085
handles this nonsense!"

It handles it thus:
                ;program area SMALLC_GENERATED is RELOCATABLE
                .area   SMALLC_GENERATED        (REL,CON)
                .module SMALLC_GENERATED
                .area  SMALLC_GENERATED  (REL,CON,CSEG)
srand:
	[8080 code]
       ret
                .area  SMALLC_GENERATED_DATA  (REL,CON,DSEG)
$0:     .db     #84,#121,#112,#101,#32,#97,#32,#99

;eof

Now according the the ASxxxx docs .module is only used by the linker
for error messages, but a complete program as:
*main file
	.module TC2B
	.area TC2B_CODE (cseg,rel,con)
        .org #0xF000

main::  lxi h,msg1  ; hl->message
	[yet more boring code]
	.area TC2B_DATA (rel,con,dseg)
               
msg1::  .asciz 'Input a hex number >'

*subroutine file:
	.module LIBMILLER
	.area LIBMILLER_CODE

c2b::  push h       ;save hl on stack
	[and more code]
     ret
	.area LIBMILLER_DATA (rel,con,dseg)
	.dw....

;eof

Does pretty much exactly what I want: All areas concatenated together
from the .org's base address, stored in a single file, and even
generated a properly continous HEX file for HEX2CO. Only weird thing
is that all areas of a "module" are stored together. In effect the
data areas are intermixed with code areas.

Interestingly this same effect can be caused without the formality of
the .module line, simply by giving your .areas the same prefix name...

	.area TC2B_CODE(rel,con,cseg)
[...stuff...]
	.area TC2B_DATA(rel,con,dseg)
[...more stuff...]
;eof

Seems to have exactly the same effect!

So I now believe I have solved this problem and can get back to making
[boring 8080 code] do what I want it to...

While I'm leaving most of the quirks of the ASX suite to the official
documentation I need to talk briefly about .END here... As with most
assemblers, the END pseudo-op supplies the binary's starting
address. 2 things are interesting about this. 1) HEX2CO doesn't
support it (binary code starts at the lowest address) and 2) as of
ASX5.11 there seems to be some sort of bug in how the address record
is created that objcopy(1) objects to. Briefly, don't use END.

