Also, make parseHexadecimal "tail" (HL). Soon, all routines in lib/parse will do that, making the life of lib/expr easier.pull/85/head
@@ -22,42 +22,6 @@ parseHex: | |||
ret | |||
; Parses 2 characters of the string pointed to by HL and returns the numerical | |||
; value in A. If the second character is a "special" character (<0x21) we don't | |||
; error out: the result will be the one from the first char only. | |||
; HL is set to point to the last char of the pair. | |||
; | |||
; On success, the carry flag is reset. On error, it is set. | |||
parseHexPair: | |||
push bc | |||
ld a, (hl) | |||
call parseHex | |||
jr c, .end ; error? goto end, keeping the C flag on | |||
rla \ rla \ rla \ rla ; let's push this in MSB | |||
ld b, a | |||
inc hl | |||
ld a, (hl) | |||
cp 0x21 | |||
jr c, .single ; special char? single digit | |||
call parseHex | |||
jr c, .end ; error? | |||
or b ; join left-shifted + new. we're done! | |||
; C flag was set on parseHex and is necessarily clear at this point | |||
jr .end | |||
.single: | |||
; If we have a single digit, our result is already stored in B, but | |||
; we have to right-shift it back. | |||
ld a, b | |||
and 0xf0 | |||
rra \ rra \ rra \ rra | |||
dec hl | |||
.end: | |||
pop bc | |||
ret | |||
; Parse the decimal char at A and extract it's 0-9 numerical value. Put the | |||
; result in A. | |||
; | |||
@@ -142,40 +106,35 @@ parseDecimal: | |||
; Parse string at (HL) as a hexadecimal value without the "0x" prefix and | |||
; return value in DE. | |||
; HL is advanced to the character following the last successfully read char. | |||
; Sets Z on success. | |||
parseHexadecimal: | |||
push hl | |||
call strlen | |||
cp 3 | |||
jr c, .single | |||
cp 4 | |||
jr c, .doubleShort ; 0x123 | |||
cp 5 | |||
jr c, .double ; 0x1234 | |||
; too long, error | |||
jr .error | |||
.double: | |||
call parseHexPair | |||
jr c, .error | |||
inc hl ; now HL is on first char of next pair | |||
ld d, a | |||
jr .single | |||
.doubleShort: | |||
ld a, (hl) | |||
call parseHex | |||
jr c, .error | |||
inc hl ; now HL is on first char of next pair | |||
ld d, a | |||
.single: | |||
call parseHexPair | |||
jr c, .error | |||
jp c, unsetZ ; we need at least one char | |||
push bc | |||
ld de, 0 | |||
ld b, 0 | |||
.loop: | |||
; we push to B to verify overflow | |||
rl e \ rl d \ rl b | |||
rl e \ rl d \ rl b | |||
rl e \ rl d \ rl b | |||
rl e \ rl d \ rl b | |||
or e | |||
ld e, a | |||
cp a ; ensure Z | |||
jr .end | |||
.error: | |||
call unsetZ | |||
; did we overflow? | |||
ld a, b | |||
or a | |||
jr nz, .end ; overflow, NZ already set | |||
; next char | |||
inc hl | |||
ld a, (hl) | |||
call parseHex | |||
jr nc, .loop | |||
cp a ; ensure Z | |||
.end: | |||
pop hl | |||
pop bc | |||
ret | |||
; Parse string at (HL) as a binary value (010101) without the "0b" prefix and | |||
@@ -271,7 +230,9 @@ parseLiteral: | |||
ret ; Z already set | |||
.hex: | |||
push hl | |||
call parseHexadecimal | |||
pop hl | |||
jr .hexOrBinEnd | |||
.bin: | |||
@@ -25,30 +25,32 @@ | |||
zasmMain: | |||
; Parse args in (HL) | |||
; blkdev in | |||
call parseHexPair ; --> A | |||
jr c, .badargs | |||
call parseHexadecimal ; --> DE | |||
jr nz, .badargs | |||
ld a, e | |||
ld de, IO_IN_BLK | |||
call blkSel | |||
inc hl ; char following last hex char | |||
; blkdev in | |||
call rdWS | |||
jr nz, .badargs | |||
call parseHexPair ; --> A | |||
jr c, .badargs | |||
call parseHexadecimal ; --> DE | |||
jr nz, .badargs | |||
ld a, e | |||
ld de, IO_OUT_BLK | |||
call blkSel | |||
inc hl ; char following last hex char | |||
; .org high byte | |||
ld e, 0 ; in case we .skipOrgSet | |||
call rdWS | |||
jr nz, .skipOrgSet ; no org argument | |||
call parseHexPair ; --> A | |||
jr c, .badargs | |||
call parseHexadecimal ; --> DE | |||
jr nz, .badargs | |||
.skipOrgSet: | |||
; Init .org with value of E | |||
; Save in "@" too | |||
ld a, e | |||
ld (ZASM_ORG+1), a ; high byte of .org | |||
ld (DIREC_LASTVAL+1), a | |||
xor a | |||
@@ -16,7 +16,6 @@ | |||
jp upcase | |||
jp findchar | |||
jp parseHex | |||
jp parseHexPair | |||
jp blkSel | |||
jp blkSet | |||
jp fsFindFN | |||
@@ -145,9 +144,9 @@ basFindCmdExtra: | |||
jp basPgmHook | |||
.mycmds: | |||
.db "ed", 0 | |||
.dw 0x1e00 | |||
.dw 0x1f00 | |||
.db "zasm", 0 | |||
.dw 0x2300 | |||
.dw 0x2400 | |||
.db 0xff | |||
f0GetB: | |||
@@ -166,13 +165,13 @@ f1PutB: | |||
ld ix, FS_HANDLES+FS_HANDLE_SIZE | |||
jp fsPutB | |||
; last time I checked, PC at this point was 0x1df8. Let's give us a nice margin | |||
; last time I checked, PC at this point was 0x1e92. Let's give us a nice margin | |||
; for the start of ed. | |||
.fill 0x1e00-$ | |||
.fill 0x1f00-$ | |||
.bin "ed.bin" | |||
; Last check: 0x22dd | |||
.fill 0x2300-$ | |||
; Last check: 0x23b0 | |||
.fill 0x2400-$ | |||
.bin "zasm.bin" | |||
.fill 0x7ff0-$ | |||
@@ -14,7 +14,6 @@ | |||
.equ upcase @+3 | |||
.equ findchar @+3 | |||
.equ parseHex @+3 | |||
.equ parseHexPair @+3 | |||
.equ blkSel @+3 | |||
.equ blkSet @+3 | |||
.equ fsFindFN @+3 | |||
@@ -13,7 +13,7 @@ test: | |||
ld sp, 0xffff | |||
call testParseHex | |||
call testParseHexPair | |||
call testParseHexadecimal | |||
; success | |||
xor a | |||
@@ -40,24 +40,30 @@ testParseHex: | |||
call nexttest | |||
ret | |||
testParseHexPair: | |||
testParseHexadecimal: | |||
ld hl, .s99 | |||
call parseHexPair | |||
jp c, fail | |||
call parseHexadecimal | |||
jp nz, fail | |||
ld a, e | |||
cp 0x99 | |||
jp nz, fail | |||
call nexttest | |||
ld hl, .saB | |||
call parseHexPair | |||
jp c, fail | |||
call parseHexadecimal | |||
jp nz, fail | |||
ld a, e | |||
cp 0xab | |||
jp nz, fail | |||
call nexttest | |||
; The string "Foo" will not cause a failure. We will parse up to "o" | |||
; and then stop. | |||
ld hl, .sFoo | |||
call parseHexPair | |||
jp nc, fail | |||
call parseHexadecimal | |||
jp nz, fail | |||
ld a, e | |||
cp 0xf | |||
call nexttest | |||
ret | |||