From: John Payson via Scott Dattalo
see
http://www.dattalo.com/technical/software/pic/bcd.txt
for notes on how this works. Plan on a headache. <GRIN>
[ed: quick guess at speed is that about 200 instructions will be executed
and 50 instructions + 7 registers used]
;Takes hex number in NumH:NumL Returns decimal in ;TenK:Thou:Hund:Tens:Ones
;written by John Payson
;input
;=A3*163 + A2*162 + A1*161 + A0*160
;=A3*4096 + A2*256 + A1*16 + A0
NumH DS 1 ;A3*16+A2
NumL DS 1 ;A1*16+A0
;output
;=B4*104 + B3*103 + B2*102 + B1*101 + B0*100
;=B4*10000 + B3*1000 + B2*100 + B1*10 + B0
TenK DS 1 ;B4
Thou DS 1 ;B3
Hund DS 1 ;B2
Tens DS 1 ;B1
Ones DS 1 ;B0
mov W, <>NumH ;w = A2*16+A3
or W, #$F0 ;w = A3-16
mov Thou, W ;B3 = A3-16
add Thou, W ;B3 = 2*(A3-16) = 2A3 - 32
mov Hund, W
mov W, #$E2
add Hund, W ;B2 = A3-16 - 30 = A3-46
mov W, #$32
add W, Hund
mov Ones, W ;B0 = A3-46 + 50 = A3+4
mov W, NumH ;w = A3*16+A2
and W, #$0F ;w = A2
add Hund, W ;B2 = A3-46 + A2 = A3+A2-46
add Hund, W ;B2 = A3+A2-46 + A2 = A3+2A2-46
add Ones, W ;B0 = A3+4 + A2 = A3+A2+4
mov Tens, W
mov W, #$E9
add Tens, W ;B1 = A2-23
mov W, Tens
add Tens, W ;B1 = 2*(A2-23)
add Tens, W ;B1 = 3*(A2-23) = 3A2-69 (Doh! thanks NG)
mov W, <>NumL ;w = A0*16+A1
and W, #$0F ;w = A1
add Tens, W ;B1 = 3A2-69 + A1 = 3A2+A1-69 range -69...-9
add Ones, W ;B0 = A3+A2+4 + A1 = A3+A2+A1+4 and Carry = 0 (thanks NG)
rl Tens ;B1 = 2*(3A2+A1-69) + C = 6A2+2A1-138 and Carry is now 1 as tens register had to be negitive
rl Ones ;B0 = 2*(A3+A2+A1+4) + C = 2A3+2A2+2A1+9 (+9 not +8 due to the carry from prev line, Thanks NG)
not Ones ;B0 = ~(2A3+2A2+2A1+9) = -2A3-2A2-2A1-10 (ones complement plus 1 is twos complement. Thanks SD)
;;Nikolai Golovchenko [golovchenko at MAIL.RU] says: complement [not Ones] can be regarded like:
;; not Ones
;; inc Ones
;; dec Ones
;;First two instructions make up negation. So,
;;Ones = -Ones - 1
;; = - 2 * (A3 + A2 + A1) - 9 - 1
;; = - 2 * (A3 + A2 + A1) - 10
rl Ones ;B0 = 2*(-2A3-2A2-2A1-10) = -4A3-4A2-4A1-20
mov W, NumL ;w = A1*16+A0
and W, #$0F ;w = A0
add Ones, W ;B0 = -4A3-4A2-4A1-20 + A0 = A0-4(A3+A2+A1)-20 range -215...-5 Carry=0
rl Thou ;B3 = 2*(2A3 - 32) = 4A3 - 64
mov W, #$07 ;w = 7
mov TenK, W ;B4 = 7
;B0 = A0-4(A3+A2+A1)-20, -5...-200
;B1 = 6A2+2A1-138, -18...-138
;B2 = A3+2A2-46, -1...-46
;B3 = 4A3-64, -4...-64
;B4 = 7, 7
; At this point, the original number is
; equal to TenK*10000+Thou*1000+Hund*100+Tens*10+Ones
; if those entities are regarded as two's compliment
; binary. To be precise, all of them are negative
; except TenK. Now the number needs to be normal-
; ized, but this can all be done with simple byte
; arithmetic.
mov W, #$0A ;w = 10
Lb1: ;do
add Ones, W ; B0 += 10
dec Tens ; B1 -= 1
sb 3.0
;skip no carry
jmp Lb1 ; while B0 < 0
;jmp carry
Lb2: ;do
add Tens, W ; B1 += 10
dec Hund ; B2 -= 1
sb 3.0
jmp Lb2 ; while B1 < 0
Lb3: ;do
add Hund, W ; B2 += 10
dec Thou ; B3 -= 1
sb 3.0
jmp Lb3 ; while B2 < 0
Lb4: ;do
add Thou, W ; B3 += 10
dec TenK ; B4 -= 1
sb 3.0
jmp Lb4 ; while B3 < 0
ret