diff --git a/apps/zasm/directive.asm b/apps/zasm/directive.asm index 34f7edb..e25ab4d 100644 --- a/apps/zasm/directive.asm +++ b/apps/zasm/directive.asm @@ -122,6 +122,12 @@ handleDW: handleEQU: call zasmIsLocalPass ; Are we in local pass? Then ignore all .equ. jr z, .skip ; they mess up duplicate symbol detection. + ; We register constants on both first and second pass for one little + ; reason: .org. Normally, we'd register constants on second pass only + ; so that we have values for forward label references, but we need .org + ; to be effective during the first pass and .org needs to support + ; expressions. So, we double-parse .equ, clearing the const registry + ; before the second pass. push hl push de push bc diff --git a/apps/zasm/main.asm b/apps/zasm/main.asm index 8baa671..d19bb99 100644 --- a/apps/zasm/main.asm +++ b/apps/zasm/main.asm @@ -64,6 +64,10 @@ zasmMain: call ioPrintLN xor a ld (ZASM_FIRST_PASS), a + ; before parsing the file for the second pass, let's clear the const + ; registry. See comment in handleEQU. + ld ix, SYM_CONST_REGISTRY + call symClear call zasmParseFile .end: jp ioLineNo ; --> HL, --> DE, returns @@ -209,9 +213,8 @@ _beginLocalPass: ; Set local pass ld (ZASM_LOCAL_PASS), a ; Empty local label registry - xor a - ld (SYM_LOC_NAMES), a - ret + ld ix, SYM_LOCAL_REGISTRY + jp symClear _endLocalPass: diff --git a/apps/zasm/symbol.asm b/apps/zasm/symbol.asm index 4400347..ed00f99 100644 --- a/apps/zasm/symbol.asm +++ b/apps/zasm/symbol.asm @@ -169,7 +169,7 @@ symRegister: push de ; --> lvl 2. it's our value. call _symFind - jr z, .alreadyThere + jr z, .duplicateError ; First, let's get our strlen @@ -223,32 +223,6 @@ symRegister: pop hl ; <-- lvl 1 ret -.alreadyThere: - ; We are in a tricky situation with regards to our handling of the - ; duplicate symbol error. Normally, it should be straightforward: We - ; only register labels during first pass and evaluate constants during - ; the second. Easy. - ; We can *almost* do that... but we have ".org". .org affects label - ; values and supports expressions, which means that we have to evaluate - ; constants during first pass. But because we can possibly have forward - ; references in ".equ", some constants are going to have a bad value. - ; Therefore, we really can't evaluate all constants during the first - ; pass. - ; With this situation, how do you manage detection of duplicate symbols? - ; By limiting the "duplicate error" condition to the first pass. During, - ; first pass, sure, we don't have our proper values, but we have all our - ; symbol names. So, if we end up in .alreadyThere during first pass, - ; then it's an error condition. If it's not first pass, then we need - ; to update our value. - - call zasmIsFirstPass - jr z, .duplicateError - ; Second pass. Don't error out, just update value, which DE points to. - pop hl ; <-- lvl 2, the value to register - call writeHLinDE - pop hl ; <-- lvl 1 - cp a ; ensure Z - ret .duplicateError: pop de ; <-- lvl 2 pop hl ; <-- lvl 1 @@ -321,3 +295,15 @@ symFindVal: .end: pop ix ret + +; Clear registry at IX +symClear: + push af + push hl + ld l, (ix) + ld h, (ix+1) + xor a + ld (hl), a + pop hl + pop af + ret