Last active
February 26, 2019 20:23
-
-
Save neuro-sys/ac0d77844f374295bfb7d410a4542602 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; Description | |
; A number is input in computer then a new no should get | |
; printed by adding one to each of its digit. If you encounter a 9, | |
; insert a 10 (don't carry over, just shift things around). | |
; | |
; For example, 998 becomes 10109. | |
; | |
; Bonus | |
; This challenge is trivial to do if you map it to a string to | |
; iterate over the input, operate, and then cast it back. Instead, try | |
; doing it without casting it as a string at any point, keep it numeric | |
; (int, float if you need it) only. | |
bdos equ $5 | |
c_read equ $1 | |
c_write equ $2 | |
c_writestr equ $9 | |
org $100 | |
ld c, c_writestr | |
ld de, message | |
call bdos | |
call readinput | |
call inputtonum | |
call convertnum | |
call printnum | |
rst 0 ; return to ccp | |
; reads from keyboard and stores in buffer with $ff end marker | |
; quits after cr | |
readinput: ld hl, buffer | |
push hl ; save buffer pointer | |
nextchar: ld c, c_read | |
call bdos | |
cp 13 ; is cr? | |
jp z, readend | |
sub '0' ; get digit value | |
pop hl ; restore buffer pointer | |
ld (hl), a | |
inc hl | |
push hl | |
jp nextchar | |
readend: pop hl | |
ld (hl), $ff ; end marker | |
ld e, 10 | |
ld c, c_write | |
call bdos ; print newline | |
ret | |
; converts buffer area into an 16-bit unsigned integer | |
; and stores in inputnum | |
inputtonum: call getinputlen ; bc = num of digits | |
dec bc | |
ld hl, buffer ; buffer pointer | |
add hl, bc | |
ld de, 0 ; digit counter | |
inputtonuml1: push de ; save digit counter | |
push hl ; save buffer pointer | |
ld b, e ; b = digit counter | |
call npower10 ; hl = 10^b | |
ex de, hl ; de = 10^b | |
pop hl ; restore buffer pointer | |
ld a, (hl) ; a = current input digit | |
push hl | |
call mul16 ; hl = current digit * 10^b | |
ex de, hl | |
ld hl, inputnum | |
ld a, (hl) | |
inc hl | |
ld h, (hl) | |
ld l, a | |
add hl, de | |
ex de, hl | |
ld hl, inputnum | |
ld (hl), e | |
inc hl | |
ld (hl), d ; inputnum = inputnum + hl | |
pop hl | |
pop de | |
ld bc, buffer | |
or a | |
sbc hl, bc | |
add hl, bc | |
jp z, inputnumend | |
dec hl ; next buffer | |
inc de ; next digit | |
jp inputtonuml1 | |
inputnumend: ret | |
; bc holds input size | |
getinputlen: ld hl, buffer | |
ld bc, 0 ; counter | |
getinputlenl1: ld a, $ff | |
cp (hl) | |
ret z | |
inc hl | |
inc bc | |
jp getinputlenl1 | |
; writes the number in inputnum to console | |
; uses buffer area | |
printnum: call getnumdigits | |
ld c, l | |
ld b, h | |
ld a, $ff | |
ld hl, buffer | |
add hl, bc | |
ld (hl), a ; end marker | |
dec hl ; prev char | |
ex de, hl ; de = buffer[buffer_len-1] | |
ld hl, inputnum ; hl = &inputnum[0] | |
printnuml2: push hl | |
push de | |
ld a, (hl) | |
inc hl | |
ld h, (hl) | |
ld l, a | |
ex de, hl | |
ld bc, 10 | |
call div16_2 | |
push hl ; save remainder | |
ld hl, inputnum | |
ld (hl), e | |
inc hl | |
ld (hl), d ; save new inputnum | |
pop hl ; restore remainder | |
ld a, e | |
cp 0 | |
jp z, printnuml1 | |
ld a, l | |
pop de | |
pop hl | |
ld (de), a | |
dec de ; prev char | |
jp printnuml2 | |
printnuml1: ld a, l ; last remainder | |
pop de | |
pop hl ; reset stack | |
ld (de), a | |
ld hl, buffer | |
printnuml4: ld a, (hl) | |
cp $ff | |
jp z, printnuml3 | |
push hl | |
add '0' | |
ld e, a | |
ld c, c_write | |
call bdos | |
pop hl | |
inc hl | |
jp printnuml4 | |
printnuml3: ret | |
; hl is the number of digits in inputnum | |
getnumdigits: ld hl, inputnum | |
ld e, (hl) | |
inc hl | |
ld d, (hl) ; de = inputnum | |
ld hl, 0 ; hl is counter | |
getnumdigitsl1: ld bc, 10 | |
push hl | |
call div16_2 | |
pop hl | |
inc hl | |
ld a, e | |
cp d | |
ret z | |
jp getnumdigitsl1 | |
; expects inputnum to hold a 16-bit unsigned integer | |
; converts as per the spec | |
; stores the final 16-bit unsigned integer in output | |
; uses a buffer area | |
convertnum: ld hl, inputnum | |
ld a, (hl) | |
inc hl | |
ld h, (hl) | |
ld l, a ; hl = number | |
ex de, hl ; de = number | |
ld bc, buffer ; address of buffer | |
push bc ; save buffer pointer | |
condigits: ld bc, 10 | |
call div16_2 ; number / 10 | |
pop bc ; restore buffer pointer | |
ld a, l | |
ld (bc), a ; save remainder | |
inc bc ; next address of fifo buffer | |
push bc ; save buffer pointer | |
ld a, e | |
or d | |
jp nz, condigits ; if quotient is zero, loop | |
pop bc ; reset stack | |
ld a, $ff | |
ld (bc), a ; end of buffer marker | |
ld bc, buffer ; address of buffer fifo buffer | |
push bc ; save buffer pointer | |
exx | |
ld b, 0 ; digit counter | |
exx | |
ld hl, inputnum | |
xor a | |
ld (hl), a | |
inc hl | |
ld (hl), a ; reset inputnum | |
procdigits: pop bc ; restore digit pointer | |
ld a, (bc) ; get current digit | |
cp $ff ; is it the end? | |
jp z, procend ; stop processing | |
push bc ; save digit pointer | |
exx | |
ld a, b ; load acc with digit index | |
inc b ; increment digit index | |
exx | |
ld b, a ; b = digit_index | |
call npower10 | |
ex de, hl ; de = 10^digit_index | |
pop bc ; restore digit pointer | |
ld a, (bc) ; get | |
inc bc ; next digit | |
push bc ; save digit pointer | |
inc a ; digit value + 1 | |
cp 10 ; is new number 10? | |
jp nz, skipb10ovf ; skip base 10 overflow case | |
exx | |
inc b ; increment digit index one more | |
exx | |
skipb10ovf: ld c, a | |
ld b, 0 ; bc = digit value + 1 | |
call mul16_2 ; (digit_value + 1) * 10^digit_index | |
ex de, hl ; de = new digit value | |
ld hl, inputnum | |
ld a, (hl) | |
inc hl | |
ld h, (hl) | |
ld l, a ; hl = inputnum | |
add hl, de ; hl = inputnum + digit value | |
ex de, hl | |
ld hl, inputnum | |
ld (hl), e | |
inc hl | |
ld (hl), d ; inputnum = hl | |
jp procdigits | |
procend ret | |
buffer: ds 64 | |
inputnum: ds 2 ; 16-bit unsigned integer | |
message: db "enter a number: $" | |
; hl = 10^b | |
npower10: xor a | |
cp b | |
ld hl, 1 | |
ret z ; if b is zero, ret 10^0 = 1 | |
ld de, 10 | |
ld a, 1 | |
cp b | |
jp nz, npower10_l1 | |
ex de, hl | |
ret ; if b is 1, ret 10^1 = 10 | |
npower10_l1 dec b | |
npower10_l2 ld c, b ; save counter | |
ld a, 10 | |
call mul16 | |
ex de, hl | |
ld b, c ; restore counter | |
djnz npower10_l2 | |
ex de, hl | |
ret | |
; a is multiplier | |
; de is multiplicand | |
; hl is result | |
mul16: ld b, 16 | |
ld hl, 0 | |
mul16_l1 sra a | |
jp nc, mul16_skip_add | |
add hl, de | |
mul16_skip_add sla e | |
rl d | |
djnz mul16_l1 | |
ret | |
; de is dividend | |
; bc is divisor | |
; out de is quotient | |
; out hl is remainder | |
div16_2: ld hl, 0 ; set accumulator to zero | |
ex af, af' | |
ld a, 16 | |
div16_2_l1 ex af, af' | |
ld a, h | |
or a | |
jp m, div16_2_l2 ; a < 0 | |
sla e | |
rl d ; left shift dividend | |
rl l | |
rl h ; left shift accumulator | |
or a | |
sbc hl, bc ; a = a - m | |
jp div16_2_l3 | |
div16_2_l2 sla e | |
rl d ; left shift dividend | |
rl l | |
rl h ; left shift accumulator | |
add hl, bc ; a = a + m | |
div16_2_l3 ld a, h | |
or a | |
jp m, div16_2_l4 ; a < 0 | |
set 0, e ; q(0) = 1 | |
jp div16_2_l5 | |
div16_2_l4 res 0, e ; q(0) = 0 | |
div16_2_l5 ex af, af' | |
dec a | |
jp nz, div16_2_l1 | |
ld a, h | |
or a | |
jp p, div16_2_l6 ; a < 0 | |
add hl, bc ; yes, a = a + m | |
div16_2_l6 ret | |
; de is multiplier | |
; bc is multiplicand | |
; hl is result | |
mul16_2: ld hl, 0 ; accumulator set to zero | |
ex af, af' | |
ld a, 16 ; set counter | |
mul16_2_l1 ex af, af' | |
sra d | |
rr e ; shift multiplier right one bit | |
jr nc, mul16_2_l2 | |
add hl, bc ; add multiplicand to accumulator | |
mul16_2_l2 sla c ; shift multiplicand left one bit | |
rl b | |
ex af, af' | |
dec a ; counter = counter - 1 | |
jr nz, mul16_2_l1 | |
ret |
Author
neuro-sys
commented
Feb 25, 2019
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment