RosettaCodeData/Task/Binary-digits/6502-Assembly/binary-digits.6502

91 lines
3.6 KiB
Plaintext

; C64 - Binary digits
; http://rosettacode.org/wiki/Binary_digits
; *** labels ***
declow = $fb
dechigh = $fc
binstrptr = $fd ; $fe is used for the high byte of the address
chkcom = $aefd
frmnum = $ad8a
getadr = $b7f7
strout = $ab1e
; *** main ***
*=$033c ; sys828 tbuffer ($033c-$03fb)
jsr chkcom ; check for and skip comma
jsr frmnum ; evaluate numeric expression
jsr getadr ; convert floating point number to two-byte int
jsr dec2bin ; convert two-byte int to binary string
lda #<binstr ; load the address of the binary string - low
ldy #>binstr ; high byte
jsr skiplz ; skip leading zeros, return an address in a/y
; that points to the first "1"
jsr strout ; print the result
rts
; *** subroutines ****
; Converts a 16 bit integer to a binary string.
; Input: y - low byte of the integer
; a - high byte of the integer
; Output: a 16 byte string stored at 'binstr'
dec2bin sty declow ; store the two-byte integer
sta dechigh
lda #<binstr ; store the binary string address on the zero page
sta binstrptr
lda #>binstr
sta binstrptr+1
ldx #$01 ; start conversion with the high byte
wordloop ldy #$00 ; bit counter
byteloop asl declow,x ; shift left, bit 7 is shifted into carry
bcs one ; carry set? jump
lda #"0" ; a="0"
bne writebit
one lda #"1" ; a="1"
writebit sta (binstrptr),y ; write the digit to the string
iny ; y++
cpy #$08 ; y==8 all bits converted?
bne byteloop ; no -> convert next bit
clc ; clear carry
lda #$08 ; a=8
adc binstrptr ; add 8 to the string address pointer
sta binstrptr
bcc nooverflow ; address low byte did overflow?
inc binstrptr+1 ; yes -> increase the high byte
nooverflow dex ; x--
bpl wordloop ; x<0? no -> convert the low byte
rts ; yes -> conversion finished, return
; Skip leading zeros.
; Input: a - low byte of the byte string address
; y - high byte -"-
; Output: a - low byte of string start address without leading zeros
; y - high byte -"-
skiplz sta binstrptr ; store the binary string address on the zero page
sty binstrptr+1
ldy #$00 ; byte counter
skiploop lda (binstrptr),y ; load a byte from the string
iny ; y++
cpy #$11 ; y==17
beq endreached ; yes -> end of string reached without a "1"
cmp #"1" ; a=="1"
bne skiploop ; no -> take the next byte
beq add2ptr ; yes -> jump
endreached dey ; move the pointer to the last 0
add2ptr clc
dey
tya ; a=y
adc binstrptr ; move the pointer to the first "1" in the string
bcc loadhigh ; overflow?
inc binstrptr+1 ; yes -> increase high byte
loadhigh ldy binstrptr+1
rts
; *** data ***
binstr .repeat 16, $00 ; reserve 16 bytes for the binary digits
.byte $0d, $00 ; newline + null terminator