more fixes; implemented two-pass assembling to resolve all labels (this is just an...
[bz80asm.git] / main.zas
blob5641c31450cc343283687fe1d18fd2b090ebf937
1   $refopt alllabels
3   org   #8000
4   ent   main
6   include "bzasm80.zas"
8 csizestart = $
9   include "labman.zas"
10 csizeend = $
11 $printf "label manager size: %d", csizeend-csizestart
13 csizestart = $
14   include "output.zas"
15 csizeend = $
16 $printf "ouput system size: %d", csizeend-csizestart
18 csizestart = $
19   ;include "output_driver_std.zas"
20   include "output_driver_4x8.zas"
21 csizeend = $
22 $printf "printing driver size: %d", csizeend-csizestart
24 ; so they won't clutter symbol table
25 csizeend = -1
26 csizestart = -1
28   include "disz80.zas"
30 asmdest equ #C000
32 main:
33   call  emitInit
35   ; setup callbacks
36   ld    hl,expr_error_cb
37   ld    (BZ80ASM.EXPR_ERROR_CB),hl
39   ld    hl,expr_error_jrfar_cb
40   ld    (BZ80ASM.ASM_JR_TOO_FAR_CB),hl
42   ld    hl,LABMAN_FIND_LABEL
43   ld    (BZ80ASM.GETLABEL_CB),hl
45   call  LABMAN_INIT
47   di
49   ; two-pass assemling
50 asm_another_pass:
51   ld    ix,asmdest
52   ld    (BZ80ASM.PC),ix
53   ld    iy,strbuf
55 asmmore:
56   ; print line to assemble
57   $IF 0
58   push  iy
59 .dumploop:
60   ld    a,(iy)
61   or    a
62   jr    z,.dumpdone
63   cp    13
64   jr    z,.dumpdone
65   call  EMIT
66   inc   iy
67   jr    .dumploop
68 .dumpdone:
69   pop   iy
70   ld    a,13
71   call  EMIT
72   $ENDIF
74 doasm:
75   push  ix      ; save code destination
76   push  iy      ; we'll need it for listing
77 doasm_nopush:
78   call  BZ80ASM.ASSEM
79   jp    c,list_and_error
80 doasm_done_line:
81   ; DE is code length here
82   pop   bc      ; text starting position
83   pop   hl      ; code starting position
84   call  ASM_LISTING
86   ; check for line terminator
87   ; actually, anything except ':' is line terminator here
88   ; 0 terminates the whole buffer
89   ld    a,(iy)
90   inc   iy
91   or    a
92   jr    z,.bufferdone
93   cp    ':'
94   jr    z,asmmore
95   dec   iy
96 .skip_line:
97   ; skip current line
98   ld    a,(iy)
99   inc   iy
100   or    a
101   jr    z,.bufferdone
102   cp    13
103   jr    nz,.skip_line
104   ; check for buffer termination again
105   ; this pasta sux
106   ld    a,(iy)
107   or    a
108   jr    nz,asmmore
109 .bufferdone:
111   ; advance pass
112   call  LABMAN_ADVANCE_PASS
113   cp    2
114   jr    c,asm_another_pass
116   ; now disasm it
117   ld    hl,msg_disasm
118   call  printstrnl
120   ld    hl,OSWRCH
121   ld    (DISZ80.EMIT_CB),hl
123   push  ix
124   pop   de
125   ld    hl,asmdest
126 disloop:
127   ; HL: address to disasm
128   ; DE: end address
129   push  de
130   ex    de,hl
131   call  DISZ80.DISASM
132   ex    de,hl
133   ld    a,13
134   call  OSWRCH
135   pop   de
136   push  hl
137   or    a
138   sbc   hl,de
139   pop   hl
140   jr    c,disloop
141   ; done with disasm
143   ld    a,6
144   out   (#fe),a
145   jr    $
147 msg_disasm: defm 13,13,"--------",13,"DISASSEMBLY",13,"--------",13+#80
149 trylabel:
150   ld    hl,(BZ80ASM.PC)
151   call  LABMAN_DEFINE_LABEL
152   jr    c,bad_label_name_error
153   call  BZ80ASM.SKIP
154   ; if terminator, don't try to assemble more
155   jr    z,.linedone
156   jp    doasm_nopush
157 .linedone:
158   jp    doasm_done_line
159 .lineerr:
160   jr    list_and_error_no_label_check
163 bad_label_name_error:
164   ld    a,BZ80ASM.EXPR_ERR_INVALID_LABEL_NAME
165   jp    BZ80ASM.PARSE_EXPR_ERROR_A
167 list_and_error:
168   ; bad mnemonics?
169   ld    a,(BZ80ASM.ASM_BAD_B)
170   cp    255
171   jr    z,trylabel
173 list_and_error_no_label_check:
174   ld    hl,errline
175   call  printstrnl
176   push  iy
177   pop   hl    ; current position in text buffer
178   pop   de    ; initial position
179   ; calc length
180   or    a
181   sbc   hl,de
182   jr    z,.nothing
183   ; de: print from here
184   ; hl: length
185 .prloop:
186   ld    a,(de)
187   call  EMIT
188   inc   de
189   dec   hl
190   ld    a,h
191   or    l
192   jr    nz,.prloop
193   dec   de
194   ld    a,(de)
195   or    a
196   jr    z,.doneerrlist
197   cp    13
198   jr    z,.doneerrlist
199   inc   de
200   ld    a,'|'
201   call  EMIT
202 .nothing:
203   ld    a,(de)
204   call  EMIT
205   ld    a,(de)
206   inc   de
207   cp    13
208   jr    nz,.nothing
210 .doneerrlist:
211   ld    hl,errline
212   call  printstrnl
213   ;jp    error_syntax
214   di
215   ld    a,2
216   out   (#fe),a
217   jr    $
218 errline: defx "---------"
221 strbuf:
222   defm  "or   c:inc a ; comment",13
223   defm  "and  (hl)",13
224   defm  "exx",13
225   defm  "label cp  69",13
226   defm  "call 0BEEFh",13
227   defm  "jr   $",13
228   defm  "jr   label",13
229   defm  "djnz label3",13
230   defm  "ld   a,40+2",13
231   defm  "ld   b,44-2",13
232   defm  "ld   c,126/3",13
233   defm  "ld   e,427%10",13
234   defm  "ld   bc,2+3*5",13
235   defm  "ld   bc,0+(2+3)*5",13
236   defm  "ld   bc,[2+3]*5",13
237   defm  "ld   bc,(2+3)*5",13
238   defm  "label3 ld   hl,16384",13
239   defm  "ld   hl,#4001",13
240   defm  "ld   a,(ix-2)",13
241   defm  "ld   c,(ix)",13
242   defm  "ld   de,$1234",13
243   defm  "ld   bc,0x5b02",13
244   defm  "ld   a,0b1001",13
245   defm  "ld   a,%1010",13
246   defm  "ld   ix,-1234",13
247   defm  "ld   iy,-0x602a",13
248   defm  "cp   1<<3",13
249   defm  "cp   8>>2",13
250   defm  "cp   ~0-1",13
251   defm  "defb 7&$c,1|2,1|(3^1),1<<15",13
252   defm  "defw 1<<15",13
253   defm  "defm '012','34'",13
254   defb  0
256 dest: defs 64,0
259 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
261 ;; show listing
262 ;; extracted from assembler code, because we don't need it there
264 ;; IN:
265 ;;   IY: current position in text buffer
266 ;;   IX: current position in code buffer
267 ;;   BC: starting position in text buffer
268 ;;   HL: starting position in code buffer
269 ;;   DE: code length
270 ;; OUT:
271 ;;   IX, IY: unchanged
272 ;;   others are dead
274 ;COUNT:  defb  0  ;PRINT POSITION
275 ASM_LISTING:
276   ld    a,d
277   or    e
278   ret   z   ; no code -- nothing to do
280   push  ix
282   ld    (.codelen),de
283   ld    (.codestart),hl
285   ; calculate original PC
286   ld    hl,(BZ80ASM.PC)
287   or    a
288   sbc   hl,de
289   ; print original PC
290   push  hl
291   ld    a,h
292   call  HEX
293   pop   hl
294   ld    a,l
295   call  HEXSP
297   ; print code bytes (if there are any)
298   ld    de,(.codelen)
299   ld    a,d
300   or    a
301   jr    nz,.nocode
302   ; do not print code if more than 4 bytes (long strings and dbs)
303   or    e
304   jr    z,.nocode
305   ; do not print code if more than 4 bytes (long strings and dbs)
306   cp    5
307   jr    nc,.nocode
309   ; print hex bytes
310   ld    hl,(.codestart)
311 .cdumploop:
312   ld    a,(hl)
313   call  HEXSP
314   inc   hl
315   dec   e
316   jr    nz,.cdumploop
317   ; align printed code
318   ld    a,(.codelen)
319 .alignloop:
320   cp    a,4
321   jr    nc,.aligndone
322   ld    e,a
323   ld    a,32
324   call  EMIT
325   ld    a,32
326   call  EMIT
327   ld    a,32
328   call  EMIT
329   ld    a,e
330   inc   a
331   jr    .alignloop
332 .aligndone:
334 .nocode:
335   ; print source line, from BC to IY (exclusive)
336   ; calculate string length
337   push  iy
338   pop   hl
339   or    a
340   sbc   hl,bc
341   jr    z,.notextline
342 .textloop:
343   ld    a,(bc)
344   call  EMIT
345   inc   bc
346   dec   hl
347   ld    a,h
348   or    l
349   jr    nz,.textloop
350 .notextline:
351   ; print final CR
352   ld    a,13
353   call  EMIT
355   pop   ix
356   ret
358 .codelen: defw 0
359 .codestart: defw 0
362 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
364 ;; print byte in hex with the trailing space
366 HEXSP:
367   call  HEX
368   ld    a,' '
369   jr    OUTCH1
372 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
374 ;; print byte in hex
376 HEX:
377   push  af
378   rrca
379   rrca
380   rrca
381   rrca
382   call  HEXOUT
383   pop   af
384 HEXOUT:
385   and   0FH
386   add   a,90H
387   daa
388   adc   a,40H
389   daa
390 OUTCH1:
391   jp    EMIT
394 LABMAN_FIRST_LABEL: defw $+2