|
- # 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, loaded with "5 LOAD" allow you to
- assemble z80 binaries. Being Forth words, opcode assembly is a
- bit different than with a typical assembler. For example, what
- would traditionally 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
-
- Macros:
-
- SUBHLd PUSH [0,1,Z,A] HLZ DEZ
- LDDE(HL) OUT [HL,DE]
-
- # 8086 assembler
-
- Load with "30 LOAD". As with the Z80 assembler, it is incom-
- plete.
-
- Mnemonics are followed by argument types. For example, MOVri,
- moves 8-bit immediate to 8-bit register.
-
- 'r' = 8-bit register 'x' = 16-bit register
- 'i' = 8-bit immediate 'I' = 16-bit immediate
- 's' = SREG register
-
- Mnemonics that only have one signature (for example INT,) don't
- have operands letters.
-
- For jumps, it's special. 's' is SHORT, 'n' is NEAR, 'f' is FAR.
-
- # 8086 Instructions list
-
- r -> AL BL CL DL AH BH CH DX
- x -> AX BX CX DX SP BP SI DI
- s -> ES CS SS DS
- [] -> [SI] [DI] [BP] [BX] [BX+SI] [BX+DI] [BP+SI] [BP+DI]
-
- RET CLI STI HLT CLD STD NOP CBW REPZ REPNZ
- LODSB LODSW CMPSB SMPSW MOVSB MOVSW SCASB SCASW STOSB STOSW
-
- CALL J[Z,NZ,C,NC] JMP[s,n,r,f]
-
- INC[r,x,[w],[b],[w]+,[b]+]
- DEC[r,x,[w],[b],[w]+,[b]+]
- POP[x,[w],[w]+]
- PUSH[x,[w],[w]+,s]
- MUL[r,x]
- DIV[r,x]
- XOR[rr,xx]
- OR[rr,xx]
- AND[rr,xx,ALi,AXI]
- ADD[rr,xx,ALi,AXI,xi]
- SUB[rr,xx,ALi,AXI,xi]
- INT
-
- CMP[rr,xx,r[],x[],r[]+,x[]+]
- MOV[rr,xx,r[],x[],[]r,[]x,r[]+,x[]+,[]+r,[]+x,ri,xI,sx,rm,xm
- mr,mx]
-
- ("1" means "shift by 1", "CL" means "shift by CL")
- ROL[r1,x1,rCL,xCL]
- ROR[r1,x1,rCL,xCL]
- SHL[r1,x1,rCL,xCL]
- SHR[r1,x1,rCL,xCL]
-
- # AVR assembler
-
- Load with "50 LOAD". As with the Z80 assembler, it is incom-
- plete.
-
- All mnemonics in AVR have a single signature. Therefore, we
- don't need any "argtype" suffixes.
-
- Registers are referred to with consts R0-R31. There is
- X, Y, Z, X+, Y+, Z+, X-, Y-, Z- for appropriate ops (LD, ST).
- XL, XH, YL, YH, ZL, ZH are simple aliases to R26-R31.
-
- Branching works differently. Instead of expecting a byte to be
- written after the naked op, branching words expect a displace-
- ment argument.
-
- This is because there's bitwise ORing involved in the creation
- of the final opcode, which makes z80a's approach impractical.
-
- This makes labelling a bit different too. Instead of expecting
- label words after the naked branching op, we rather have label
- words expecting branching wordref as an argument. Examples:
-
- L2 ' BRTS FLBL! ( branch forward to L2 )
- L1 ' RJMP LBL, ( branch backward to L1 )
-
- # Model-specific constants
-
- Model-specific constants must be loaded separately. Here is a
- list of units:
-
- - ATMega328P: B65-B66
-
- Those units contain register constants such as PORTB, DDRB, etc.
- Unlike many moder assemblers, they do not include bit constants.
- Here's an example use:
-
- DDRB 5 SBI,
- PORTB 5 CBI,
- R16 TIFR0 IN,
- R16 0 ( TOV0 ) SBRS,
-
- # AVR instructions list
-
- OPRd (B53)
- ASR COM DEC INC LAC LAS LAT LSR NEG POP PUSH
- ROR SWAP XCH
-
- OPRdRr (B54)
- ADC ADD AND CP CPC CPSE EOR MOV MUL OR SBC
- SUB
-
- OPRdA (B54)
- IN OUT
-
- OPRdK (B55)
- ANDI CPI LDI ORI SBCI SBR SUBI
-
- OPAb (B55)
- CBI SBI SBIC SBIS
-
- OPNA (B56)
- BREAK CL[C,H,I,N,S,T,V,Z] SE[C,H,I,N,S,T,V,Z] EIJMP ICALL
- EICALL IJMP NOP RET RETI SLEEP WDR
-
- OPb (B57)
- BCLR BSET
-
- OPRdb (B57)
- BLD BST SBRC SBRS
-
- Special (B57,B60)
- CLR TST LSL LD ST
-
- Flow (B58)
- RJMP RCALL
- BR[BC,BS,CC,CS,EQ,NE,GE,HC,HS,ID,IE,LO,LT,MI,PL,SH,TC,TS,VC,VS]
-
- Flow macros (B61)
- LBL! LBL, SKIP, TO, FLBL, FLBL! BEGIN, AGAIN? AGAIN, IF, THEN,
|