Post Undeleted by Felix Palmen
2 added 5 characters in body
source | link
A0 09 F3 FB B1 FB C9 5B 90 07 A9 30 91 FB 88 10 F1 C9 3A 90D0 04 A9 41 91 FB 60
; function to increment base 36 number as 10 character string
;
; input:
;   $fb/$fc: address of string to increment
; clobbers:
;   A, Y
 .inc36:
A0 09       LDY #$09            ; start at last character
 .loop:
F3 FB       ISB ($FB),Y         ; increment character ("illegal" opcode)
B1 FB       LDA ($FB),Y         ; load incremented character
C9 5B       CMP #$5B            ; > 'z' ?
90 07       BCC .checkgap       ; no, check for gap between numbers and letters
A9 30       LDA #$30            ; load '0'
91 FB       STA ($FB),Y         ; and store in string
88          DEY                 ; previous position
10 F1       BPL .loop           ; and loop
 .checkgap:
C9 3A       CMP #$3A            ; >== '9' + 1 ?
90D0 04       BCCBNE .done           ; done if not
A9 41       LDA #$41            ; load 'a'
91 FB       STA ($FB),Y         ; and store in string
 .done:
60          RTS

Online demoOnline demo

A0 09 F3 FB B1 FB C9 5B 90 07 A9 30 91 FB 88 10 F1 C9 3A 90 04 A9 41 91 FB 60
; function to increment base 36 number as 10 character string
;
; input:
;   $fb/$fc: address of string to increment
; clobbers:
;   A, Y
 .inc36:
A0 09       LDY #$09            ; start at last character
 .loop:
F3 FB       ISB ($FB),Y         ; increment character ("illegal" opcode)
B1 FB       LDA ($FB),Y         ; load incremented character
C9 5B       CMP #$5B            ; > 'z' ?
90 07       BCC .checkgap       ; no, check for gap between numbers and letters
A9 30       LDA #$30            ; load '0'
91 FB       STA ($FB),Y         ; and store in string
88          DEY                 ; previous position
10 F1       BPL .loop           ; and loop
 .checkgap:
C9 3A       CMP #$3A            ; > '9' ?
90 04       BCC .done           ; done if not
A9 41       LDA #$41            ; load 'a'
91 FB       STA ($FB),Y         ; and store in string
 .done:
60          RTS

Online demo

A0 09 F3 FB B1 FB C9 5B 90 07 A9 30 91 FB 88 10 F1 C9 3A D0 04 A9 41 91 FB 60
; function to increment base 36 number as 10 character string
;
; input:
;   $fb/$fc: address of string to increment
; clobbers:
;   A, Y
 .inc36:
A0 09       LDY #$09            ; start at last character
 .loop:
F3 FB       ISB ($FB),Y         ; increment character ("illegal" opcode)
B1 FB       LDA ($FB),Y         ; load incremented character
C9 5B       CMP #$5B            ; > 'z' ?
90 07       BCC .checkgap       ; no, check for gap between numbers and letters
A9 30       LDA #$30            ; load '0'
91 FB       STA ($FB),Y         ; and store in string
88          DEY                 ; previous position
10 F1       BPL .loop           ; and loop
 .checkgap:
C9 3A       CMP #$3A            ; == '9' + 1 ?
D0 04       BNE .done           ; done if not
A9 41       LDA #$41            ; load 'a'
91 FB       STA ($FB),Y         ; and store in string
 .done:
60          RTS

Online demo

    Post Deleted by Felix Palmen
1
source | link

6502 (NMOS*) machine code routine, 26 bytes

A0 09 F3 FB B1 FB C9 5B 90 07 A9 30 91 FB 88 10 F1 C9 3A 90 04 A9 41 91 FB 60

*) uses an "illegal" opcode ISB/0xF3, works on all original NMOS 6502 chips, not on later CMOS variants.

Expects a pointer to a 10-character string in $fb/$fc which is expected to be a base-36 number. Increments this number in-place.

Doesn't do anything sensible on invalid input (like e.g. a shorter string) -- handles ZZZZZZZZZZ "correctly" by accident ;)

Commented disassembly

; function to increment base 36 number as 10 character string
;
; input:
;   $fb/$fc: address of string to increment
; clobbers:
;   A, Y
 .inc36:
A0 09       LDY #$09            ; start at last character
 .loop:
