# Assembling Z80 binaries (All assembers in Collapse OS follow the same basic principles. There are sections, below, for each supported architectures, but you should read this first section first to be familiar with those common, basic principles) Words in the Z80 assembler (B5) allow you to assemble z80 bin- aries. Being Forth words, opcode assembly is a bit different than with a typical assembler. For example, what would tradi- tionally be "ld a, b" would become "A B LDrr,". Those opcode words, of which there is a complete list below, end with "," to indicate that their effect is to write (,) the cor- responding opcode. The "argtype" suffix after each mnemonic is needed because the assembler doesn't auto-detect the op's form based on arguments. It has to be explicitly specified. "r" is for 8-bit registers, "d" for 16-bit ones, "i" for immediate, "c" is for conditions. Be aware that "SP" and "AF" refer to the same value: some 16- bit ops can affect SP, others, AF. If you use the wrong argu- ment on the wrong op, you will affect the wrong register. Mnemonics having only a single form, such as PUSH and POP, don't have argtype suffixes. In addition to opcode words, some variables are also defined by this program: BIN( is the addr at which the compiled binary will live. It is often 0. ORG is H@ offset at which we begin spitting binary. Used to compute PC. To have a proper PC, call "H@ ORG !" at the beginning of your assembly process. PC is H@ - ORG + BIN(. Labels are a convenient way of managing relative jump calculations. Backward labels are easy. It is only a matter or recording "HERE" and do subtractions. Forward labels record the place where we should write the offset, and then when we get to that point later on, the label records the offset there. To avoid using dict memory in compilation targets, we pre-declare label variables here, which means we have a limited number of it. We have 4: L1, L2, L3, L4. # Flow There are 2 label types: backward and forward. For each type, there are two actions: set and write. Setting a label is declaring where it is. Words for this are BSET and FSET. It has to be performed at the label's destination. Writing a label is writing its offset difference to the binary result. It has to be done right after a relative jump operation. Word for this are BWR and FWR. Yes, those words are only for relative jumps. For backward labels, set happens before write. For forward labels, write happen before set. The write operation writes a dummy placeholder, and then the set operation writes the offset at that placeholder's address. Variable actions are expected to be called with labels in front of them. Examples: L1 BSET NOP, JR, L1 BWR ( backward jump ) JR, L1 FWR NOP, L1 FSET ( forward jump ) If you look at the code for those words, you'll notice a mys- terious "1-". z80 relative jumps receives "e-2", that is, the offset that *counts the 2 bytes of the jump itself*. Because we set the label *after* the jump OP1 itself, that's 1 byte that is taken care of. We still need to adjust by another byte before writing the offset. Can you use labels with JP, and CALL,? Yes, but only backwards jumps, and in that case, you use the label's value directly. Example: L2 @ CALL, # Structured flow z80a also has words that behave similarly to IF..THEN and BEGIN..UNTIL. On the IF side, we have IFZ, IFNZ, IFC, IFNC, and THEN,. When the opposite condition is met, a relative jump is made to THEN,'s PC. For example, if you have IFZ, a jump is made when Z is unset. On the BEGIN,..AGAIN, side, it's a bit different. You start with your BEGIN, instruction, and then later you issue a JRxx, instr followed by AGAIN,. Exactly like you would do with a label. On top of that, you have the very nice BREAK, instruction, which must also be preceded by a JRxx, and will jump to the PC following the next AGAIN,. Examples: IFZ, NOP, THEN, BEGIN, NOP, JR, AGAIN, ( unconditional ) BEGIN, NOP, JRZ, AGAIN, ( conditional ) BEGIN, NOP, JRZ, BREAK, JR, AGAIN, ( break off the loop ) # Z80 Instructions list Letters in [] brackets indicate "argtype" variants. When the bracket starts with ",", it means that a "plain" mnemonic is available. For example, "RET," and "RETc," exist. Note that assemblers in Collapse OS are incomplete and opcode words were implemented in a "just-in-time" fashion, when needed. r => A B C D E H L (HL) d => BC DE HL AF/SP c => CNZ CZ CNC CC CPO CPE CP CM LD [rr, ri, di, (i)HL, HL(i), d(i), (i)d, rIXY, IXYr, (DE)A, A(DE), (i)A, A(i)] ADD [r, i, HLd, IXd, IXIX, IYd, IYIY] ADC [r, HLd] CP [r, i, (IXY+)] SBC [r, HLd] SUB [r, i] INC [r, d, (IXY+)] DEC [r, d, (IXY+)] AND [r, i] OR [r, i] XOR [r, i] OUT [iA, (C)r] IN [Ai, r(C)] JP [i, (HL), (IX), (IY)] JR [, Z, NZ, C, NC] PUSH POP SET RES BIT RL RLC SLA RLA RLCA RR RRC SRL RRA RRCA CALL RST DJNZ DI EI EXDEHL EXX HALT NOP RET [,c] RETI RETN SCF