-
Difference between revisions of "Z80 Assembler Reference Manual"
(Created page with "== Introduction == The assembler incorporated in the HI-TECH C compiler system is a full-featured relocating macro assembler accept- ing Zilog mnemonics. These mnemonics a...") |
|||
Line 2: | Line 2: | ||
The assembler incorporated in the HI-TECH C compiler | The assembler incorporated in the HI-TECH C compiler | ||
− | system is a full-featured relocating macro assembler | + | system is a full-featured relocating macro assembler accepting Zilog mnemonics. These mnemonics and the syntax of the |
− | |||
Z80 assembly language are described in the "Z80 Assembly | Z80 assembly language are described in the "Z80 Assembly | ||
Language Handbook" published by Zilog and are included at | Language Handbook" published by Zilog and are included at | ||
− | the end of this manual as a reference. The assembler | + | the end of this manual as a reference. The assembler implements certain extensions to the operands allowed, and certain additional pseudo-ops, which are described here. The |
− | + | assembler also accepts the additional opcodes for the Hitachi 64180 and Z180 processors. | |
− | |||
− | assembler also accepts the additional opcodes for the | ||
− | |||
== Usage == | == Usage == | ||
Line 25: | Line 21: | ||
options are zero or more options from the following list: | options are zero or more options from the following list: | ||
− | -N | + | ;-N |
− | option suppresses the normal check for arithmetic | + | :Ignore arithmetic overflow in expressions. The -N option suppresses the normal check for arithmetic overflow. The assembler follows the "Z80 Assembly Language Handbook" in its treatment of overflow, and in certain instances this can lead to an error where in fact the expression does evaluate to what the user intended. This option may be used to override the overflow checking. |
− | |||
− | Handbook" in its treatment of overflow, and in certain | ||
− | instances this can lead to an error where in fact the | ||
− | expression does evaluate to what the user intended. | ||
− | This option may be used to override the overflow | ||
− | |||
− | -J | + | ;-J |
− | will request the assembler to attempt to assemble jumps | + | :Attempt to optimize jumps to branches. The -J option will request the assembler to attempt to assemble jumps and conditional jumps as relative branches where possible. Only those conditional jumps with branch equivalents will be optimized, and jumps will only be optimized to branches where the target is in branch range. Note that the use of this option slows the assembly down, due to the necessity for the assembler to make an additional pass over the input code. |
− | and conditional jumps as relative branches where | ||
− | |||
− | equivalents will be optimized, and jumps will only be | ||
− | optimized to branches where the target is in branch | ||
− | range. Note that the use of this option slows the | ||
− | assembly down, due to the necessity for the assembler | ||
− | to make an additional pass over the input code. | ||
− | -U | + | ;-U |
− | will suppress error messages relating to undefined | + | :Treat undefined symbols as external. The -U option will suppress error messages relating to undefined symbols. Such symbols are treated as externals in any case. The use of this option will not alter the object code generated, but merely serves to suppress the error messages. |
− | |||
− | case. The use of this option will not alter the object | ||
− | code generated, but merely serves to suppress the error | ||
− | messages. | ||
− | - | + | ;-O<strong>file</strong> |
− | Place the object code in | + | :Place the object code in <strong>file</strong>. The default object file name is constructed from the name of the first source file. Any suffix or file type (i.e. anything following the rightmost dot ('.') in the name is stripped, and the suffix .obj appended. Thus the command |
− | name is constructed from the name of the first source | ||
− | file. Any suffix or file type (i.e. anything following | ||
− | the rightmost dot ('.') in the name is stripped, and | ||
− | the suffix .obj appended. Thus the command | ||
− | ZAS file1.as file2.z80 | + | ZAS file1.as file2.z80 |
− | will produce an object file called file1.obj. The use | + | :will produce an object file called file1.obj. The use of the -O option will override this default convention, allowing the object file to be arbitrarily named. For example: |
− | of the -O option will override this default convention, | ||
− | allowing the object file to be arbitrarily named. For | ||
− | example: | ||
− | ZAS -ox.obj file1.obj | + | ZAS -ox.obj file1.obj |
− | will place the object code in x.obj. | + | :will place the object code in x.obj. |
− | - | + | ;-L<strong>list</strong> |
− | Place an assembly listing in the file | + | :Place an assembly listing in the file <strong>list</strong>, or on standard output if <strong>list</strong> is null A listfile may be produced with the -L option. If a file name is supplied to the option, the list file will be created with that name, otherwise the listing will be written to standard output (i.e. the console). List file names such as CON: and LST: are acceptable. |
− | |||
− | with the -L option. If a file name is supplied to the | ||
− | option, the list file will be created with that name, | ||
− | otherwise the listing will be written to standard | ||
− | |||
− | and LST: are acceptable. | ||
− | - | + | ;-W<strong>width</strong> |
− | The listing is to be formatted for a printer of given | + | :The listing is to be formatted for a printer of given <strong>width</strong> The -W option specifies the width to which the listing is to be formatted. E.g. |
− | |||
− | listing is to be formatted. E.g. | ||
− | ZAS -Llst: -W80 x.as | + | ZAS -Llst: -W80 x.as |
− | will output a listing formatted for an 80 column | + | :will output a listing formatted for an 80 column printer to the list device. |
− | printer to the list device. | ||
− | -C | + | ;-C |
− | information in a file. The file will be called | + | :This options requests ZAS to produce cross reference information in a file. The file will be called <strong>xxx</strong>.crf where <strong>xxx</strong> is the base part of the first source file name. It will then be necessary to run the CREF utility to turn this information into a formatted listing. |
− | where | ||
− | name. It will then be necessary to run the CREF utility | ||
− | to turn this information into a formatted listing. | ||
− | == The Assembly Language | + | == The Assembly Language == |
− | As mentioned above, the assembly language accepted by | + | As mentioned above, the assembly language accepted by zas is based on the Zilog mnemonics. You should have some reference book such as the "Z80 Assembly Language Handbook". Described below are those areas in which zas differs, or has extensions, compared to the standard Zilog assembly language. |
− | zas is based on the Zilog mnemonics. You should have some | ||
− | reference book such as the "Z80 Assembly Language Handbook". | ||
− | Described below are those areas in which zas differs, or has | ||
− | extensions, compared to the standard Zilog assembly | ||
− | language. | ||
=== Symbols === | === Symbols === | ||
The symbols (labels) accepted by the assembler may be | The symbols (labels) accepted by the assembler may be | ||
− | of any length, and all characters are significant. The | + | of any length, and all characters are significant. The characters used to form a symbol may be chosen from the upper |
− | |||
and lower case alphabetics, the digits 0-9, and the special | and lower case alphabetics, the digits 0-9, and the special | ||
Line 116: | Line 70: | ||
distinct symbols. | distinct symbols. | ||
− | An_identifier | + | An_identifier |
− | an_identifier | + | an_identifier |
− | an_identifier1 | + | an_identifier1 |
− | $$$ | + | $$$ |
− | ?$_123455 | + | ?$_123455 |
− | |||
Note that the symbol $ is special (representing the | Note that the symbol $ is special (representing the | ||
Line 143: | Line 96: | ||
such labels. | such labels. | ||
− | entry_point: ;This is referenced from far away | + | entry_point: ;This is referenced from far away |
− | ld b,10 | + | ld b,10 |
− | 1: dec c | + | 1: dec c |
− | jr nz,2f ;if zero, branch forward to 2: | + | jr nz,2f ;if zero, branch forward to 2: |
− | ld c,8 | + | ld c,8 |
− | djnz 1b ;decrement and branch back to 1: | + | djnz 1b ;decrement and branch back to 1: |
− | jr 1f ;this does not branch to the | + | jr 1f ;this does not branch to the |
− | ;same label as the djnz | + | ;same label as the djnz |
− | 2: call fred ;get here from the jr nz,2f | + | 2: call fred ;get here from the jr nz,2f |
− | 1: ret ;get here from the jr 1f | + | 1: ret ;get here from the jr 1f |
Line 170: | Line 123: | ||
set: | set: | ||
− | + | {| | |
− | Character Radix Name | + | |+ |
− | + | !Character|| Radix|| Name | |
− | B 2 binary | + | |- |
− | O 8 octal | + | !B|| 2|| binary |
− | Q 8 octal | + | |- |
− | o 8 octal | + | !O|| 8|| octal |
− | q 8 octal | + | |- |
− | H 16 hexadecimal | + | !Q|| 8|| octal |
− | h 16 hexadecimal | + | |- |
− | + | !o|| 8|| octal | |
+ | |- | ||
+ | !q|| 8|| octal | ||
+ | |- | ||
+ | !H|| 16|| hexadecimal | ||
+ | |- | ||
+ | !h|| 16|| hexadecimal | ||
+ | |} | ||
Hexadecimal constants may also be specified in C style, | Hexadecimal constants may also be specified in C style, | ||
Line 203: | Line 163: | ||
sion. The value of the opcode in this context will be the | sion. The value of the opcode in this context will be the | ||
byte that the opcode would have assembled to if used in the | byte that the opcode would have assembled to if used in the | ||
− | normal way. If the opcode is a 2-byte opcode (CB or ED | + | normal way. If the opcode is a 2-byte opcode (CB or ED prefix byte) only the second byte of the opcode will be used. |
− | |||
This is particularly useful when setting up jump vectors. | This is particularly useful when setting up jump vectors. | ||
For example: | For example: | ||
− | ld a,jp ;a jump instruction | + | ld a,jp ;a jump instruction |
− | ld (0),a ;0 is jump to warm boot | + | ld (0),a ;0 is jump to warm boot |
− | ld hl,boot ;done here | + | ld hl,boot ;done here |
− | ld (1),hl | + | ld (1),hl |
Line 223: | Line 182: | ||
The following operators may be used in expressions: | The following operators may be used in expressions: | ||
− | Operator Meaning | + | {| |
− | + | |+ | |
− | & Bitwise AND | + | !Operator|| Meaning |
− | * Multiplication | + | |- |
− | + Addition | + | !&|| Bitwise AND |
− | - Subtraction | + | |- |
− | + | !*|| Multiplication | |
− | + | |- | |
− | + | !+|| Addition | |
− | + | |- | |
− | + | !-|| Subtraction | |
− | + | .and.|| Bitwise AND | |
− | + | |- | |
− | + | !.eq.|| Equality test | |
− | .and. Bitwise AND | + | |- |
− | .eq. Equality test | + | !.gt.|| Signed greater than |
− | .gt. Signed greater than | + | |- |
− | .high. Hi byte of operand | + | !.high.|| Hi byte of operand |
− | .low. Low byte of operand | + | |- |
− | .lt. Signed less than | + | !.low.|| Low byte of operand |
− | .mod. Modulus | + | |- |
− | .not. Bitwise complement | + | !.lt.|| Signed less than |
− | .or. Bitwise or | + | |- |
− | .shl. Shift left | + | !.mod.|| Modulus |
− | .shr. Shift right | + | |- |
− | .ult. Unsigned less than | + | !.not.|| Bitwise complement |
− | .ugt. Unsigned greater than | + | |- |
− | .xor. Exclusive or | + | !.or.|| Bitwise or |
− | / Divison | + | |- |
− | < Signed less than | + | !.shl.|| Shift left |
− | = Equality | + | |- |
− | > Signed greater than | + | !.shr.|| Shift right |
− | ^ Bitwise or | + | |- |
+ | !.ult.|| Unsigned less than | ||
+ | |- | ||
+ | !.ugt.|| Unsigned greater than | ||
+ | |- | ||
+ | !.xor.|| Exclusive or | ||
+ | |- | ||
+ | !/|| Divison | ||
+ | |- | ||
+ | !<|| Signed less than | ||
+ | |- | ||
+ | !=|| Equality | ||
+ | |- | ||
+ | !>|| Signed greater than | ||
+ | |- | ||
+ | !^|| Bitwise or | ||
+ | |} | ||
Line 278: | Line 253: | ||
− | psect text, global | + | psect text, global |
− | + | ||
− | alabel: | + | alabel: |
− | ld hl,astring | + | ld hl,astring |
− | call putit | + | call putit |
− | ld hl,anotherstring | + | ld hl,anotherstring |
− | + | ||
− | psect data, global | + | psect data, global |
− | astring: | + | astring: |
− | defm 'A string of chars' | + | defm 'A string of chars' |
− | defb 0 | + | defb 0 |
− | anotherstring: | + | anotherstring: |
− | defm 'Another string' | + | defm 'Another string' |
− | defb 0 | + | defb 0 |
− | + | ||
− | psect text | + | psect text |
− | + | ||
− | putit: | + | putit: |
− | ld a,(hl) | + | ld a,(hl) |
− | or a | + | or a |
− | ret z | + | ret z |
− | call outchar | + | call outchar |
− | inc hl | + | inc hl |
− | jr putit | + | jr putit |
Line 341: | Line 316: | ||
DEFB. Example: | DEFB. Example: | ||
− | DEFB 10, 20, 'a', 0FFH | + | DEFB 10, 20, 'a', 0FFH |
− | DB 'hello world',13,10,0 | + | DB 'hello world',13,10,0 |
Line 352: | Line 327: | ||
ple: | ple: | ||
− | pi: DEFF 3.14159 | + | pi: DEFF 3.14159 |
Line 359: | Line 334: | ||
This operates in a similar fashion to DEFB, except that | This operates in a similar fashion to DEFB, except that | ||
− | it assembles expressions into words, without the value | + | it assembles expressions into words, without the value restriction. Example: |
− | |||
− | DEFW -1, 3664H, 'A', 3777Q | + | DEFW -1, 3664H, 'A', 3777Q |
Line 376: | Line 350: | ||
program. Example: | program. Example: | ||
− | DEFS 20h ;reserve 32 bytes of memory | + | DEFS 20h ;reserve 32 bytes of memory |
Line 386: | Line 360: | ||
of a symbol which is already defined. Example: | of a symbol which is already defined. Example: | ||
− | SIZE equ 46 | + | SIZE equ 46 |
Line 396: | Line 370: | ||
− | SIZE defl 48 | + | SIZE defl 48 |
Line 407: | Line 381: | ||
Example: | Example: | ||
− | DEFM 'A string of funny *@$ characters' | + | DEFM 'A string of funny *@$ characters' |
Line 421: | Line 395: | ||
ple: | ple: | ||
− | END somelabel | + | END somelabel |
Line 435: | Line 409: | ||
a COND/ENDC block, for example: | a COND/ENDC block, for example: | ||
− | IF CPM | + | IF CPM |
− | call 5 | + | call 5 |
− | ELSE | + | ELSE |
− | call os_func | + | call os_func |
− | ENDC | + | ENDC |
Line 466: | Line 440: | ||
pseudo-op. The psect flags are as follows: | pseudo-op. The psect flags are as follows: | ||
− | ABS | + | ;ABS |
+ | :Psect is absolute | ||
− | GLOBAL | + | ;GLOBAL |
+ | :Psect is global | ||
− | LOCAL | + | ;LOCAL |
+ | :Psect is not global | ||
− | OVRLD | + | ;OVRLD |
+ | :Psect is to be overlapped by linker | ||
− | PURE | + | ;PURE |
+ | :Psect is to be read-only | ||
Line 490: | Line 469: | ||
The PURE flag instructs the linker that the psect is to | The PURE flag instructs the linker that the psect is to | ||
be made read-only at run time. The usefulness of this flag | be made read-only at run time. The usefulness of this flag | ||
− | depends on the ability of the linker to enforce the | + | depends on the ability of the linker to enforce the requirement. CP/M fails miserably in this regard. |
− | |||
The ABS flag makes a psect absolute. The psect will be | The ABS flag makes a psect absolute. The psect will be | ||
Line 498: | Line 476: | ||
− | PSECT text, global, pure | + | PSECT text, global, pure |
− | PSECT data, global | + | PSECT data, global |
− | PSECT vectors, ovrld | + | PSECT vectors, ovrld |
Line 512: | Line 490: | ||
− | GLOBAL label1, putchar, _printf | + | GLOBAL label1, putchar, _printf |
Line 522: | Line 500: | ||
which must be an absolute expression. Example: | which must be an absolute expression. Example: | ||
− | ORG 100H | + | ORG 100H |
Line 539: | Line 517: | ||
corresponding actual parameter. For example: | corresponding actual parameter. For example: | ||
− | print MACRO string | + | print MACRO string |
− | psect data | + | psect data |
− | 999: db string,'$' | + | 999: db string,'$' |
− | psect text | + | psect text |
− | ld de,999b | + | ld de,999b |
− | ld c,9 | + | ld c,9 |
− | call 5 | + | call 5 |
− | ENDM | + | ENDM |
When used, this macro will expand to the 3 instructions | When used, this macro will expand to the 3 instructions | ||
− | in the body of the macro, with the actual parameters | + | in the body of the macro, with the actual parameters substituted for func and arg. Thus |
− | |||
print 'hello world' | print 'hello world' | ||
Line 559: | Line 536: | ||
expands to | expands to | ||
− | psect data | + | psect data |
− | 999: db 'hello world','$' | + | 999: db 'hello world','$' |
− | psect text | + | psect text |
− | ld de,999b | + | ld de,999b |
− | ld c,9 | + | ld c,9 |
− | call 5 | + | call 5 |
Macro arguments can be enclosed in angle brackets ('<' | Macro arguments can be enclosed in angle brackets ('<' | ||
− | and '>') to pass arbitrary text including delimiter | + | and '>') to pass arbitrary text including delimiter characters like commas as a single argument. For example, suppose |
− | |||
you wanted to use the print macro defined above to print a | you wanted to use the print macro defined above to print a | ||
− | string which includes the carriage return and linefeed | + | string which includes the carriage return and linefeed characters. The macro invocation: |
− | |||
− | print 'hello world',13,10 | + | print 'hello world',13,10 |
Line 582: | Line 557: | ||
as a single argument, you could write: | as a single argument, you could write: | ||
− | print <'hello world',13,10> | + | print <'hello world',13,10> |
which would cause the text 'hello world',13,10 to be passed | which would cause the text 'hello world',13,10 to be passed | ||
− | through as a single argument. This would expand to the | + | through as a single argument. This would expand to the following code: |
− | |||
− | psect data | + | psect data |
− | 999: db 'hello world',13,10,'$' | + | 999: db 'hello world',13,10,'$' |
− | psect text | + | psect text |
− | ld de,999b | + | ld de,999b |
− | ld c,9 | + | ld c,9 |
− | call 5 | + | call 5 |
− | ZAS supports two forms of macro declaration for | + | ZAS supports two forms of macro declaration for compatibility with older versions of ZAS and other Z80 assemblers. The macro name may be declared either in the label |
− | |||
− | |||
field before the MACRO pseudo-op, or in the operand field | field before the MACRO pseudo-op, or in the operand field | ||
− | after the MACRO pseudo-op. Thus these two MACRO | + | after the MACRO pseudo-op. Thus these two MACRO declarations are equivalent: |
− | |||
− | bdos MACRO func,arg | + | bdos MACRO func,arg |
− | ld de,arg | + | ld de,arg |
− | ld c,func | + | ld c,func |
− | call 5 | + | call 5 |
− | ENDM | + | ENDM |
and | and | ||
− | MACRO bdos,func,arg | + | MACRO bdos,func,arg |
− | ld de,arg | + | ld de,arg |
− | ld c,func | + | ld c,func |
− | call 5 | + | call 5 |
− | ENDM | + | ENDM |
Line 625: | Line 596: | ||
The LOCAL pseudo-op allows unique labels to be defined | The LOCAL pseudo-op allows unique labels to be defined | ||
for each expansion of a macro. Any symbols listed after the | for each expansion of a macro. Any symbols listed after the | ||
− | LOCAL directive will have a unique assembler-generated | + | LOCAL directive will have a unique assembler-generated symbol substituted for them when the macro is expanded. For |
− | |||
example: | example: | ||
− | copy MACRO source,dest,count | + | copy MACRO source,dest,count |
− | LOCAL nocopy | + | LOCAL nocopy |
− | push af | + | push af |
− | push bc | + | push bc |
− | ld bc,source | + | ld bc,source |
− | ld a,b | + | ld a,b |
− | or c | + | or c |
− | jr z,nocopy | + | jr z,nocopy |
− | push de | + | push de |
− | push hl | + | push hl |
− | ld de,dest | + | ld de,dest |
− | ld hl,source | + | ld hl,source |
− | ldir | + | ldir |
− | pop hl | + | pop hl |
− | pop de | + | pop de |
− | nocopy: pop bc | + | nocopy: pop bc |
− | pop af | + | pop af |
− | ENDM | + | ENDM |
Line 655: | Line 625: | ||
(recptr),buf,(recsize) will expand to: | (recptr),buf,(recsize) will expand to: | ||
− | push af | + | push af |
− | push bc | + | push bc |
− | ld bc,(recsize) | + | ld bc,(recsize) |
− | ld a,b | + | ld a,b |
− | or c | + | or c |
− | jr z,??0001 | + | jr z,??0001 |
− | push de | + | push de |
− | push hl | + | push hl |
− | ld de,buf | + | ld de,buf |
− | ld hl,(recptr) | + | ld hl,(recptr) |
− | ldir | + | ldir |
− | pop hl | + | pop hl |
− | pop de | + | pop de |
− | ??0001: pop bc | + | ??0001: pop bc |
− | pop af | + | pop af |
if invoked a second time, the label nocopy would expand to | if invoked a second time, the label nocopy would expand to | ||
Line 680: | Line 650: | ||
ment. For example: | ment. For example: | ||
− | REPT 3 | + | REPT 3 |
− | ld (hl),0 | + | ld (hl),0 |
− | inc hl | + | inc hl |
− | ENDM | + | ENDM |
Line 690: | Line 660: | ||
− | ld (hl),0 | + | ld (hl),0 |
− | inc hl | + | inc hl |
− | ld (hl),0 | + | ld (hl),0 |
− | inc hl | + | inc hl |
− | ld (hl),0 | + | ld (hl),0 |
− | inc hl | + | inc hl |
Line 701: | Line 671: | ||
=== IRP and IRPC === | === IRP and IRPC === | ||
− | The IRP and IRPC directives are similar to REPT, | + | The IRP and IRPC directives are similar to REPT, however instead of repeating the block a fixed number of times |
− | |||
it is repeated once for each member of an argument list. In | it is repeated once for each member of an argument list. In | ||
the case of IRP the list is a conventional macro argument | the case of IRP the list is a conventional macro argument | ||
Line 708: | Line 677: | ||
string. For example: | string. For example: | ||
− | IRP string,<'hello world',13,10>,'arg2' | + | IRP string,<'hello world',13,10>,'arg2' |
− | LOCAL str | + | LOCAL str |
− | psect data | + | psect data |
− | str: db string,'$' | + | str: db string,'$' |
− | psect text | + | psect text |
− | ld c,9 | + | ld c,9 |
− | ld de,str | + | ld de,str |
− | call 5 | + | call 5 |
− | ENDM | + | ENDM |
would expand to | would expand to | ||
− | psect data | + | psect data |
− | ??0001: db 'hello world',13,10,'$' | + | ??0001: db 'hello world',13,10,'$' |
− | psect text | + | psect text |
− | ld c,9 | + | ld c,9 |
− | ld de,??0001 | + | ld de,??0001 |
− | call 5 | + | call 5 |
− | psect data | + | psect data |
− | ??0002: db 'arg2','$' | + | ??0002: db 'arg2','$' |
− | psect text | + | psect text |
− | ld c,9 | + | ld c,9 |
− | ld de,??0002 | + | ld de,??0002 |
− | call 5 | + | call 5 |
Line 740: | Line 709: | ||
IRPC is best demonstrated using the following example: | IRPC is best demonstrated using the following example: | ||
− | IRPC char,ABC | + | IRPC char,ABC |
− | ld c,2 | + | ld c,2 |
− | ld e,'char' | + | ld e,'char' |
− | call 5 | + | call 5 |
− | ENDM | + | ENDM |
will expand to: | will expand to: | ||
− | ld c,2 | + | ld c,2 |
− | ld e,'A' | + | ld e,'A' |
− | call 5 | + | call 5 |
− | ld c,2 | + | ld c,2 |
− | ld e,'B' | + | ld e,'B' |
− | call 5 | + | call 5 |
− | ld c,2 | + | ld c,2 |
− | ld e,'C' | + | ld e,'C' |
− | call 5 | + | call 5 |
Line 766: | Line 735: | ||
codes. These are: | codes. These are: | ||
− | + | {| | |
− | | Code| Equivalent| Meaning | | + | |+ |
− | | alt | m | Arithmetic less than | | + | Code|| Equivalent|| Meaning | |
− | | llt | c | Logical less than | | + | |- |
− | | age | p | Arithmetic greater or equal| | + | alt || m || Arithmetic less than | |
− | | lge | nc | Logical greater or equal | | + | |- |
− | | di | | Use after ld a,i for test-| | + | llt || c || Logical less than | |
− | | ei | | ing state of interrupt| | + | |- |
− | | | | enable flag - enabled or| | + | age || p || Arithmetic greater or equal| |
− | | | + | |- |
− | + | lge || nc || Logical greater or equal | | |
+ | |- | ||
+ | di || || Use after ld a,i for test-| | ||
+ | |- | ||
+ | ei || || ing state of interrupt| | ||
+ | |- | ||
+ | || || enable flag - enabled or| | ||
+ | |- | ||
+ | || || disabled respectively. | ||
+ | |} | ||
− | + | == Assembler Directives == | |
− | An assembler directive is a line in the source file | + | An assembler directive is a line in the source file which produces no code, but rather which modifies the behaviour of the assembler. Each directive is recognized by the presence of an asterisk in the first column of the line, followed immediately by a word, only the first character of which is looked at. the line containing the directive itself is never listed. The directives are: |
− | which produces no code, but rather which modifies the | ||
− | behaviour of the assembler. Each directive is recognized by | ||
− | the presence of an asterisk in the first column of the line, | ||
− | followed immediately by a word, only the first character of | ||
− | which is looked at. the line containing the directive itself | ||
− | is never listed. The directives are: | ||
− | *Title | + | ;<nowiki>*Title</nowiki> |
− | Use the text following the directive as a title for the | + | :Use the text following the directive as a title for the listing. |
− | listing. | ||
− | *Heading | + | ;<nowiki>*Heading</nowiki> |
− | Use the text following the directive as a subtitle for | + | :Use the text following the directive as a subtitle for the listing; also causes an *Eject. |
− | the listing; also causes an *Eject. | ||
− | *List | + | ;<nowiki>*List</nowiki> |
− | May be followed by ON or OFF to turn listing on or off | + | :May be followed by ON or OFF to turn listing on or off respectively. Note that this directive may be used inside a macro or include file to control listing of that macro or include file. The previous listing state will be restored on exit from the macro or include file. |
− | respectively. Note that this directive may be used | ||
− | inside a macro or include file to control listing of | ||
− | that macro or include file. The previous listing state | ||
− | will be restored on exit from the macro or include | ||
− | file. | ||
− | *Include | + | ;<nowiki>*Include</nowiki> |
− | The file named following the directive will be included | + | :The file named following the directive will be included in the assembly at that point. |
− | in the assembly at that point. | ||
− | *Eject | + | ;<nowiki>*Eject</nowiki> |
− | A new page will be started in the listing at that | + | :A new page will be started in the listing at that point. A form feed character in the source will have the same effect. |
− | point. A form feed character in the source will have | ||
− | the same effect. | ||
Some examples of the use of these directives: | Some examples of the use of these directives: | ||
− | *Title Widget Control Program | + | *Title Widget Control Program |
− | *Heading Initialization Phase | + | *Heading Initialization Phase |
− | + | ||
− | *Include widget.i | + | *Include widget.i |
Line 827: | Line 789: | ||
An error message will be written on the standard error | An error message will be written on the standard error | ||
− | stream for each error encountered in the assembly. This | + | stream for each error encountered in the assembly. This message identifies the file name and line number and describes |
− | |||
the error. In addition the line in the listing where the | the error. In addition the line in the listing where the | ||
error occurred will be flagged with a single character to | error occurred will be flagged with a single character to | ||
Line 836: | Line 797: | ||
− | A: | + | ;A: |
+ | :Absolute expression required | ||
− | B: | + | ;B: |
− | Bad arg to IM | + | :Bad arg to *L |
− | Bad bit number | + | :Bad arg to IM |
− | Bad character constant | + | :Bad bit number |
− | Bad jump condition | + | :Bad character constant |
+ | :Bad jump condition | ||
− | D: | + | ;D: |
− | Digit out of range | + | :Directive not recognized |
+ | :Digit out of range | ||
− | E: | + | ;E: |
− | Expression error | + | :EOF inside conditional |
+ | :Expression error | ||
− | G: | + | ;G: |
− | Garbage on end of line | + | :Garbage after operands |
+ | :Garbage on end of line | ||
− | I: | + | ;I: |
+ | :Index offset too large | ||
− | J: | + | ;J: |
+ | :Jump target out of range | ||
− | L: | + | ;L: |
+ | :Lexical error | ||
− | M: | + | ;M: |
+ | :Multiply defined symbol | ||
− | O: | + | ;O: |
+ | :Operand error | ||
− | P: | + | ;P: |
− | Psect may not be local and global | + | :Phase error |
+ | :Psect may not be local and global | ||
− | R: | + | ;R: |
+ | :Relocation error | ||
− | S: | + | ;S: |
− | Syntax error | + | :Size error |
+ | :Syntax error | ||
− | U: | + | ;U: |
− | Undefined temporary label | + | :Undefined symbol |
− | Unterminated string | + | :Undefined temporary label |
+ | :Unterminated string | ||
− | + | == Z80/Z180/64180 Instruction Set== | |
The remainder of this chapter is devoted to a complete | The remainder of this chapter is devoted to a complete |
Revision as of 20:00, 30 July 2017
Contents
Introduction
The assembler incorporated in the HI-TECH C compiler system is a full-featured relocating macro assembler accepting Zilog mnemonics. These mnemonics and the syntax of the Z80 assembly language are described in the "Z80 Assembly Language Handbook" published by Zilog and are included at the end of this manual as a reference. The assembler implements certain extensions to the operands allowed, and certain additional pseudo-ops, which are described here. The assembler also accepts the additional opcodes for the Hitachi 64180 and Z180 processors.
Usage
The assembler is named zas, and is invoked as follows:
ZAS options files ...
The files are one or more assembler source files which
will be assembled, but note that all the files are assembled
as one, not as separate files. To assemble separate files,
the assembler must be invoked on each file separately. The
options are zero or more options from the following list:
- -N
- Ignore arithmetic overflow in expressions. The -N option suppresses the normal check for arithmetic overflow. The assembler follows the "Z80 Assembly Language Handbook" in its treatment of overflow, and in certain instances this can lead to an error where in fact the expression does evaluate to what the user intended. This option may be used to override the overflow checking.
- -J
- Attempt to optimize jumps to branches. The -J option will request the assembler to attempt to assemble jumps and conditional jumps as relative branches where possible. Only those conditional jumps with branch equivalents will be optimized, and jumps will only be optimized to branches where the target is in branch range. Note that the use of this option slows the assembly down, due to the necessity for the assembler to make an additional pass over the input code.
- -U
- Treat undefined symbols as external. The -U option will suppress error messages relating to undefined symbols. Such symbols are treated as externals in any case. The use of this option will not alter the object code generated, but merely serves to suppress the error messages.
- -Ofile
- Place the object code in file. The default object file name is constructed from the name of the first source file. Any suffix or file type (i.e. anything following the rightmost dot ('.') in the name is stripped, and the suffix .obj appended. Thus the command
ZAS file1.as file2.z80
- will produce an object file called file1.obj. The use of the -O option will override this default convention, allowing the object file to be arbitrarily named. For example:
ZAS -ox.obj file1.obj
- will place the object code in x.obj.
- -Llist
- Place an assembly listing in the file list, or on standard output if list is null A listfile may be produced with the -L option. If a file name is supplied to the option, the list file will be created with that name, otherwise the listing will be written to standard output (i.e. the console). List file names such as CON: and LST: are acceptable.
- -Wwidth
- The listing is to be formatted for a printer of given width The -W option specifies the width to which the listing is to be formatted. E.g.
ZAS -Llst: -W80 x.as
- will output a listing formatted for an 80 column printer to the list device.
- -C
- This options requests ZAS to produce cross reference information in a file. The file will be called xxx.crf where xxx is the base part of the first source file name. It will then be necessary to run the CREF utility to turn this information into a formatted listing.
The Assembly Language
As mentioned above, the assembly language accepted by zas is based on the Zilog mnemonics. You should have some reference book such as the "Z80 Assembly Language Handbook". Described below are those areas in which zas differs, or has extensions, compared to the standard Zilog assembly language.
Symbols
The symbols (labels) accepted by the assembler may be of any length, and all characters are significant. The characters used to form a symbol may be chosen from the upper and lower case alphabetics, the digits 0-9, and the special
symbols underscore ('_'), dollar ('$') and question mark ('?'). The first character may not be numeric. Upper and lower case are distinct. The following are all legal and distinct symbols.
An_identifier an_identifier an_identifier1 $$$ ?$_123455
Note that the symbol $ is special (representing the current location) and may not be used as a label. Nor may any opcode or pseudo-op mnemonic, register name or condition code name. You should note the additional condition code names described later.
Temporary Labels
The assembler implements a system of temporary labels, useful for use within a localized section of code. These help eliminate the need to generate names for labels which are referenced only in the immediate vicinity of their definition, for example where a loop is implemented.
A temporary label takes the form of a digit string. A reference to such a label requires the same digit string, plus an appended b or f to signify a backward or forward reference respectively. Here is an example of the use of such labels.
entry_point: ;This is referenced from far away ld b,10 1: dec c jr nz,2f ;if zero, branch forward to 2: ld c,8 djnz 1b ;decrement and branch back to 1: jr 1f ;this does not branch to the ;same label as the djnz 2: call fred ;get here from the jr nz,2f 1: ret ;get here from the jr 1f
The digit string may be any positive decimal number 0
to 65535. A temporary label value may be re-used any number
of times. Where a reference to e.g. 1b is made, this will
reference the closest label 1: found by looking backwards
from the current point in the file. Similarly 23f will
reference the first label 23: found by looking forwards from
the current point in the file.
Constants
Constants may be entered in one of the radices 2, 8, 10 or 16. The default is 10. Constants in the other radices may be denoted by a trailing character drawn from the following set:
Character | Radix | Name |
---|---|---|
B | 2 | binary |
O | 8 | octal |
Q | 8 | octal |
o | 8 | octal |
q | 8 | octal |
H | 16 | hexadecimal |
h | 16 | hexadecimal |
Hexadecimal constants may also be specified in C style, for example LD A,0x21. Note that a lower case b may not be used to indicate a binary number, since 1b is a backward reference to a temporary label 1:.
Character Constants
A character constant is a single character enclosed in single quotes ('). Multi character constants may be used only as an operand to a DEFM pseudo-op.
Floating Constants
A floating constant in the usual notation (e.g. 1.234 or 1234e-3) may be used as the operand to a DEFF pseudo-op.
Opcode Constants
Any z80 opcode may be used as a constant in an expres- sion. The value of the opcode in this context will be the byte that the opcode would have assembled to if used in the normal way. If the opcode is a 2-byte opcode (CB or ED prefix byte) only the second byte of the opcode will be used. This is particularly useful when setting up jump vectors. For example:
ld a,jp ;a jump instruction ld (0),a ;0 is jump to warm boot ld hl,boot ;done here ld (1),hl
Expressions
Expressions are constructed largely as described in the "Z80 Assembly Language Handbook".
Operators
The following operators may be used in expressions:
Operator | Meaning |
---|---|
& | Bitwise AND |
* | Multiplication |
+ | Addition |
- | Subtraction
.and.|| Bitwise AND |
.eq. | Equality test |
.gt. | Signed greater than |
.high. | Hi byte of operand |
.low. | Low byte of operand |
.lt. | Signed less than |
.mod. | Modulus |
.not. | Bitwise complement |
.or. | Bitwise or |
.shl. | Shift left |
.shr. | Shift right |
.ult. | Unsigned less than |
.ugt. | Unsigned greater than |
.xor. | Exclusive or |
/ | Divison |
< | Signed less than |
= | Equality |
> | Signed greater than |
^ | Bitwise or |
Operators starting with a dot "." should be delimited
by spaces, thus label .and. 1 is valid but label.and.1 is
not.
Relocatability
Zas produces object code which is relocatable; this means that it is not necessary to specify assembly time where the code is to be located in memory. It is possible to do so, by use of the ORG pseudo-op, however the preferred approach is to use program sections or psects. A psect is a named section of the program, in which code or data may be defined at assembly time. All parts of a psect will be loaded contiguously into memory, even if they were defined in separate files, or in the same file but separated by code for another psect. For example, the following code will load some executable instructions into the psect named text, and some data bytes into the data psect.
psect text, global alabel: ld hl,astring call putit ld hl,anotherstring psect data, global astring: defm 'A string of chars' defb 0 anotherstring: defm 'Another string' defb 0 psect text putit: ld a,(hl) or a ret z call outchar inc hl jr putit
Note that even though the two blocks of code in the
text psect are separated by a block in the data psect, the
two text psect blocks will be contiguous when loaded by the
linker. The instruction "ld hl,anotherstring" will fall
through to the label "putit:" during execution. The actual
location in memory of the two psects will be determined by
the linker. See the linker manual for information on how
psect addresses are determined.
A label defined in a psect is said to be relocatable, that is, its actual memory address is not determined at assembly time. Note that this does not apply if the label is in the default (unnamed) psect, or in a psect declared abso- lute (see the PSECT pseudo-op description below). Any labels declared in an absolute psect will be absolute, that is their address will be determined by the assembler.
With the version of ZAS supplied with version 7 or later of HI-TECH C, relocatable expressions may be combined freely in expressions. Older versions of ZAS allowed only limited arithmetic on relocatable expressions.
Pseudo-ops
The pseudo-ops are based on those described in the "Z80 Assembly Language Handbook", with some additions.
DEFB, DB
This pseudo-op should be followed by a comma-separated list of expressions, which will be assembled into sequential
byte locations. Each expression must have a value between
-128 and 255 inclusive. DB can be used as a synonym for
DEFB. Example:
DEFB 10, 20, 'a', 0FFH DB 'hello world',13,10,0
DEFF
This pseudo-op assembles floating point constants into 32 bit HI-TECH C format floating point constants. For exam- ple:
pi: DEFF 3.14159
DEFW
This operates in a similar fashion to DEFB, except that it assembles expressions into words, without the value restriction. Example:
DEFW -1, 3664H, 'A', 3777Q
DEFS
Defs reserves memory locations without initializing them. Its operand is an absolute expression, representing the number of bytes to be reserved. This expression is added to the current location counter. Note however that locations reserved by DEFS may be initialized to zero by the linker if the reserved locations are in the middle of the program. Example:
DEFS 20h ;reserve 32 bytes of memory
EQU
Equ sets the value of a symbol on the left of EQU to the expression on the right. It is illegal to set the value of a symbol which is already defined. Example:
SIZE equ 46
DEFL
This is identical to EQU except that it may redefine existing symbols. Example:
SIZE defl 48
DEFM
Defm should be followed by a string of characters, enclosed in single quotes. The ASCII values of these char- acters are assembled into successive memory locations. Example:
DEFM 'A string of funny *@$ characters'
END
The end of an assembly is signified by the end of the source file, or the END pseudo-op. The END pseudo-op may optionally be followed by an expression which will define the start address of the program. This is not actually use- ful for CP/M. Only one start address may be defined per pro- gram, and the linker will complain if there are more. Exam- ple:
END somelabel
COND, IF, ELSE, ENDC
Conditional assembly is introduced by the COND pseudo- op. The operand to COND must be an absolute expression. If its value is false (zero) the code following the COND up to the corresponding ENDC pseudo-op will not be assembled. COND/ENDC pairs may be nested. IF may be used as a synonym for COND. The ELSE pseudo operation may be included within a COND/ENDC block, for example:
IF CPM call 5 ELSE call os_func ENDC
ELSE
See COND.
ENDC
See COND.
ENDM
See MACRO.
PSECT
This pseudo-op allows specification of relocatable pro- gram sections. Its arguments are a psect name, optionally followed by a list of psect flags. The psect name is a sym- bol constructed according to the same rules as for labels, however a psect may have the same name as a label without conflict. Psect names are recognized only after a PSECT pseudo-op. The psect flags are as follows:
- ABS
- Psect is absolute
- GLOBAL
- Psect is global
- LOCAL
- Psect is not global
- OVRLD
- Psect is to be overlapped by linker
- PURE
- Psect is to be read-only
If a psect is global, the linker will merge it with any
other global psects of the same name from other modules.
Local psects will be treated as distinct from any other
psect from another module. Psects are global by default.
By default the linker concatenates code within a psect from various modules. If a psect is specified as OVRLD, the linker will overlap each module's contribution to that psect. This is particularly useful when linking modules which initialize e.g. interrupt vectors.
The PURE flag instructs the linker that the psect is to be made read-only at run time. The usefulness of this flag depends on the ability of the linker to enforce the requirement. CP/M fails miserably in this regard.
The ABS flag makes a psect absolute. The psect will be loaded at zero. This is useful for statically initializing interrupt vectors and jump tables. Examples:
PSECT text, global, pure PSECT data, global PSECT vectors, ovrld
GLOBAL
Global should be followed by one more symbols (comma separated) which will be treated by the assembler as global symbols, either internal or external depending on whether they are defined within the current module or not. Example:
GLOBAL label1, putchar, _printf
ORG
An ORG pseudo-op sets the current psect to the default (absolute) psect, and the location counter to its operand, which must be an absolute expression. Example:
ORG 100H
MACRO
This pseudo-op defines a macro. It should be either preceded or followed by the macro name, then optionally fol- lowed by a comma-separated list of formal parameters. The lines of code following the MACRO pseudo-op up to the next ENDM pseudo-op will be stored as the body of the macro. The macro name may subsequently be used in the opcode part of an assembler statement, followed by actual parameters. The text of the body of the macro will be substituted at that point, with any use of the formal parameters substituted with the corresponding actual parameter. For example:
print MACRO string psect data 999: db string,'$' psect text ld de,999b ld c,9 call 5 ENDM
When used, this macro will expand to the 3 instructions in the body of the macro, with the actual parameters substituted for func and arg. Thus
print 'hello world'
expands to
psect data 999: db 'hello world','$' psect text ld de,999b ld c,9 call 5
Macro arguments can be enclosed in angle brackets ('<' and '>') to pass arbitrary text including delimiter characters like commas as a single argument. For example, suppose you wanted to use the print macro defined above to print a string which includes the carriage return and linefeed characters. The macro invocation:
print 'hello world',13,10
would fail because 13 and 10 are treated as extra arguments
and ignored. In order to pass a string which includes commas
as a single argument, you could write:
print <'hello world',13,10>
which would cause the text 'hello world',13,10 to be passed
through as a single argument. This would expand to the following code:
psect data 999: db 'hello world',13,10,'$' psect text ld de,999b ld c,9 call 5
ZAS supports two forms of macro declaration for compatibility with older versions of ZAS and other Z80 assemblers. The macro name may be declared either in the label field before the MACRO pseudo-op, or in the operand field after the MACRO pseudo-op. Thus these two MACRO declarations are equivalent:
bdos MACRO func,arg ld de,arg ld c,func call 5 ENDM
and
MACRO bdos,func,arg ld de,arg ld c,func call 5 ENDM
LOCAL
The LOCAL pseudo-op allows unique labels to be defined for each expansion of a macro. Any symbols listed after the LOCAL directive will have a unique assembler-generated symbol substituted for them when the macro is expanded. For
example:
copy MACRO source,dest,count LOCAL nocopy push af push bc ld bc,source ld a,b or c jr z,nocopy push de push hl ld de,dest ld hl,source ldir pop hl pop de nocopy: pop bc pop af ENDM
when expanded will include a unique assembler generated
label in place of nocopy. For example, copy
(recptr),buf,(recsize) will expand to:
push af push bc ld bc,(recsize) ld a,b or c jr z,??0001 push de push hl ld de,buf ld hl,(recptr) ldir pop hl pop de ??0001: pop bc pop af
if invoked a second time, the label nocopy would expand to ??0002.
REPT
The REPT pseudo-op defines a temporary macro which is then expanded a number of times, as determined by its argu- ment. For example:
REPT 3 ld (hl),0 inc hl ENDM
will expand to
ld (hl),0 inc hl ld (hl),0 inc hl ld (hl),0 inc hl
IRP and IRPC
The IRP and IRPC directives are similar to REPT, however instead of repeating the block a fixed number of times it is repeated once for each member of an argument list. In the case of IRP the list is a conventional macro argument list, in the case of IRPC it is successive characters from a string. For example:
IRP string,<'hello world',13,10>,'arg2' LOCAL str psect data str: db string,'$' psect text ld c,9 ld de,str call 5 ENDM
would expand to
psect data ??0001: db 'hello world',13,10,'$' psect text ld c,9 ld de,??0001 call 5 psect data ??0002: db 'arg2','$' psect text ld c,9 ld de,??0002 call 5
Note the use of LOCAL labels and angle brackets in the same
manner as with conventional macros.
IRPC is best demonstrated using the following example:
IRPC char,ABC ld c,2 ld e,'char' call 5 ENDM
will expand to:
ld c,2 ld e,'A' call 5 ld c,2 ld e,'B' call 5 ld c,2 ld e,'C' call 5
Extended Condition Codes
The assembler recognizes several additional condition codes. These are:
disabled respectively. |
Assembler Directives
An assembler directive is a line in the source file which produces no code, but rather which modifies the behaviour of the assembler. Each directive is recognized by the presence of an asterisk in the first column of the line, followed immediately by a word, only the first character of which is looked at. the line containing the directive itself is never listed. The directives are:
- *Title
- Use the text following the directive as a title for the listing.
- *Heading
- Use the text following the directive as a subtitle for the listing; also causes an *Eject.
- *List
- May be followed by ON or OFF to turn listing on or off respectively. Note that this directive may be used inside a macro or include file to control listing of that macro or include file. The previous listing state will be restored on exit from the macro or include file.
- *Include
- The file named following the directive will be included in the assembly at that point.
- *Eject
- A new page will be started in the listing at that point. A form feed character in the source will have the same effect.
Some examples of the use of these directives:
*Title Widget Control Program *Heading Initialization Phase *Include widget.i
Diagnostics
An error message will be written on the standard error stream for each error encountered in the assembly. This message identifies the file name and line number and describes the error. In addition the line in the listing where the error occurred will be flagged with a single character to indicate the error. The characters and the corresponding messages are:
- A
- Absolute expression required
- B
- Bad arg to *L
- Bad arg to IM
- Bad bit number
- Bad character constant
- Bad jump condition
- D
- Directive not recognized
- Digit out of range
- E
- EOF inside conditional
- Expression error
- G
- Garbage after operands
- Garbage on end of line
- I
- Index offset too large
- J
- Jump target out of range
- L
- Lexical error
- M
- Multiply defined symbol
- O
- Operand error
- P
- Phase error
- Psect may not be local and global
- R
- Relocation error
- S
- Size error
- Syntax error
- U
- Undefined symbol
- Undefined temporary label
- Unterminated string
Z80/Z180/64180 Instruction Set
The remainder of this chapter is devoted to a complete instruction set listing for the Z80, Z180, 64180 and NSC800 processors. The Z180 and 64180 will execute all Z80 instructions, although the timing is different.