diff --git a/apps/lib/parse.asm b/apps/lib/parse.asm index 103c005..9536379 100644 --- a/apps/lib/parse.asm +++ b/apps/lib/parse.asm @@ -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: diff --git a/apps/zasm/main.asm b/apps/zasm/main.asm index 02a1a72..59e3f31 100644 --- a/apps/zasm/main.asm +++ b/apps/zasm/main.asm @@ -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 diff --git a/recipes/sms/romasm/glue.asm b/recipes/sms/romasm/glue.asm index b583e48..dea11b8 100644 --- a/recipes/sms/romasm/glue.asm +++ b/recipes/sms/romasm/glue.asm @@ -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-$ diff --git a/recipes/sms/romasm/user.h b/recipes/sms/romasm/user.h index 5d7ff7b..ff4456b 100644 --- a/recipes/sms/romasm/user.h +++ b/recipes/sms/romasm/user.h @@ -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 diff --git a/tools/tests/unit/test_parse.asm b/tools/tests/unit/test_lib_parse.asm similarity index 71% rename from tools/tests/unit/test_parse.asm rename to tools/tests/unit/test_lib_parse.asm index ae77408..788c01e 100644 --- a/tools/tests/unit/test_parse.asm +++ b/tools/tests/unit/test_lib_parse.asm @@ -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