forked from z88dk/z88dk
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathz80asm.txt
2435 lines (1705 loc) · 124 KB
/
z80asm.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
THE Z80 CROSS ASSEMBLER (z88dk)
Version: v2.6.1 (October 3rd, 2014)
Thank you for purchasing a copy of this cross assembler. We have made an effort
to program an easy user interface and efficient assembler source file compiling.
The object file and library format is an invention of our own and has also been
included in this documentation. We hope that you will enjoy your Z80 machine code
programming with our assembler.
We have made an effort to produce a fairly easy-to-understand documentation. If
you have any comments or corrections, please don't hesitate to contact us:
Gunther Strube
Gl. Kongevej 37, 4.tv.
DK-1610 Kobenhavn V
Denmark
e-mail [email protected]
1. Running the assembler
========================
Since assemblers are developed for programmers the user interface have been
implemented according to the standard command line environment (CLI) used in most
operating systems; however, if only a GUI interface is available (as in MacOS)
then a command shell must be executed to allow standard command line input. The
Z80 Module Assembler command line interface may change if other programmers wish
to implement a different interface to the assembler. You have the opportunity!
1.1. Help page
--------------
When executing the assembler from the command line with the -h option, a help
page is displayed. The page shortly explains the syntax of parameter
specification and which parameters are available.
1.2. Command line
-----------------
The syntax of the assembler parameters is a straightforward design. Filenames or
a project file are always specified. The options may be left out:
z80asm [options] <filename {filename}> | <@modulesfile>
As seen above <options> must be specified first. Then you enter the names of all
files to be assembled. You either choose to specify all file names or a
@<project-file> containing all file names. File name may be specified with or
without the 'asm extension. The correct filename parsing is handled automatically
by the assembler. As seen on the syntax at least one source file must be
specified and may be repeated with several file names. Only one project file may
be specified if no source file names are given.
Many of the parameters are preset with default values which gives an easy user
interface when specifying the assembly parameters. Only advanced parameters need
to be specified explicitly. The help page displays the default parameter values
at the bottom of the page.
1.3. Command line options
-------------------------
Options are used to control the assembly process and output. They are recognized
by the assembler when you specify a leading minus before the option identifier
('-'). Options are always specified before file names or project files.
When the assembler is executed options are all preset with default values and are
either switched ON or OFF (active or not). All options have a single letter
identification. Upper and lower case letters are distinguished, which means that
'a' might be different command than 'A'. If an option is to be turned off, you
simply specify a 'n' before the identification, e.g. -nl which selects listing
files not to be created by the assembler.
1.3.1. -h : Show help screen
Shows a help screen with the available options.
1.3.2. -v : Information during assembly
The assembler writes a certain amount of information to its program window (or on
the command line screen) to let the user know what is happening. For each source
file both the current assembler pass and include file names are displayed. During
linking all object file names and specified names of library modules are
displayed. When all files have been processed and the necessary output generated,
a status message is displayed which informs you of how many errors occurred (or
none). You will also be reported with a message of how many source lines that
have been parsed during a compilation. This information can be very convenient
during a large compilation project, especially on relatively smaller computers
(with less powerful processors) and no hard disk. If you own a powerful 32-bit
computer equipped with a fast hard disk, assembly information is displayed at
high speed (and almost impossible to read); it may then be useful to turn this
information off specifying a -nv option at the command line.
1.3.3. -e<ext> : Use alternative source file extension
The default assembler source file extension is ".asm". Using this option, you
force the assembler to use another default extension, like ".opt" or ".as" for
the source file.
The extension is specified without the ".". Only three letters are accepted - the
rest is discarded.
1.3.4. -M<ext> : Use alternative object file extension
The default assembler object file extension is ".obj". Using this option, you
force the assembler to use another default extension, like ".o" as the object
file name extension.
The extension is specified without the ".". Only three letters are accepted - the
rest is discarded.
1.3.5. -l : Create listing file output
The information in listing files is a combination of the original source file and
additional information of the generated machine code. Further, the listing file
is page formatted with a header specifying the date and time of the compilation,
the filename of the listing and a page number.
For each line of the source file the following information is written:
<source file line number> <assembler address>
<machine code hex dump> <source line>
The machine code and assembler address output are written in hexadecimal
notation. If the machine code uses more the 4 bytes, the source file line is
written on the following line. This usually happens when you have defined a
string constant or a relatively large amount of constant definitions.
The assembler address is always beginning at zero, i.e. the beginning of the
current modules' machine code. In a relocated context of the machine code, where
all code is positioned at fixed addresses, you will have the opportunity to view
the addresses of your code relative to the start of individual modules using the
assembler output addresses. Further, the last assembler address can be
interpreted as the size of the modules' generated machine code.
Listing files also serves the purpose of a hard copy on paper of your programs,
and are useful in a debugging phase (identifying opcodes versus the mnemonic
representation of instructions).
The creation of listing files imposes much more processing work of the assembler.
If you want to compile your code as quickly as possible then don't create listing
files. Listing files obtain their file name from the base of the source filename,
and is added with the 'lst' extension.
1.3.6. -s : Create symbol table
Symbol tables contains the integer form of symbolical names and constants that
has been parsed and generated during a compilation of a source file. The
structure of the symbol table is divided into two columns. The first contains the
parsed symbol names, converted to uppercase. The second column contains the
generated value of the symbol name.
All symbol values are displayed in signed 32-bit hexadecimal notation.
The two columns are separated by tabulators which represents a default value of 8
spaces per tabulator. The width of the symbol name column is defined as the
tabulator distance multiplied by 4. The default width of the name column is 4 * 8
= 32 spaces.
The symbol table will be written to the end of the appropriate listing file, if
listing file and symbol table output is enabled. If no listing file output is
enabled, the symbol table will be written to a separate file, identified with the
base name of the source file module and given the 'sym' extension.
1.3.7. -d : Assemble only updated files
Assemblers usually force compiles all specified files. This is also possible (as
default) for the Z80 Module Assembler. In large application project with 15
modules or more it can be quite frustrating to compile all every time. The
solution is to only assemble updated files and leave the rest (since they have
been compiled to the programmers knowledge).
But in a long term view it is better to just compile a project without thinking
of which files need to be compiled or not. That can be done with the Z80 Module
Assembler. By simply specifying the -d parameter at the command line, only
updated source files are assembled into object files - the rest are ignored.
Using the -d option in combination with a project file gives the best project
setup for a large compilation; compile your projects without worrying about which
module is updated or not.
1.3.8. -b : Link/relocate object files
The -b option must be used if you want to create an executable Z80 machine code
output file of your previously created object files. You may also use the -a
option which is identical in functionality but also includes the -d option. In
other words assemble only updated source modules and perform linking/relocation
of the code afterwards.
* Pass 1:
When the linking process begins with the first object module, it is examined
for an ORG address to perform the absolute address relocation of all the
object module machine code. The ORG (loading address for memory) will have to
be defined in the first source file module. If not, the assembler will prompt
you for it on the command line. The ORG address must be typed in hexadecimal
notation. If you never use the ORG directive in your source files, you can
always explicitly define one at the command line with the -r option.
The next step in the linking process is loading of the machine code from each
object module, in the order of the specified modules. Pass 1 is completed
with loading all local and global symbol definitions of the object modules.
All relocatable address symbols are assigned the correct absolute memory
location (based on ORG).
* Pass 2:
The address patching process. All expressions are now read and evaluated,
then patched into the appropriate positions of the linked machine code.
When all expressions have been evaluated the machine code is completed and
saved to a file named as the first source file module, and assigned the 'bin'
extension.
1.3.9. -a : Combine -d and -b
Same as providing both -b (link/relocate object files) and -d (assemble only
updated files).
1.3.10. -o<binary-filename> : Binary filename
Define another filename for the compiled binary output than the default source
filename of the project, appended with the ".bin" extension.
1.3.11. -m : Create address map information file
When the linking process has been completed and the machine code saved to a file,
the address map file is produced. This file contains the information of all
relocated address symbols with their assigned absolute addresses. Further, an id
is written that displays the scope of the symbols; local ('L') or global ('G').
The last item of each address map line, identified after the colon, is the name
of the module which the symbol name belongs to.
The address map file is divided into two sections; the first produces the symbol
list in alphabetical order (fast lookup of symbol names), the second in order of
their address counterparts. The section is more used during a debugging session
when an address in a disassembly needs to be identified with a name. The second
list also gives a chronological view (composition) of the linked modules.
1.3.12. -r<hex-address> : Re-define the ORG relocation address
During the linking phase of the assembler the ORG address that defines the
position in memory where the code is to be loaded and executed, is fetched from
the first object module file. You can override this by specifying an explicit
address origin by entering the -r option followed by an address in hexadecimal
notation at the command line, e.g.:
z80asm -b -r4000 file.asm
which specifies that your code is to be relocated for address 4000h (16384)
onwards.
Using the -r option supersedes a defined ORG in the object file. You could for
example have defined the ORG to 8000h (32768) in your first source file, then
compiled the project. This would have generated machine code for memory location
8000h (segment 2 in the Cambridge Z88). Since the object files are generated it
is easy to link them again with another ORG address by just using the -r option.
The linking process does not alter the information in object files - they are
only read. The same project could then easily be re-linked to another address,
e.g.
z80asm -b -r2000 file.asm
1.3.13. -R : Generate address independent code
The Z80 processor instruction set allows only relative jumps in maximum +/- 128
bytes using the JR and DJNZ instructions. Further, there is no program counter
relative call-to-subroutine or jump-to-subroutine instruction. If you want a
program to be address-independent no absolute address references may be used in
jump or call instructions. If you want to program Z80 address independent code
you can only write small routines using the JR and DJNZ instructions. With a
restricted interval of 128 bytes you can imagine the size of those routines!
Programming of large applications using address independency is simply impossible
on the Z80 processor with the basic instruction set available. You can only
define a fixed address origin (ORG) for your machine code to be loaded and
executed from. However, there is one solution: before the code is executed an
automatical address-relocation is performed to the current position in memory.
This is done only once. The penalty is that the program fills more space in
memory. This is unavoidable since information must be available to define where
the address relocation has to be performed in the program. Further, a small
routine must be included with the program to read the relocation information and
patch it into the specified locations of the program. It is impossible to
determine the extra size generated with a relocation table. We assume an extra
size of 3 - 3.5K for a typical 16K application program.
You can generate address independent code using the -R option accompanied with
the -a or -b option. There is no other requirements. The relocatable code may be
useful for programmers using the Cambridge Z88 who want to use machine code in
the BBC BASIC application environment. This can easily be interfaced with the DIM
statement to allocate memory for the machine code program, and issue a CALL or
USR() to execute the machine code.
Please note that the linking process with the -R option addresses your code from
0 onwards. This is necessary when the runtime relocation is performed by the
relocator (just before your program is executed). This can be examined by loading
the address map file into a text editor.
The principle of relocation is in fact a self-modifying program. You cannot
relocate a program that has been blown into an EPROM (cannot be modified). You
may only execute relocatable programs in dynamic memory (RAM).
The relocator is built into the Z80 Module Assembler. The relocation table is
created during the linking phase. When all object modules have been linked and
the appropriate machine code generated, the process is ended with first copying
the relocator routine into the executable file, then a relocation table and
finally the compiled machine code program. Any defined ORG in your code is
superseded - this is not necessary in a relocatable program!
Two rules must be obeyed when using relocatable programs:
1. The IY register must have been set up to point at the address where your
program resides. The first code is in fact the relocator which manipulates
your code on the basis of the IY register. If IY is not setup properly your
machine code program will be relocated for an address it is not resided at.
On execution your might then call a random address (on the basis of the
random IY register).
2. Don't use the alternate register set for parameter passing between the
caller (of your code) in the main code and the relocated program. The
following registers are affected by the initial relocation process:
AFBCDEHL/IXIY/........ same
......../..../afbcdehl different
You still have all the main registers for parameter passing which is more than
sufficient for average programming.
When your address-independent code is stored to the file, a message is displayed
which informs the user of how many bytes the relocation header consists of. This
constant is useful since it informs you of the distance between the relocation
header and the start of your code. The map file automatically reflects the
relocation header. All addresses of your code has been modified to include the
relocation header. Please note that all addresses in the map file are defined
from address 0. When your code is placed in an absolute memory address, and you
need to perform a debugging session, you can find your specific label address by
adding the constant from the map file to the memory origin of your code. The
inbuilt relocator routine may be examined by extracting the "relocate.asm" file
from the "Z80src.zip" compressed file resource.
1.3.14. -g : Create global address definition file
With this option it is possible to generate a DEFC directive definition file of
all globally declared identifiers in a file project (declared with the XDEF
directive). These global definitions are calculated from the specified ORG
address (from first module or the -r option). This feature is very useful, if you
want to get access to routines from a separate compilation. If the two code
compilation were placed in different banks of the Z88, it would be possible to
know the correct address of a routine just by using the DEFC address definition
previously compiled. We used this facility to access routines in the two 8K
halves of the segment 0 debugged version. This debugger actually swaps one of the
two 8K blocks in and out of segment 0 when needed to call an 'external' routine.
Applications on the Z88 may only access the upper 8K of segment 0. A 16K
application therefore needs to be split in 8K halves and paged in when needed to
be run in this area. Tuff!
1.3.15. -D<symbol> : Define a static symbol
This option is useful if you want to produce conditional compilations. The symbol
defined here will be active throughout the compilation. We used this feature to
compile machine code on different computer platforms (QL, IBM, LINUX or Z88).
Specify the symbol immediately after the option identifier, i.e.
z80asm -b -DZ88 file.asm
@<project-file> :1.3.16. Using a project file
Project files defines all file names of a project. The file name standard stored
in a project file obeys the operating system notation.
Instead of specifying every module file name at the command line, a simple
reference of a project file can be made instead. According to the rules of the
specification of parameters you specify either your source file modules or use a
project file. The project file specification is of course much faster. An
example:
z80asm -a main pass1 pass2 link asmdrctv z80instr
This command line will compile all specified module file names into a single
executable file called "main.bin". However if a project file 'assembler' were
created already containing the same file names, the command line would have been:
z80asm -a @assembler
- much easier!
A project file only contains file names. Each file name is separated by a newline
character \n. The new line character may be different on various computer
platforms - but the assembler interprets it correctly. The contents of a project
file may look like this:
z80asm
z80pass1
z80pass1
modlink
Project files are easily created using a simple text editor.
1.3.17. -i<library-file> : Include library modules during linking/relocation
This option allows compilation time linking of external machine code, better
known as library routines. Much, much programming time can be saved by producing
a set of standard routines compiled into library files. These may then be
included later in application project compilations. The command line option
allows specification of several library files. For each library reference in an
application module, all library files will be scanned for that particular module.
The filename (inclusive directory path) of the library may be specified
explicitly on the command line immediately after the -i identifier. If you omit
the filename, a default library filename will be used by the assembler. This
default filename is defined by creating the environment variable
"Z80_STDLIB=<library-file>. Please refer to your operating system documentation
on how to create environment variables.
Library files are recognised by the ".lib" extension.
1.3.18. -L<library-path> : Add directory to search path for libraries
Tells the assembler where to look for library files.
1.3.19. -I<include-path> : Add directory to search path for INCLUDE
Tells the assembler where to look for INCLUDE files.
1.3.20. -x : Create a library
A library file is composed of object files surrounded by a few file structures.
The library file format (and object file format) may be found at the end of this
documentation. A library is simply a set of independent routines (that may refer
to each other) put together in a sequential form. You may only specify a single
-x option on the command line. A filename may be explicitly defined (including
device and path information) to determine the storage location of the library. As
in -i you may omit the filename to use the default filename identified by the
"Z80_STDLIB" environment variable. A library routine must be defined using a
simple XLIB directive with an identical address name label definition. Please
refer to further information later in this documentation. The "Z80lib.zip"
contains the standard library with all corresponding source files. Have a look at
them - they clearly displays how to compose a library routine.
One very important aspect of libraries is the time that the assembler spends
searching through them. To optimize the search you should place your routines in
a "topological" order, i.e. routines that access other library routines should be
placed first. In most situations you avoid redundant sequential searching through
the library.
1.3.21. -t<number> : Define tabulator distance for text output files
To save storage space the Z80 cross assembler output files (listing, map, symbol
and XDEF definition files) uses a tabulator control character instead of spaces.
The benefit is about 30% compressed files.
The tabulator distance defines the distance of space between each tabulator it
represents. The default value is 8 spaces per tabulator.
The tabulators are used to separate two columns of information. The first column
contains a name of some sort. Since names have variable length, a size of the
column is defined. The Assembler defines the size of the column by multiplying
the current tabulator distance with 4, i.e. giving a default size of 4*8 = 32
'spaces'. This is usually more than enough for most name definitions parsed from
source files.
You may redefine the tabulator distance by using the -t option immediately
followed by a decimal number, e.g. -t4 for defining a tabulator distance of 4.
The width of the first column will then be 4*4 = 16 'spaces'.
1.3.22. -RCMX000 : Support the RCM2000/RCM3000 series of Z80-like CPU's
This option disables assembly opcodes not available in the RCM2000/RCM3000 series
of Z80-like CPU's.
1.3.23. -plus : Support for the Ti83Plus
Defines how the INVOKE command is coded: either as a RST 28H instruction (option
on) or as a regular CALL instruction (option off).
1.3.24. -IXIY : Swap IX and IY registers
Swaps the IX and IY registers; references to IX are coded as IY and vice versa.
Useful when the assembler is used as a back-end of a compiler that uses one of
the index registers that is used in the target platform.
1.3.25. -C : Enable LINE directive
Enables the LINE directive to synchronize error message line numbers with the
line numbers from the source file.
2. An overview of assembler features and related files
======================================================
2.1. The Z88 operating system definition files
----------------------------------------------
You will find header files containing all operating system definitions as defined
in the Z88 Developers' Notes V3 in the "OZdefc.zip" file. This makes the
operating system interface programming a lot easier.
2.2. The supplied standard library Z80 source files
---------------------------------------------------
We have supplied a standard library with useful routines for both beginners and
professional machine code programmers. All source files are supplied for having
the opportunity to study and improve the routines. However some routines are
programmed especially for the Z88 operating system and may not be of use for
other Z80 based computers unless thoroughly rewritten. The standard library
source files may be found in the "Z80lib.zip" file.
2.3. Z88 module assembler application source
--------------------------------------------
We have supplied the complete source of the Z88 module assembler application.
This allows you to evaluate many aspects of programming applications on the Z88.
Further, most features of the assembler are mirrored in these source files; using
directives, the free format of Z80 mnemonics, library routine access, modular
file design, labels, using expressions, comments, data structure manipulation and
good programming design.
2.4. File based compilation
---------------------------
This assembler is completely file based, i.e. all parsing and code generation is
manipulated via files on storage medias such as harddisks or floppy disks (or
file based RAM-discs).
2.5. Modular source file design
-------------------------------
A compilation may be split into individual source files that either can be linked
together during assembly as a single module or assembled as separate source file
modules. Separate source file modules saves compilation time and memory. Further,
this design is much more straightforward and much more logically clear in a
design phase of a large compilation project than one huge kludge of a source
file.
2.6. Scope of symbols in source modules
---------------------------------------
All source modules may refer to each others symbols by using EXTERN directives.
This means that you refer to external information outside the current source
module. The opposite of an external module reference is to declare symbols
globally available using a PUBLIC directive, i.e. making symbols available to other
source modules. Finally it is possible to have local symbols that are not known to
other source modules than the current. A label or constant that has not been
declared with EXTERN, PUBLIC or GLOBAL is local to the module.
2.7. Using arithmetic and relational expressions
------------------------------------------------
All directives that require a numerical parameter or Z80 mnemonics that use an
integer argument may use expressions. Expressions may be formed by all standard
arithmetic operators and relational operators. Even binary operators are
implemented. All expressions may contain external identifiers and is
automatically resolved during the linking phase. Only certain directives require
compilation time evaluable expressions.
2.8. Source file manipulation
-----------------------------
To allow the Assembler to execute in multitasking environments such as LINUX and
QDOS, all source input files are opened as shared I/O. This allows other programs
to access the source files while the assembler is working. All output files (both
text and binary files) are opened/created for exclusive use; other programs will
have no access to those files until they have been closed.
2.9. Free format of assembler source files
------------------------------------------
The source files may be written in a free format. No fixed position columns as
needed as in the COBOL programming language. All text may be typed in mixed case
(the assembler converts all text input to uppercase). Tabulators may be used
freely (instead of spaces which also saves source file space) to suit the
programmers own habits of structured text layouts. However, one rule must be
obeyed: syntax of Z80 assembler mnemonics and most directives must be completed
on individual lines. Text files using different OS dependant line feed standard
are parsed properly; line feed types CR, LF or CRLF are automatically recognized.
So you can easily compile your sources from Linux/UNIX on an MSDOS platform.
2.10. Specification of filenames
--------------------------------
Specification of file names in source files are always enclosed in double quotes.
The assembler just collects the filename string and uses this to open a file.
This way all filename standards may be used as defined on different operating
system platforms.
2.11. Including other source files into the current source file
---------------------------------------------------------------
The need for header file information such as operating system constants or data
structures is often indispensable for source file modules. Instead of copying the
contents of those files into each module, it is possible to include them at run
time (during parsing). Infinite include file levels are permitted, i.e. included
files calling other files.
2.12. Conditional assembly in source file modules
-------------------------------------------------
Large compilation projects often need to compile the application in several
variations. This can be achieved with enclosing parts of the source with
conditional directives for the different variations of the application. This may
also be useful if the assembler source is ported to several platforms, where
inclusion of other source files (such as header files) are using different
filename standards. The conditional directives IF, IFDEF, IFNDEF, ELSE, and ENDIF
may be nested into infinite levels.
2.13. Undocumented Z80 instruction code generation
--------------------------------------------------
We have included the syntax parsing and code generation of the undocumented Z80
instructions for the sake of completeness. However, IM 2 interrupts must be
disabled before they are executed (an interrupt may otherwise occur in the middle
of the instruction execution). Many games on the ZX Spectrum have used them to
protect the code from prying eyes. The Z88 native debugger code uses some of the
undocumented instructions for fast access to register variables.
2.14. Object file generation
----------------------------
The Z80 Module Assembler generates object files that contains the compressed
version of an assembled source module. The information herein contains declared
symbols (local, global and external), expressions, address origin, module name
and machine code. The object file modules are much smaller than their source file
counterparts (often smaller than 2K).
2.15. Transfer of object files across platforms
-----------------------------------------------
The Z80 Module Assembler is already implemented on several different computer
platforms. You may freely transfer the object files and use them as a part of
another cross-compilation. There is no system-dependent information in the object
files.
2.16. Date stamp controlled assembly
------------------------------------
To avoid unnecessary compilation of source file modules, it is possible to let
the assembler compile only recently updated source file modules by comparing the
date stamp of the source and the object file modules. Source file modules that
are older than object file modules are ignored. This facility is indispensable in
large compilation projects.
2.17. Listing files
-------------------
The assembler may generate listing files that contain a copy of the source file
with additional code generation information of Z80 mnemonics dumped in
hexadecimal format. The listing files are formatted with page headers containing
time of assembly and the filename. Line numbers are included which corresponds to
the source file lines.
2.18. Symbol information
------------------------
All symbol generated values used in source modules may be dumped to the end of
the listing file or as a separate symbol file. If the symbol table is dumped into
the listing file, each symbol will be written with page references of all
occurrences in the listing file. Address symbols (labels) are addressed relative
to the start of the module. Symbol constants are written as defined in the
source. The symbol table is written in alphabetical order with corresponding
values in hexadecimal format.
2.19. Linking and relocation of object modules into executable Z80 machine code
-------------------------------------------------------------------------------
To obtain an executable Z80 machine code file it is necessary to link all
assembled object modules and relocate them at a defined address, where the code
is to be executed at in the computers' memory. The linking & relocation is
performed automatically after completed assembly of all specified source file
modules. The ORG relocation address is specified in the first object module.
2.20. Address map files
-----------------------
The address map is invaluable information during a debugging session of your
compiled program. This file contains all symbolical address labels with their
generated address constants after a completed linking/relocation of all modules
into executable machine code. The map file is ordered in two groups; the first
list contains all symbol names ordered alphabetically with corresponding address
constants, the second list contains all symbols ordered by their address value
(in chronological order).
2.21. Symbol address definition files
-------------------------------------
As with address map files this contains information of globally declared
symbolical address labels, relocated to their absolute position as for the
compiled machine code file. However, the format is completely different; all
symbols are created as constant definitions to be included as a header file into
another source file and assembled. This is useful if you want to call subroutines
compiled separately in another project (originated in a different memory setup).
2.22. Error files
-----------------
Error files are created by the assembler during processing. If any errors should
occur, they will be written to stderr and copied to this file containing
information of where the error occurred in the source module. If no errors were
found, the error file is automatically closed and deleted.
2.23. Creating and using object file libraries for standard routines
--------------------------------------------------------------------
Machine programmers often re-use their standard routines. We have implemented a
file format for generating libraries using the existing object file modules.
Using a simple set of rules makes it very easy to create your own libraries from
your source file modules. Documentation of the library file format is included in
this documentation. At command line infinite number of libraries may be
specified. All will be searched during linking of your object modules for
referenced library routines.
3. Executing the cross assembler and environment variables
==========================================================
The following text describes how to execute the assembler and defining the
environment variables used by the assembler.
3.1. The environment variables
------------------------------
The assembler uses two environment variables:
* "Z80_STDLIB" define the default filename of the standard library filename.
* "Z80_OZFILES" define the default path of the standard Z88 OZ system headers.
3.2. Running in the QDOS/SMSQ operating system environment
----------------------------------------------------------
z80asm may be compiled using the C68 compiler developed by the Walker brothers.
You also need the 'env_bin' file. This is necessary to install into the operating
system before using the assembler. It contains the environment variable facility
integrated on UNIX, MS-DOS and many other operating systems. Include the
following line into your BOOT upstart program:
LRESPR win1_ext_env_bin
The device and path 'win1_ext_' is just an example of where to store your system
extension file. You may have it on your BOOT disk as well. If you don't have
ToolKit 2 on your system use the following line in your BOOT program:
envext=RESPR(1024):LBYTES win1_ext_env_bin,envext:CALL envext
Use the following in your BOOT file to set the environment variables:
SETENV "Z80_OZFILES=win1_z80_src_oz_"
SETENV "Z80_STDLIB=win1_z80_standard_lib"
The example file names are only a demonstration. Change them as necessary.
3.3. Running in the LINUX/UNIX operating system environment
-----------------------------------------------------------
This program can be executed on the LINUX operating system and any other UNIX.
The sources are strictly ANSI C and uses only library calls that are described in
Brian W. Kernighan and Dennis M. Ritchie C books. The important thing to remember
before compiling it under UNIX, is in which direction the integers are stored by
the processor architecture; the famous Big Endian and Little endian concept. The
config.h file uses a "ENDIAN" definition when z80asm must interpret integers in
big endian order. Please set this definition according to your system's processor
architecture. Most people uses the Intel processor when running Linux - this is a
little endian architecture (so you don't need the ENDIAN define...).
You can compile z80asm using GNU C compiler simply by entering the following on
your command line:
gcc -o z80asm -O2 *.c
The environment variables needed by z80asm are easily added in your accounts
login script, ".profile" or ".bash_profile" in your home directory.
3.4. Running in the MS-DOS operating system environment
-------------------------------------------------------
This program can be executed on all MSDOS operating systems using the INTEL 8086
processor up to high speed 80386/80486/Pentium processors on IBM & compatible
computers. Add the source files to your favorite C compiler system in MSDOS or
Windows (here you need to specify compilation options o a console application).
The environment variables are easily put into your AUTOEXEC.BAT file. Simply
specify:
SET Z80_OZFILES=C:\Z80\OZ\
SET Z80_STDLIB=C:\Z80\STANDARD.LIB
Choose your own settings if you like.
If you want the assembler to be accessible in any path, add the path location of
the assembler in the PATH search line:
SET PATH=%PATH%;C:\Z80
4. Z80 module assembler file types
==================================
4.1. The assembler file types and their extension names
-------------------------------------------------------
The Z80 Module Assembler uses several different filename extensions to
distinguish the type of files processed. The base name of the source file is used
to create the various assembler output file types. The following chapters
explains the available files.
4.2. The file name extension identifier
---------------------------------------
The file name extension identifier may be different from platform to platform.
UNIX has no defined standard. MSDOS and TOS uses '.'. QDOS uses the '_'
identifier. SMSQ also allows the '.' extension identifier.
The Assembler implemented on the supplied platforms is defined with the correct
extension identifier. You can see this on the Assembler help page (executing the
program with no parameters).
4.3. File types
---------------
4.3.1. The source file extension, asm
The extension for assembler mnemonic source files is 'asm'. Source files are
specified by the user with or without the extension - whatever chosen, the
assembler will investigate automatically what is needed to read the source files.
You may override the default extension with the -e option.
4.3.2. The object file extension, obj
The extension for object files is 'obj'. The base file name is taken from the
corresponding source file name. This file is generated by the assembler from
parsing the source file and contains intermediate generated machine code, an
address origin of the machine code, symbol information and expressions.
You may override the default extension with the -M option.
4.3.3. The error file extension, err
The extension for error files is 'err'. Before beginning processing the source
files, an error file is created. If any errors should occur, they will be written
to this file containing information of where the error occurred. If no error were
found, the error file is automatically closed and deleted.
Error files are simple text files that can be loaded by any text editor for
evaluation.
4.3.4. The listing file extension, lst
The extension for listing files is 'lst'. The base file name is taken from the
corresponding source file name. This file is generated by the assembler and
contains a hexadecimal output of the generated machine code that corresponds to
the Z80 mnemonic instruction or directive, followed by a copy of the original
source line. If selected, the symbol table is dumped at the end of the listing
file.
4.3.5. The symbol file extension, sym
The extension for symbol table files is 'sym'. The base file name is taken from
the corresponding source file name. The symbol table file contains information
about the defined and used symbols of the source file and their generated values
(labels and constants). The symbol file is only created if listing file output is
disabled.
4.3.6. The executable file extension, bin
The extension for executable Z80 machine code files is 'bin'. The base file name
is taken from the first specified source file name at the command line (or
project file). This is the linked and relocated output of object files and may be
executed by the Z80 processor. You may override this default behaviour by using
the -o option and specify your own output filename (and extension).
You may override this default behavior by using the -o option and specify your
own output filename and extension.
4.3.7. The address map file extension, map
The extension for address map files is 'map'. The base file name is taken from
the first specified source file name at the command line (or project file). This
file is generated by the assembler and contains a list of all defined address
labels from all linked/relocated modules with their calculated (absolute) address
in memory.
4.3.8. The definition file extension, def
The extension for global address label definition files is 'def'. The base file
name is taken from the first specified source file name at the command line (or
project file). This file is generated by the assembler and contains a list of all
globally declared address labels with their calculated (absolute) origin address,
fetched only during assembly of source file modules. The format of the list
contains constant definitions (addresses) and may be parsed e.g. as include files
for other projects.
4.3.9. The library file extension, lib
Library files are identified with the 'lib' extension. Library files may be
created using the -x option. Library may be included into application code during
linking of object modules with the -i option.
5. Compiling files
==================
5.1. The assembler compiling process
------------------------------------
The Z80 Module Assembler uses a two stage compilation process; stage 1 parses
source files and generates object files. Stage 2 reads the object files and links
the object file code, completes with address patching and finishes with storing
the executable code.
5.1.1. Stage 1, parsing and code generation of all source files, object file
generation
A source file is being parsed for Z80 mnemonics and directives. An object file is
created to hold information of module name, local, global and external symbol
identifiers, expressions and the intermediate code generation (but address and
other constant information). During pass 1 all Z80 mnemonics are parsed and code
is generated appropriately. All expressions are evaluated; expressions that
contain relocatable address symbols or external symbol are automatically stored
into the object file. Expressions that didn't evaluate are preserved for pass 2.
When a source file has been read successfully to the end, pass 2 is started.
During pass 2 all non-evaluated expressions from pass 1 are re-evaluated and
stored to the object file if necessary. Errors are reported if symbols are still
missing in expressions. When all expressions are evaluated and no errors
occurred, all "touched" symbols (used in expressions) are stored into the object
file, with scope, type and value. Then, the module name and generated code is
stored to the object file. Various file pointers to sub-sections of the object
file is resolved. The completion of stage 1 is to produce the symbol table output
(either appended to listing file if selected or as a separate file).