F3 FB       ISB ($FB),Y         ; increment character ("illegal" opcode)
B1 FB       LDA ($FB),Y         ; load incremented character
C9 5B       CMP #$5B            ; > 'z' ?
90 07       BCC .checkgap       ; no, check for gap between numbers and letters
A9 30       LDA #$30            ; load '0'
91 FB       STA ($FB),Y         ; and store in string
88          DEY                 ; previous position
10 F1       BPL .loop           ; and loop
 .checkgap:
C9 3A       CMP #$3A            ; > '9' ?
90 04       BCC .done           ; done if not
A9 41       LDA #$41            ; load 'a'
91 FB       STA ($FB),Y         ; and store in string
 .done:
60          RTS

Example C64 assembler program using the routine:

Online demo

screenshot

Code in ca65 syntax:

.import inc36   ; link with routine above

.segment "BHDR" ; BASIC header
                .word   $0801           ; load address
                .word   $080b           ; pointer next BASIC line
                .word   2018            ; line number
                .byte   $9e             ; BASIC token "SYS"
                .byte   "2061",$0,$0,$0 ; 2061 ($080d) and terminating 0 bytes

.bss
b36str:         .res    11

.data
prompt:         .byte   "> ", $0

.code
                lda     #<prompt        ; display prompt
                ldy     #>prompt
                jsr     $ab1e

                lda     #<b36str        ; read string into buffer
                ldy     #>b36str
                ldx     #$b
                jsr     readline

                lda     #<b36str        ; address of array to $fb/fc
                sta     $fb
                lda     #>b36str
                sta     $fc
                jsr     inc36           ; call incrementing function

                lda     #<b36str        ; output result
                ldy     #>b36str
                jmp     $ab1e

; read a line of input from keyboard, terminate it with 0
; expects pointer to input buffer in A/Y, buffer length in X
.proc readline
                dex
                stx     $fb
                sta     $fc
                sty     $fd
                ldy     #$0
                sty     $cc             ; enable cursor blinking
                sty     $fe             ; temporary for loop variable
getkey:         jsr     $f142           ; get character from keyboard
                beq     getkey
                sta     $2              ; save to temporary
                and     #$7f
                cmp     #$20            ; check for control character
                bcs     checkout        ; no -> check buffer size
                cmp     #$d             ; was it enter/return?
                beq     prepout         ; -> normal flow
                cmp     #$14            ; was it backspace/delete?
                bne     getkey          ; if not, get next char
                lda     $fe             ; check current index
                beq     getkey          ; zero -> backspace not possible
                bne     prepout         ; skip checking buffer size for bs
checkout:       lda     $fe             ; buffer index
                cmp     $fb             ; check against buffer size
                beq     getkey          ; if it would overflow, loop again
prepout:        sei                     ; no interrupts
                ldy     $d3             ; get current screen column
                lda     ($d1),y         ; and clear 
                and     #$7f            ;   cursor in
                sta     ($d1),y         ;   current row
output:         lda     $2              ; load character
                jsr     $e716           ;   and output
                ldx     $cf             ; check cursor phase
                beq     store           ; invisible -> to store
                ldy     $d3             ; get current screen column
                lda     ($d1),y         ; and show
                ora     #$80            ;   cursor in
                sta     ($d1),y         ;   current row
                lda     $2              ; load character
store:          cli                     ; enable interrupts
                cmp     #$14            ; was it backspace/delete?
                beq     backspace       ; to backspace handling code
                cmp     #$d             ; was it enter/return?
                beq     done            ; then we're done.
                ldy     $fe             ; load buffer index
                sta     ($fc),y         ; store character in buffer
                iny                     ; advance buffer index
                sty     $fe
                bne     getkey          ; not zero -> ok
done:           lda     #$0             ; terminate string in buffer with zero
                ldy     $fe             ; get buffer index
                sta     ($fc),y         ; store terminator in buffer
                sei                     ; no interrupts
                ldy     $d3             ; get current screen column
                lda     ($d1),y         ; and clear 
                and     #$7f            ;   cursor in
                sta     ($d1),y         ;   current row
                inc     $cc             ; disable cursor blinking
                cli                     ; enable interrupts
                rts                     ; return
backspace:      dec     $fe             ; decrement buffer index
                bcs     getkey          ; and get next key
.endproc