From 9f6241b36105f19c74015822e8e96452e23c7f43 Mon Sep 17 00:00:00 2001 From: Ketmar Dark Date: Sun, 16 Aug 2020 01:00:53 +0300 Subject: [PATCH] more fixes; implemented two-pass assembling to resolve all labels (this is just an example of how you can do it) --- bzasm80.zas | 4 +-- labman.zas | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- main.zas | 10 ++++++- output.zas | 2 +- 4 files changed, 100 insertions(+), 7 deletions(-) diff --git a/bzasm80.zas b/bzasm80.zas index 995b69a..24ec246 100644 --- a/bzasm80.zas +++ b/bzasm80.zas @@ -119,8 +119,8 @@ EXPR_ERR_DIVISION_BY_ZERO equ 4 ;; jp BZ80ASM.PARSE_EXPR_ERROR_A EXPR_ERR_JR_TOO_FAR equ 5 -;; this "unknown label" error can be used by label manager -EXPR_ERR_UNKNOWN_LABEL equ 6 +;; this "unresolved label" error can be used by label manager +EXPR_ERR_UNRESOLVED_LABEL equ 6 ;; this error can be used by label manager if it cannot parse a label EXPR_ERR_INVALID_LABEL_NAME equ 7 ;; this error can be used by label manager diff --git a/labman.zas b/labman.zas index 2a36d20..1a6e0f6 100644 --- a/labman.zas +++ b/labman.zas @@ -1,11 +1,54 @@ -; label manager +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; label manager +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; reset all labels, reinit label manager +;; HL,AF: dead +;; LABMAN_INIT: + xor a ld hl,(LABMAN_FIRST_LABEL) - ld (hl),0 + ld (hl),a + ld (LABMAN_PASS),a + ret + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; increment pass counter, perform pass bookkeeping +;; calling this more than once is UB +;; returns current pass in A +;; HL, flags: dead +;; +LABMAN_ADVANCE_PASS: + ld hl,LABMAN_PASS + inc (hl) + ld a,(hl) ret + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +LABMAN_PASS: defb 0 + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; data buffer format: +;; +;; label-name ; end of table if the first byte is zero +;; defw value +;; defb flags +;; +;; name has highest bit of the last char set +;; flags are used for forward references +;; #00: fully resolved label +;; #FF: forward-referenced label (it was used, but the value is unknown yet) +;; at the end of the first pass, any labels with #FF are undefined +;; on the second pass, no new labels are created +;; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; find a label @@ -79,10 +122,12 @@ labman_find: ;; IY: text input buffer ;; OUT: ;; IY: text input buffer after the label +;; CARRY SET on error ;; LABMAN_DEFINE_LABEL: ld a,0 ld (LABMAN_NEW_LABEL_FLAG),a + ld (.orig_tib),iy call labman_find jr c,LABMAN_FIND_LABEL_create_new_label ; existing label: check if it is a forward reference @@ -91,11 +136,19 @@ LABMAN_DEFINE_LABEL: ld a,(hl) inc a jr z,.fwd_label + ; on second and other passes, this is not an error + ld a,(LABMAN_PASS) + or a + jr nz,.skip_label ld a,BZ80ASM.EXPR_ERR_DUPLICATE_LABEL jp BZ80ASM.PARSE_EXPR_ERROR_A .fwd_label: ; reset "forward" flag ld (hl),a + ; there should be no unresolved labels on the second pass + ld a,(LABMAN_PASS) + or a + jr nz,.broken_code ; set value (PC) dec hl dec hl @@ -104,6 +157,31 @@ LABMAN_DEFINE_LABEL: inc hl ld (hl),d ret +.broken_code: + ld iy,0 ; patched above +.orig_tib equ $-2 + call .print_label + ld a,13 + call EMIT + ld a,BZ80ASM.EXPR_ERR_UNRESOLVED_LABEL + jp BZ80ASM.PARSE_EXPR_ERROR_A +.skip_label: + ; assume that label name is good + ld a,(iy) + inc iy + call isIdChar + jr nc,.skip_label + ccf ; reset carry + ret + +.print_label: + ld a,(iy) + call EMIT + ld a,(iy) + inc iy + call isIdChar + jr nc,.print_label + ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -134,6 +212,10 @@ LABMAN_FIND_LABEL: @LABMAN_FIND_LABEL_create_new_label: .create_new_label: + ; allowed only on the first pass + ld a,(LABMAN_PASS) + or a + jr nz,.broken_code ld a,(iy) call isAlpha jr nc,.good_start @@ -144,6 +226,9 @@ LABMAN_FIND_LABEL: ret nz ld a,EXPR_ERR_NO_LOCAL_LABELS_YET jp BZ80ASM.PARSE_EXPR_ERROR_A +.broken_code: + ld a,BZ80ASM.EXPR_ERR_BAD_SYNTAX + jp BZ80ASM.PARSE_EXPR_ERROR_A .good_start: push hl ; we'll use this later to print a name @@ -171,7 +256,7 @@ LABMAN_FIND_LABEL: inc hl ; set "forward reference" flag ld (hl),#FF -@LABMAN_NEW_LABEL_FLAG equ $01 +@LABMAN_NEW_LABEL_FLAG equ $-1 ; put zero to mark new label area end inc hl ld (hl),0 diff --git a/main.zas b/main.zas index 24a6139..5641c31 100644 --- a/main.zas +++ b/main.zas @@ -45,8 +45,11 @@ main: call LABMAN_INIT di + + ; two-pass assemling +asm_another_pass: ld ix,asmdest - ;ld ix,(BZ80ASM.PC) + ld (BZ80ASM.PC),ix ld iy,strbuf asmmore: @@ -105,6 +108,11 @@ doasm_done_line: jr nz,asmmore .bufferdone: + ; advance pass + call LABMAN_ADVANCE_PASS + cp 2 + jr c,asm_another_pass + ; now disasm it ld hl,msg_disasm call printstrnl diff --git a/output.zas b/output.zas index 41e3eea..3e3ce31 100644 --- a/output.zas +++ b/output.zas @@ -40,7 +40,7 @@ errmsg_table: defx "')' expected" defx "division by 0" defx "relative jump dest too far" - defx "unknown label" + defx "unresolved label" defx "invalid label name" defx "duplicate label" defx "bad syntax" -- 2.11.4.GIT