1
0
mirror of https://github.com/hsoft/collapseos.git synced 2024-12-25 04:48:06 +11:00

zasm: add support for local labels

This commit is contained in:
Virgil Dupras 2019-05-13 20:23:10 -04:00
parent 17dbee6a49
commit 2de69ee7cd
3 changed files with 93 additions and 6 deletions

View File

@ -56,12 +56,16 @@ jp zasmMain
; Read file through blockdev ID in H and outputs its upcodes through blockdev
; ID in L.
zasmMain:
; Init I/O
ld a, h
ld de, IO_IN_GETC
call JUMP_BLKSEL
ld a, l
ld de, IO_OUT_GETC
call JUMP_BLKSEL
; Init modules
call symInit
; First pass
ld a, 1
ld (ZASM_FIRST_PASS), a
@ -155,14 +159,25 @@ parseLine:
djnz .loopDirec
jr .success
.label:
call zasmIsFirstPass
jr nz, .success ; not in first pass? nothing to do
; The string in (scratchpad) is a label with its trailing ':' removed.
ld hl, scratchpad
call zasmIsFirstPass
jr z, .registerLabel ; When we encounter a label in the first
; pass, we register it in the symbol
; list
; When we're not in the first pass, we set the context (if label is not
; local) to that label.
call symIsLabelLocal
jr z, .success ; local? nothing to do.
call symSetContext
jr z, .success
; NZ? this means that (HL) couldn't be found in symbol list. Weird
jr .error
.registerLabel:
ld de, (curOutputOffset)
call symRegister
jr .success
jr nz, .error
; continue to .success
.success:
xor a ; ensure Z
jr .end

View File

@ -29,7 +29,14 @@
; index of the name, then go get the value at that index in SYM_VALUES.
.equ SYM_NAMES SYM_VALUES+(SYM_MAXCOUNT*2)
.equ SYM_RAMEND SYM_NAMES+SYM_BUFSIZE
; Index of the symbol found during the last symSetContext call
.equ SYM_CONTEXT_IDX SYM_NAMES+SYM_BUFSIZE
; Pointer, in the SYM_NAMES buffer, of the string found during the last
; symSetContext call
.equ SYM_CONTEXT_PTR SYM_CONTEXT_IDX+1
.equ SYM_RAMEND SYM_CONTEXT_PTR+2
; *** Code ***
@ -52,6 +59,20 @@ _symNext:
cp a ; ensure Z
ret
symInit:
xor a
ld (SYM_NAMES), a
ld (SYM_CONTEXT_IDX), a
ld hl, SYM_CONTEXT_PTR
ld (SYM_CONTEXT_PTR), hl
ret
; Sets Z according to whether label in (HL) is local (starts with a dot)
symIsLabelLocal:
ld a, '.'
cp (hl)
ret
; Place HL at the end of SYM_NAMES end (that is, at the point where we have two
; consecutive null chars. We return the index of that new name in A.
; If we're within bounds, Z is set, otherwise unset.
@ -148,6 +169,12 @@ symRegister:
; If we find something, Z is set, otherwise unset.
symFind:
push hl
call _symFind
pop hl
ret
; Same as symFind, but leaks HL
_symFind:
push bc
push de
@ -155,10 +182,21 @@ symFind:
call strlen
ld c, a ; let's save that
call symIsLabelLocal ; save Z for after the 3 next lines, which
; doesn't touch flags. We need to call this now
; before we lose HL.
ex hl, de ; it's easier if HL is haystack and DE is
; needle.
ld b, 0
ld hl, SYM_NAMES
jr nz, .loop ; not local? jump right to loop
; local? then we need to adjust B and HL
ld hl, (SYM_CONTEXT_PTR)
ld a, (SYM_CONTEXT_IDX)
ld b, a
xor a
sub b
ld b, a
.loop:
ld a, c ; recall strlen
call JUMP_STRNCMP
@ -179,7 +217,6 @@ symFind:
.end:
pop de
pop bc
pop hl
ret
; Return value associated with symbol index A into DE
@ -194,3 +231,18 @@ symGetVal:
ld d, (hl)
pop hl
ret
; Find symbol name (HL) in the symbol list and set SYM_CONTEXT_* accordingly.
; When symFind will be called with a symbol name starting with a '.', the search
; will begin at that context instead of the beginning of the register.
; Sets Z if symbol is found, unsets it if not.
symSetContext:
push hl
call _symFind
jr nz, .end ; Z already unset
ld (SYM_CONTEXT_IDX), a
ld (SYM_CONTEXT_PTR), hl
; Z already set
.end:
pop hl
ret

20
apps/zasm/tests/test3.asm Normal file
View File

@ -0,0 +1,20 @@
; test local labels
addDE:
push af
add a, e
jr nc, .end ; no carry? skip inc
inc d
.end:
ld e, a
pop af
ret
addHL:
push af
add a, l
jr nc, .end ; no carry? skip inc
inc h
.end:
ld l, a
pop af
ret