diff --git a/src/int_to_string.asm b/src/int_to_string.asm index ceb166f..567c609 100644 --- a/src/int_to_string.asm +++ b/src/int_to_string.asm @@ -17,6 +17,8 @@ cmp r4, 8 je oct cmp r4, 16 je hex +cmp r4, 10 +jmp dec mov flags, errno.INTTOSTR_BAD_BASE jmp r13 @@ -52,7 +54,7 @@ lsr r5, r1, r4 ; Select bit and advance counter and r5, r5, 1 sub r4, r4, 1 -cmp r4, 0 ; Start printing if last bit ... +cmp r4, zr ; Start printing if last bit ... jl bin_print cmp r5, zr ; .. or if nonzero je bin_find_one @@ -65,7 +67,7 @@ bin_print: add r5, r5, 0x30 ; '0' ; Add digit to buffer store_8 [r2], r5 add r2, r2, 1 -cmp r4, 0 ; Done if last bit +cmp r4, zr ; Done if last bit jl done lsr r5, r1, r4 ; Select bit and advance counter and r5, r5, 1 @@ -94,7 +96,7 @@ and r5, r5, 7 sub r4, r4, 3 sub r6, r6, 1 -cmp r4, 0 ; Start printing if last bit ... +cmp r4, zr ; Start printing if last bit ... jl oct_print cmp r5, zr ; .. or if nonzero je oct_find_one @@ -106,7 +108,7 @@ oct_print: add r5, r5, 0x30 ; '0' ; Add digit to buffer store_8 [r2], r5 add r2, r2, 1 -cmp r4, 0 ; Done if last bit +cmp r4, zr ; Done if last bit jl done lsr r5, r1, r4 ; Select bit and advance counter and r5, r5, 7 @@ -132,7 +134,7 @@ lsr r5, r1, r4 ; Select bit and advance counter and r5, r5, 0xF sub r4, r4, 4 -cmp r4, 0 ; Start printing if last bit ... +cmp r4, zr ; Start printing if last bit ... jl hex_print cmp r5, zr ; .. or if nonzero je hex_find_one @@ -150,9 +152,88 @@ add r5, r5, 0x07 ; 'A' - '0' - 10 hex_no_letter: store_8 [r2], r5 add r2, r2, 1 -cmp r4, 0 ; Done if last bit +cmp r4, zr ; Done if last bit jl done lsr r5, r1, r4 ; Select bit and advance counter and r5, r5, 0xF sub r4, r4, 4 jmp hex_print + +; Convert integer to decimal string +; Arguments: +; r1 - Integer +; r2 - Start of buffer +; r3 - Buffer length +; Result: +; none +; Clobbers: +; flags +; r4, r5 +pub dec: +mov r4, 0x5F5 +lsl r4, r4, 16 +add r4, r4, 0xE100 ; 100 million; 8 digits +cmp r1, r4 +jl dec_small +; TODO large + + +; Small numbers have at least most 8 digits, thus their BCD form fits in +; one register. Bit 26 is the highest which can be set. +; +; Utilizes double dabble +; r4, r5 are loop counters +; +; for( r4 = 24 ; r4 >= 0 ; r4-- ) +; for( r5 = r4 ; r5 <= 28 ; r5+= 4 ) +; if( ((r1 >> r5) & 0xF) >= 5 ) +; r1 += 3 << r5 +dec_small: +mov r4, 24 +dec_small_dabble_outer: +mov r5, r4 +dec_small_dabble_inner: +lsr flags, r1, r5 +and flags, flags, 0xF +cmp flags, 5 +jl dec_small_dabble_noinc +mov flags, 3 +lsl flags, flags, r5 +add r1, r1, flags +dec_small_dabble_noinc: +add r5, r5, 4 +cmp r5, 28 +jl dec_small_dabble_inner +sub r4, r4, 1 +cmp r4, zr +jg dec_small_dabble_outer + +; Print the BCD in r1 +; r4 is a counter +; r5 is the output character +mov r4, 28 +dec_find_one: +lsr r5, r1, r4 ; Select bit and advance counter +and r5, r5, 0xF +sub r4, r4, 4 + +cmp r4, zr ; Start printing if last bit ... +jl dec_print +cmp r5, zr ; .. or if nonzero +je dec_find_one + +lsr flags, r5, 2 ; Check buffer size +add flags, flags, 3 +cmp flags, r3 +ja badbuffer + +dec_print: +add r5, r5, 0x30 ; '0' ; Add digit to buffer +store_8 [r2], r5 +add r2, r2, 1 +cmp r4, zr ; Done if last bit +jl done +lsr r5, r1, r4 ; Select bit and advance counter +and r5, r5, 0xF +sub r4, r4, 4 +jmp dec_print diff --git a/tests/int_to_string_test.asm b/tests/int_to_string_test.asm index e9b76cd..ecac19b 100644 --- a/tests/int_to_string_test.asm +++ b/tests/int_to_string_test.asm @@ -52,7 +52,10 @@ tests: @0x201c0 U32 0x32fF6 U8 16 "32FF6\0" @0x20200 U32 0xdeadbeef U8 16 "DEADBEEF\0" @0x20240 U32 0xFFFFFFFF U8 16 "FFFFFFFF\0" -@0x20280 +@0x20280 U32 0 U8 10 "0\0" +@0x202c0 U32 42069 U8 10 "42069\0" +@0x20300 U32 12345678 U8 10 "12345678\0" +@0x20340 end_of_tests: scratch: U1024 0