zasm: add multiplication expressions
This commit is contained in:
parent
157ac03e25
commit
cdb6cce914
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
36
tools/tests/unit/test_util_z.asm
Normal file
36
tools/tests/unit/test_util_z.asm
Normal 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
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user