gbdk-2020 | GameBoy Development Kit |
| download: https://git.y1.nz/archives/gbdk.tar.gz | |
| README | Files | Log | Refs | LICENSE |
commit 4524a3f0b514c2a6650eeb666447bc21ab12cb1c parent 6aeebafecc4695121242347ea7e8229dbe0843a4 Author: Phidias618 <126189685+Phidias618@users.noreply.github.com> Date: Mon, 13 Apr 2026 11:24:44 +0200 Optimization of uitoa() and itoa() for the sm83 port Diffstat:
| A | gbdk-lib/include/asm/mos6502/stdlib.h | 151 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | gbdk-lib/include/asm/sm83/stdlib.h | 151 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | gbdk-lib/include/asm/z80/stdlib.h | 151 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| M | gbdk-lib/include/stdlib.h | 156 | ++++++------------------------------------------------------------------------- |
| M | gbdk-lib/libc/asm/sm83/itoa.s | 304 | +++++++++++++++++++++++++++++++++++++------------------------------------------ |
5 files changed, 608 insertions(+), 305 deletions(-)
diff --git a/gbdk-lib/include/asm/mos6502/stdlib.h b/gbdk-lib/include/asm/mos6502/stdlib.h @@ -0,0 +1,151 @@ +/** file stdlib.h + 'Standard library' functions, for whatever that means. +*/ +#ifndef STDLIB_INCLUDE +#define STDLIB_INCLUDE + +#include <types.h> + +/** Causes normal program termination and the value of status is + returned to the parent. + All open streams are flushed and closed. +*/ +void exit(int status); + +#if 0 +/** Compatibility function. Not implemented. + */ +int getkey(void); +#endif + +/** Returns the absolute value of int __i__ + @param i Int to obtain absolute value of + + If i is negative, returns -i; else returns i. +*/ +int abs(int i); + + +/** Returns the absolute value of long int __num__ + + @param num Long integer to obtain absolute value of + */ +long labs(long num); + + +/** Converts an ASCII string to an int + + @param s String to convert to an int + + The string may be of the format + \code{.c} + [\s]*[+-][\d]+[\D]* + \endcode + i.e. any number of spaces, an optional + or -, then an + arbitrary number of digits. + + The result is undefined if the number doesnt fit in an int. + + Returns: Int value of string + */ +int atoi(const char *s); + + +/** Converts an ASCII string to a long. + @param s String to convert to an long int + @see atoi() + + Returns: Long int value of string + */ +long atol(const char *s); + +/** Converts an int into a base 10 ASCII string. + @param n Int to convert to a string + @param s String to store the converted number + @param radix Numerical base for converted number, ex: 10 is decimal base + (parameter is required but not utilized on Game Boy and Analogue Pocket) + + Can be used with @ref set_bkg_based_tiles() for printing if + the digit character tiles are not ascii-mapped. + + Returns: Pointer to converted string + */ +char *itoa(int n, char *s, unsigned char radix); + +/** Converts an unsigned int into a base 10 ASCII string. + @param n Unsigned Int to convert to a string + @param s String to store the converted number + @param radix Numerical base for converted number, ex: 10 is decimal base + (parameter is required but not utilized on Game Boy and Analogue Pocket) + + Can be used with @ref set_bkg_based_tiles() for printing if + the digit character tiles are not ascii-mapped. + + Returns: Pointer to converted string + */ +char *uitoa(unsigned int n, char *s, unsigned char radix); + +/** Converts a long into a base 10 ASCII string. + @param n Long int to convert to a string + @param s String to store the converted number + @param radix Numerical base for converted number, ex: 10 is decimal base + (parameter is required but not utilized on Game Boy and Analogue Pocket) + + Can be used with @ref set_bkg_based_tiles() for printing if + the digit character tiles are not ascii-mapped. + + Returns: Pointer to converted string + */ +char *ltoa(long n, char *s, unsigned char radix); + +/** Converts an unsigned long into a base 10 ASCII string. + @param n Unsigned Long Int to convert to a string + @param s String to store the converted number + @param radix Numerical base for converted number, ex: 10 is decimal base + (parameter is required but not utilized on Game Boy and Analogue Pocket) + + Can be used with @ref set_bkg_based_tiles() for printing if + the digit character tiles are not ascii-mapped. + + Returns: Pointer to converted string + */ +char *ultoa(unsigned long n, char *s, unsigned char radix); + + +/** Memory allocation functions + */ +void *calloc (size_t nmemb, size_t size); +void *malloc (size_t size); +void *realloc (void *ptr, size_t size); +#if __STDC_VERSION__ >= 201112L +inline void *aligned_alloc(size_t alignment, size_t size) +{ + (void)alignment; + return malloc(size); +} +#endif +extern void free (void * ptr); + +/* Searching and sorting utilities (ISO C11 7.22.5) */ +/** search a sorted array of __nmemb__ items + @param key Pointer to object that is the key for the search + @param base Pointer to first object in the array to search + @param nmemb Number of elements in the array + @param size Size in bytes of each element in the array + @param compar Function used to compare two elements of the array + + Returns: Pointer to array entry that matches the search key. + If key is not found, NULL is returned. +*/ +extern void *bsearch(const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *) REENTRANT); + + +/** Sort an array of __nmemb__ items + @param base Pointer to first object in the array to sort + @param nmemb Number of elements in the array + @param size Size in bytes of each element in the array + @param compar Function used to compare and sort two elements of the array +*/ +extern void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *) REENTRANT); + +#endif diff --git a/gbdk-lib/include/asm/sm83/stdlib.h b/gbdk-lib/include/asm/sm83/stdlib.h @@ -0,0 +1,151 @@ +/** file stdlib.h + 'Standard library' functions, for whatever that means. +*/ +#ifndef STDLIB_INCLUDE +#define STDLIB_INCLUDE + +#include <types.h> + +/** Causes normal program termination and the value of status is + returned to the parent. + All open streams are flushed and closed. +*/ +void exit(int status) OLDCALL; + +#if 0 +/** Compatibility function. Not implemented. + */ +int getkey(void) OLDCALL; +#endif + +/** Returns the absolute value of int __i__ + @param i Int to obtain absolute value of + + If i is negative, returns -i; else returns i. +*/ +int abs(int i); + + +/** Returns the absolute value of long int __num__ + + @param num Long integer to obtain absolute value of + */ +long labs(long num) OLDCALL; + + +/** Converts an ASCII string to an int + + @param s String to convert to an int + + The string may be of the format + \code{.c} + [\s]*[+-][\d]+[\D]* + \endcode + i.e. any number of spaces, an optional + or -, then an + arbitrary number of digits. + + The result is undefined if the number doesnt fit in an int. + + Returns: Int value of string + */ +int atoi(const char *s); + + +/** Converts an ASCII string to a long. + @param s String to convert to an long int + @see atoi() + + Returns: Long int value of string + */ +long atol(const char *s); + +/** Converts an int into a base 10 ASCII string. + @param n Int to convert to a string + @param s String to store the converted number + @param radix Numerical base for converted number, ex: 10 is decimal base + (parameter is required but not utilized on Game Boy and Analogue Pocket) + + Can be used with @ref set_bkg_based_tiles() for printing if + the digit character tiles are not ascii-mapped. + + Returns: Pointer to converted string + */ +char *itoa(int n, char *s, unsigned char radix); + +/** Converts an unsigned int into a base 10 ASCII string. + @param n Unsigned Int to convert to a string + @param s String to store the converted number + @param radix Numerical base for converted number, ex: 10 is decimal base + (parameter is required but not utilized on Game Boy and Analogue Pocket) + + Can be used with @ref set_bkg_based_tiles() for printing if + the digit character tiles are not ascii-mapped. + + Returns: Pointer to converted string + */ +char *uitoa(unsigned int n, char *s, unsigned char radix); + +/** Converts a long into a base 10 ASCII string. + @param n Long int to convert to a string + @param s String to store the converted number + @param radix Numerical base for converted number, ex: 10 is decimal base + (parameter is required but not utilized on Game Boy and Analogue Pocket) + + Can be used with @ref set_bkg_based_tiles() for printing if + the digit character tiles are not ascii-mapped. + + Returns: Pointer to converted string + */ +char *ltoa(long n, char *s, unsigned char radix) OLDCALL; + +/** Converts an unsigned long into a base 10 ASCII string. + @param n Unsigned Long Int to convert to a string + @param s String to store the converted number + @param radix Numerical base for converted number, ex: 10 is decimal base + (parameter is required but not utilized on Game Boy and Analogue Pocket) + + Can be used with @ref set_bkg_based_tiles() for printing if + the digit character tiles are not ascii-mapped. + + Returns: Pointer to converted string + */ +char *ultoa(unsigned long n, char *s, unsigned char radix) OLDCALL; + + +/** Memory allocation functions + */ +void *calloc (size_t nmemb, size_t size); +void *malloc (size_t size); +void *realloc (void *ptr, size_t size); +#if __STDC_VERSION__ >= 201112L +inline void *aligned_alloc(size_t alignment, size_t size) +{ + (void)alignment; + return malloc(size); +} +#endif +extern void free (void * ptr); + +/* Searching and sorting utilities (ISO C11 7.22.5) */ +/** search a sorted array of __nmemb__ items + @param key Pointer to object that is the key for the search + @param base Pointer to first object in the array to search + @param nmemb Number of elements in the array + @param size Size in bytes of each element in the array + @param compar Function used to compare two elements of the array + + Returns: Pointer to array entry that matches the search key. + If key is not found, NULL is returned. +*/ +extern void *bsearch(const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); + + +/** Sort an array of __nmemb__ items + @param base Pointer to first object in the array to sort + @param nmemb Number of elements in the array + @param size Size in bytes of each element in the array + @param compar Function used to compare and sort two elements of the array +*/ +extern void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); + +#endif diff --git a/gbdk-lib/include/asm/z80/stdlib.h b/gbdk-lib/include/asm/z80/stdlib.h @@ -0,0 +1,151 @@ +/** file stdlib.h + 'Standard library' functions, for whatever that means. +*/ +#ifndef STDLIB_INCLUDE +#define STDLIB_INCLUDE + +#include <types.h> + +/** Causes normal program termination and the value of status is + returned to the parent. + All open streams are flushed and closed. +*/ +void exit(int status) OLDCALL; + +#if 0 +/** Compatibility function. Not implemented. + */ +int getkey(void) OLDCALL; +#endif + +/** Returns the absolute value of int __i__ + @param i Int to obtain absolute value of + + If i is negative, returns -i; else returns i. +*/ +int abs(int i); + + +/** Returns the absolute value of long int __num__ + + @param num Long integer to obtain absolute value of + */ +long labs(long num) OLDCALL; + + +/** Converts an ASCII string to an int + + @param s String to convert to an int + + The string may be of the format + \code{.c} + [\s]*[+-][\d]+[\D]* + \endcode + i.e. any number of spaces, an optional + or -, then an + arbitrary number of digits. + + The result is undefined if the number doesnt fit in an int. + + Returns: Int value of string + */ +int atoi(const char *s); + + +/** Converts an ASCII string to a long. + @param s String to convert to an long int + @see atoi() + + Returns: Long int value of string + */ +long atol(const char *s); + +/** Converts an int into a base 10 ASCII string. + @param n Int to convert to a string + @param s String to store the converted number + @param radix Numerical base for converted number, ex: 10 is decimal base + (parameter is required but not utilized on Game Boy and Analogue Pocket) + + Can be used with @ref set_bkg_based_tiles() for printing if + the digit character tiles are not ascii-mapped. + + Returns: Pointer to converted string + */ +char *itoa(int n, char *s, unsigned char radix) OLDCALL; + +/** Converts an unsigned int into a base 10 ASCII string. + @param n Unsigned Int to convert to a string + @param s String to store the converted number + @param radix Numerical base for converted number, ex: 10 is decimal base + (parameter is required but not utilized on Game Boy and Analogue Pocket) + + Can be used with @ref set_bkg_based_tiles() for printing if + the digit character tiles are not ascii-mapped. + + Returns: Pointer to converted string + */ +char *uitoa(unsigned int n, char *s, unsigned char radix) OLDCALL; + +/** Converts a long into a base 10 ASCII string. + @param n Long int to convert to a string + @param s String to store the converted number + @param radix Numerical base for converted number, ex: 10 is decimal base + (parameter is required but not utilized on Game Boy and Analogue Pocket) + + Can be used with @ref set_bkg_based_tiles() for printing if + the digit character tiles are not ascii-mapped. + + Returns: Pointer to converted string + */ +char *ltoa(long n, char *s, unsigned char radix) OLDCALL; + +/** Converts an unsigned long into a base 10 ASCII string. + @param n Unsigned Long Int to convert to a string + @param s String to store the converted number + @param radix Numerical base for converted number, ex: 10 is decimal base + (parameter is required but not utilized on Game Boy and Analogue Pocket) + + Can be used with @ref set_bkg_based_tiles() for printing if + the digit character tiles are not ascii-mapped. + + Returns: Pointer to converted string + */ +char *ultoa(unsigned long n, char *s, unsigned char radix) OLDCALL; + + +/** Memory allocation functions + */ +void *calloc (size_t nmemb, size_t size); +void *malloc (size_t size); +void *realloc (void *ptr, size_t size); +#if __STDC_VERSION__ >= 201112L +inline void *aligned_alloc(size_t alignment, size_t size) +{ + (void)alignment; + return malloc(size); +} +#endif +extern void free (void * ptr); + +/* Searching and sorting utilities (ISO C11 7.22.5) */ +/** search a sorted array of __nmemb__ items + @param key Pointer to object that is the key for the search + @param base Pointer to first object in the array to search + @param nmemb Number of elements in the array + @param size Size in bytes of each element in the array + @param compar Function used to compare two elements of the array + + Returns: Pointer to array entry that matches the search key. + If key is not found, NULL is returned. +*/ +extern void *bsearch(const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); + + +/** Sort an array of __nmemb__ items + @param base Pointer to first object in the array to sort + @param nmemb Number of elements in the array + @param size Size in bytes of each element in the array + @param compar Function used to compare and sort two elements of the array +*/ +extern void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); + +#endif diff --git a/gbdk-lib/include/stdlib.h b/gbdk-lib/include/stdlib.h @@ -1,151 +1,17 @@ /** file stdlib.h 'Standard library' functions, for whatever that means. */ -#ifndef STDLIB_INCLUDE -#define STDLIB_INCLUDE - -#include <types.h> - -/** Causes normal program termination and the value of status is - returned to the parent. - All open streams are flushed and closed. -*/ -void exit(int status) OLDCALL; - -#if 0 -/** Compatibility function. Not implemented. - */ -int getkey(void) OLDCALL; -#endif - -/** Returns the absolute value of int __i__ - @param i Int to obtain absolute value of - - If i is negative, returns -i; else returns i. -*/ -int abs(int i); - - -/** Returns the absolute value of long int __num__ - - @param num Long integer to obtain absolute value of - */ -long labs(long num) OLDCALL; - - -/** Converts an ASCII string to an int - - @param s String to convert to an int - - The string may be of the format - \code{.c} - [\s]*[+-][\d]+[\D]* - \endcode - i.e. any number of spaces, an optional + or -, then an - arbitrary number of digits. - - The result is undefined if the number doesnt fit in an int. - - Returns: Int value of string - */ -int atoi(const char *s); - - -/** Converts an ASCII string to a long. - @param s String to convert to an long int - @see atoi() - - Returns: Long int value of string - */ -long atol(const char *s); - -/** Converts an int into a base 10 ASCII string. - @param n Int to convert to a string - @param s String to store the converted number - @param radix Numerical base for converted number, ex: 10 is decimal base - (parameter is required but not utilized on Game Boy and Analogue Pocket) - - Can be used with @ref set_bkg_based_tiles() for printing if - the digit character tiles are not ascii-mapped. - - Returns: Pointer to converted string - */ -char *itoa(int n, char *s, unsigned char radix) OLDCALL; - -/** Converts an unsigned int into a base 10 ASCII string. - @param n Unsigned Int to convert to a string - @param s String to store the converted number - @param radix Numerical base for converted number, ex: 10 is decimal base - (parameter is required but not utilized on Game Boy and Analogue Pocket) - - Can be used with @ref set_bkg_based_tiles() for printing if - the digit character tiles are not ascii-mapped. - - Returns: Pointer to converted string - */ -char *uitoa(unsigned int n, char *s, unsigned char radix) OLDCALL; - -/** Converts a long into a base 10 ASCII string. - @param n Long int to convert to a string - @param s String to store the converted number - @param radix Numerical base for converted number, ex: 10 is decimal base - (parameter is required but not utilized on Game Boy and Analogue Pocket) - - Can be used with @ref set_bkg_based_tiles() for printing if - the digit character tiles are not ascii-mapped. - - Returns: Pointer to converted string - */ -char *ltoa(long n, char *s, unsigned char radix) OLDCALL; - -/** Converts an unsigned long into a base 10 ASCII string. - @param n Unsigned Long Int to convert to a string - @param s String to store the converted number - @param radix Numerical base for converted number, ex: 10 is decimal base - (parameter is required but not utilized on Game Boy and Analogue Pocket) - - Can be used with @ref set_bkg_based_tiles() for printing if - the digit character tiles are not ascii-mapped. - - Returns: Pointer to converted string - */ -char *ultoa(unsigned long n, char *s, unsigned char radix) OLDCALL; - - -/** Memory allocation functions - */ -void *calloc (size_t nmemb, size_t size); -void *malloc (size_t size); -void *realloc (void *ptr, size_t size); -#if __STDC_VERSION__ >= 201112L -inline void *aligned_alloc(size_t alignment, size_t size) -{ - (void)alignment; - return malloc(size); -} +#ifndef STD_STDLIB_INCLUDE +#define STD_STDLIB_INCLUDE + +#if defined(__PORT_sm83) + #include <asm/sm83/stdlib.h> +#elif defined(__PORT_z80) + #include <asm/z80/stdlib.h> +#elif defined(__PORT_mos6502) + #include <asm/mos6502/stdlib.h> +#else + #error Unrecognized port #endif -extern void free (void * ptr); - -/* Searching and sorting utilities (ISO C11 7.22.5) */ -/** search a sorted array of __nmemb__ items - @param key Pointer to object that is the key for the search - @param base Pointer to first object in the array to search - @param nmemb Number of elements in the array - @param size Size in bytes of each element in the array - @param compar Function used to compare two elements of the array - - Returns: Pointer to array entry that matches the search key. - If key is not found, NULL is returned. -*/ -extern void *bsearch(const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *) REENTRANT); - - -/** Sort an array of __nmemb__ items - @param base Pointer to first object in the array to sort - @param nmemb Number of elements in the array - @param size Size in bytes of each element in the array - @param compar Function used to compare and sort two elements of the array -*/ -extern void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *) REENTRANT); #endif diff --git a/gbdk-lib/libc/asm/sm83/itoa.s b/gbdk-lib/libc/asm/sm83/itoa.s @@ -1,190 +1,174 @@ ;-------------------------------------------------------------------------- ; itoa.s ; -; Copyright (C) 2020, Tony Pavlov +; Copyright (c) 2026, Phidias618 ; -; This library is free software; you can redistribute it and/or modify it -; under the terms of the GNU General Public License as published by the -; Free Software Foundation; either version 2, or (at your option) any -; later version. -; -; This library is distributed in the hope that it will be useful, -; but WITHOUT ANY WARRANTY; without even the implied warranty of -; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -; GNU General Public License for more details. -; -; You should have received a copy of the GNU General Public License -; along with this library; see the file COPYING. If not, write to the -; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, -; MA 02110-1301, USA. -; -; As a special exception, if you link this library with other files, -; some of which are compiled with SDCC, to produce an executable, -; this library does not by itself cause the resulting executable to -; be covered by the GNU General Public License. This exception does -; not however invalidate any other reasons why the executable file -; might be covered by the GNU General Public License. ;-------------------------------------------------------------------------- .module itoa .area _HOME -_uitoa:: - push BC - lda HL, 4(SP) - ld A, (HL+) - ld E, A - ld A, (HL+) - ld D, A ; DE: uint - ld A, (HL+) - ld C, A - ld B, (HL) ; BC: dest - call .utoa - pop BC - ret _itoa:: - push BC - lda HL, 4(SP) - ld A, (HL+) - ld E, A - ld A, (HL+) - ld D, A ; DE: int - ld A, (HL+) - ld C, A - ld B, (HL) ; BC: dest - call .itoa - pop BC - ret - + pop hl ; get the return address + inc sp ; get rid of the unused radix argument + push hl ; put the return address back .itoa:: ; convert int into ascii - ld A, D - add A, A - jr NC, .utoa + bit 7, d + jr z, .utoa - rra ; DE = abs(DE) - cpl - ld D, A - ld A, E - cpl - ld E, A - inc DE + ; DE = -DE + xor a + sub e + ld e, a + sbc a + sub d + ld d, a - ld A, #'-' - ld (BC), A - inc BC + ld a, #'-' + ld (bc), A + inc bc call .utoa - dec DE + dec bc ret +_uitoa:: + pop hl ; get the return address + inc sp ; get rid of the unused radix argument + push hl ; put the return address back .utoa:: ; convert unsigned int into ascii - add SP, #-3 - lda HL, 2(SP) - - xor A ; clear value - ld (HL-), A - ld (HL-), A - ld (HL), A + ; input : + ; - de (x) : the 16 bit unsigned number to convert to ascii + ; - bc (dst) : the pointer to the destination string - push BC - ld B, #8 -1$: - sla E - rl D - - ld A, (HL) - adc A - daa - ld (HL+), A - ld A, (HL) - adc A - daa - ld (HL+), A - ld A, (HL) - adc A - daa - ld (HL-), A - dec HL + ld h, b + ld l, c - sla E - rl D - - ld A, (HL) - adc A - daa - ld (HL+), A - ld A, (HL) - adc A - daa - ld (HL+), A - ld A, (HL) - adc A - daa - ld (HL-), A - dec HL + push bc + ld bc, #10 + jr 4$ +0$: + push hl + + ; compute an approximation of x / 10 + ; by using the approximation 1/10 ~ 0.0001100110011 + + ld b, e + ld c, d - dec B - jr NZ, 1$ + ld l, e + ld h, d + xor a +.rept 3 + add hl, hl + adc a +.endm + ld e, h + ld d, a + + add hl, hl + adc a + ld l, h + ld h, a + add hl, de + + ld e, b + xor a + ld b, a + + add hl, bc + srl c + add hl, bc - pop BC - push BC + srl c + srl c + srl c + add hl, bc + srl c + add hl, bc + + ; computes an approximation of the remainder + ; by using the computed approximation of x / 10 + ; it will always be in the range [0; 75] + sub l + add a + add a + sub l + add a + add e ; e = x - 10 * hl - ld DE, #'0' - lda HL, 4(SP) - - ld A, (HL-) - and #0x0f - or A - jr Z, 3$ - add A, E - ld D, #1 ; make D nonzero - ld (BC), A - inc BC + ; fix both the quotient and the remainder of x / 10 + ; using the fact that the remainder should be less than 10 + cp #40 + jr c, 1$ + sub #40 + ld c, #4 + add hl, bc ; add hl, #4 +1$: + cp #20 + jr c, 2$ + sub #20 + ; this can *not* trigger an OAM corruption glitch + ; because hl is too small + inc hl + inc hl +2$: + ld c, #10 + cp c ; cp #10 + jr c, 3$ + sub c ; sub #10 + ; this can *not* trigger an OAM corruption glitch + ; because hl is too small + inc hl 3$: - ld A, (HL) - swap A - and #0x0f - add D - jr Z, 4$ - sub D - add A, E - ld D, #1 ; make D nonzero - ld (BC), A - inc BC + ; now a = x % 10 + ld d, h + ld e, l ; x = x / 10 + + pop hl + add #'0' + ld (hl+), a 4$: - ld A, (HL-) - and #0x0f - add D - jr Z, 5$ - sub D - add A, E - ld D, #1 ; make D nonzero - ld (BC), A - inc BC -5$: - ld A, (HL) - swap A - and #0x0f - add D - jr Z, 6$ - sub D - add A, E - ld (BC), A - inc BC -6$: - ld A, (HL) - and #0x0f - add A, E - ld (BC), A - inc BC - - xor A - ld (BC), A ; write trailing #0 + ld a, e + sub c ; sub #10 + ld a, d + sbc b ; sbc #0 - pop DE + jr nc, 0$ ; exit the loop if x is only one digit long + + ld a, e + add #'0' + ld (hl+), a + + xor a + ld (hl-), a ; store the terminator of the string + + pop bc ; bc = dst + + ; reverse the order of the string + ld a, l + sub c ; a = length-1 + ret z ; no need to reverse if length == 1 + cp #3 - add sp, #3 + ; swap 2 chars + ld d, (hl) + ld a, (bc) + ld (hl-), a + ld a, d + ld (bc), a + + ret c + inc bc - ret + ; swap 2 more chars + ld d, (hl) + ld a, (bc) + ld (hl-), a + ld a, d + ld (bc), a + + dec bc ; bc = dst + ret
This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.