zasm: add multiplication expressions

This commit is contained in:
Virgil Dupras 2019-05-17 22:22:10 -04:00
parent 157ac03e25
commit cdb6cce914
5 changed files with 130 additions and 47 deletions

View File

@ -2,69 +2,85 @@
; We expect (HL) to be disposable: we mutate it to avoid having to make a copy. ; We expect (HL) to be disposable: we mutate it to avoid having to make a copy.
; Sets Z on success, unset on error. ; Sets Z on success, unset on error.
parseExpr: parseExpr:
push bc
push de push de
push hl push hl
ld a, '+' call _parseExpr
call findchar
jr z, .hasExpr
pop hl pop hl
push hl
ld a, '-'
call findchar
jr nz, .noExpr
ld c, '-'
jr .hasExpr
.hasPlus:
ld c, '+'
jr .hasExpr
.hasExpr:
; Alright, we have a +/ and we're pointing at it. Let's advance HL and
; recurse. But first, let's change this + into a null char. It will be
; handy later.
xor a
ld (hl), a ; + changed to \0
inc hl
pop de ; we pop out the HL we pushed earlier into DE
; That's our original beginning of string.
call _applyExprToHL
pop de pop de
pop bc
ret ret
.noExpr: _parseExpr:
pop hl ld a, '*'
pop de call _findAndSplit
pop bc jp z, _applyMult
ld a, '+'
call _findAndSplit
jp z, _applyPlus
ld a, '-'
call _findAndSplit
jp z, _applyMinus
jp parseNumberOrSymbol jp parseNumberOrSymbol
; Parse number or symbol in (DE) and expression in (HL) and apply operator ; Given a string in (HL) and a separator char in A, return a splitted string,
; specified in C to them. ; that is, the same (HL) string but with the found A char replaced by a null
_applyExprToHL: ; char. DE points to the second part of the split.
; Sets Z if found, unset if not found.
_findAndSplit:
push hl
call findchar
jr nz, .end ; nothing found
; Alright, we have our char and we're pointing at it. Let's replace it
; with a null char.
xor a
ld (hl), a ; + changed to \0
inc hl
ex de, hl ; DE now points to the second part of the split
cp a ; ensure Z
.end:
pop hl ; HL is back to the start
ret
; parse expression on the left (HL) and the right (DE) and put the results in
; DE (left) and IX (right)
_resolveLeftAndRight:
call parseExpr call parseExpr
ret nz ; return immediately if error ret nz ; return immediately if error
; Now we have parsed everything to the right and we have its result in ; Now we have parsed everything to the left and we have its result in
; IX. What we need to do now is parseNumberOrSymbol on (DE) and apply ; IX. What we need to do now is the same thing on (DE) and then apply
; operator. Let's save IX somewhere and parse this. ; the + operator. Let's save IX somewhere and parse this.
ex hl, de ex hl, de ; right expr now in HL
push ix push ix
pop de pop de ; numeric left expr result in DE
call parseNumberOrSymbol jp parseExpr
ret nz ; error
; Good! let's do the math! IX has our left part, DE has our right one. ; Parse expr in (HL) and expr in (DE) and apply + operator to both sides.
ld a, c ; restore operator ; Put result in IX.
cp '-' _applyPlus:
jr z, .sub call _resolveLeftAndRight
; addition ret nz
; Good! let's do the math! IX has our right part, DE has our left one.
add ix, de add ix, de
jr .end cp a ; ensure Z
.sub: ret
; Same as _applyPlus but with -
_applyMinus:
call _resolveLeftAndRight
ret nz
push ix push ix
pop hl pop hl
ex de, hl
sbc hl, de sbc hl, de
push hl push hl
pop ix pop ix
.end: cp a ; ensure Z
ret
_applyMult:
call _resolveLeftAndRight
ret nz
push ix \ pop bc
call multDEBC
push hl \ pop ix
cp a ; ensure Z cp a ; ensure Z
ret ret

View File

@ -210,3 +210,21 @@ findStringInList:
pop de pop de
cp a ; ensure Z cp a ; ensure Z
ret ret
; DE * BC -> DE (high) and HL (low)
multDEBC:
ld hl, 0
ld a, 0x10
.loop:
add hl, hl
rl e
rl d
jr nc, .noinc
add hl, bc
jr nc, .noinc
inc de
.noinc:
dec a
jr nz, .loop
ret

View File

@ -18,6 +18,7 @@ testNum: .db 1
s1: .db "2+2", 0 s1: .db "2+2", 0
s2: .db "0x4001+0x22", 0 s2: .db "0x4001+0x22", 0
s3: .db "FOO+BAR", 0 s3: .db "FOO+BAR", 0
s4: .db "3*3", 0
sFOO: .db "FOO", 0 sFOO: .db "FOO", 0
sBAR: .db "BAR", 0 sBAR: .db "BAR", 0
@ -70,6 +71,17 @@ test:
jp nz, fail jp nz, fail
call nexttest call nexttest
ld hl, s4
call parseExpr
jp nz, fail
ld a, ixh
or a
jp nz, fail
ld a, ixl
cp 9
jp nz, fail
call nexttest
; success ; success
xor a xor a
halt halt

View File

@ -0,0 +1,36 @@
jp test
#include "core.asm"
#include "parse.asm"
#include "zasm/util.asm"
testNum: .db 1
test:
ld hl, 0xffff
ld sp, hl
ld de, 12
ld bc, 4
call multDEBC
ld a, l
cp 48
jp nz, fail
call nexttest
; success
xor a
halt
nexttest:
ld a, (testNum)
inc a
ld (testNum), a
ret
fail:
ld a, (testNum)
halt

View File

@ -1,3 +1,4 @@
; test expressions ; test expressions
ld a, 'A'+3 ld a, 'A'+3
ld a, 'A'-0x20 ld a, 'A'-0x20
ld a, 8*5