OutBufDXasDecimal: push ax push bx push si sub sp, 24h mov ax, dx ; value mov bx, 10 ; radix mov si, sp .repeat xor dx, dx div bx mov [si], dl inc si .until ax==0 .repeat dec si mov al, [si] add al, '0' stosb .until si==sp add sp, 24h pop si pop bx pop ax retn ;OutBufDXasDecimal ends
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]
;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 DB 0 ;A3*16+A2
NumL DB 0 ;A1*16+A0
;share variables
;=B4*104 + B3*103 + B2*102 + B1*101 + B0*100
;=B4*10000 + B3*1000 + B2*100 + B1*10 + B0
TenK DB 0 ;B4
Thou DB 0 ;B3
Hund DB 0 ;B2
Tens DB 0 ;B1
Ones DB 0 ;B0
mov al, NumH ;swapf NumH,w ;al = A2*16+A3
shr al, 4 ;andlw $0F ;al = A3 *** PERSONALLY, I'D REPLACE THESE 2
add al, 0F0h ;addlw $F0 ;al = A3-16 *** LINES WITH "IORLW 11110000B" -AW
mov Thou, al ;movwf Thou ;B3 = A3-16
add Thou, al ;addwf Thou,f ;B3 = 2*(A3-16) = 2A3 - 32
add al, 0E2h ;addlw $E2 ;al = A3-16 - 30 = A3-46
mov Hund, al ;movwf Hund ;B2 = A3-46
add al, 32h ;addlw $32 ;al = A3-46 + 50 = A3+4
mov Ones, al ;movwf Ones ;B0 = A3+4
mov al, NumH ;movf NumH,w ;al = A3*16+A2
and al, 0Fh ;andlw $0F ;al = A2
add Hund, al ;addwf Hund,f ;B2 = A3-46 + A2 = A3+A2-46
add Hund, al ;addwf Hund,f ;B2 = A3+A2-46 + A2 = A3+2A2-46
add Ones, al ;addwf Ones,f ;B0 = A3+4 + A2 = A3+A2+4
add al, 0E9h ;addlw $E9 ;al = A2 - 23
mov Tens, al ;movwf Tens ;B1 = A2-23
add Tens, al ;addwf Tens,f ;B1 = 2*(A2-23)
add Tens, al ;addwf Tens,f ;B1 = 3*(A2-23) = 3A2-69 (Doh! thanks NG)
mov al, NumL ;swapf NumL,w ;al = A0*16+A1
shr al, 4 ;andlw $0F ;al = A1
add Tens, al ;addwf Tens,f ;B1 = 3A2-69 + A1 = 3A2+A1-69 range -69...-9
add Ones, al ;addwf Ones,f ;B0 = A3+A2+4 + A1 = A3+A2+A1+4 and Carry = 0 (thanks NG)
shl Tens, 1 ;rlf Tens,f ;B1 = 2*(3A2+A1-69) + C = 6A2+2A1-138 and Carry is now 1 as tens register had to be negitive
rcl Ones, 1 ;rlf Ones,f ;B0 = 2*(A3+A2+A1+4) + C = 2A3+2A2+2A1+9 (+9 not +8 due to the carry from prev line, Thanks NG)
xor Ones, 0FFh ;comf Ones,f ;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: comf can be regarded like:
;; comf Ones, f
;; incf Ones, f
;; decf Ones, f
;;First two instructions make up negation. So,
;;Ones = -1 * Ones - 1
;; = - 2 * (A3 + A2 + A1) - 9 - 1
;; = - 2 * (A3 + A2 + A1) - 10
shl Ones, 1 ;rlf Ones,f ;B0 = 2*(-2A3-2A2-2A1-10) = -4A3-4A2-4A1-20
mov al, NumL ;movf NumL,w ;al = A1*16+A0
and al, 0Fh ;andlw $0F ;al = A0
add Ones, al ;addwf Ones,f ;B0 = -4A3-4A2-4A1-20 + A0 = A0-4(A3+A2+A1)-20 range -215...-5 Carry=0
shl Thou, 1 ;rlf Thou,f ;B3 = 2*(2A3 - 32) = 4A3 - 64
mov TenK, 7 ;movlw $07 ;al = 7
;movwf TenK ;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 al, 0Ah ;movlw $0A ;al = 10
.repeat ;Lb1: ;do
add Ones, al ;addwf Ones,f ; B0 += 10
dec Tens ;decf Tens,f ; B1 -= 1
.until Carry? ;btfss 3,0 ;skip no carry
;goto Lb1 ; while B0 < 0 ;jmp carry
.repeat ;Lb2: ;do
add Tens, al ;addwf Tens,f ; B1 += 10
dec Hund ;decf Hund,f ; B2 -= 1
.until Carry? ;btfss 3,0
;goto Lb2 ; while B1 < 0
.repeat ;Lb3: ;do
add Hund, al ;addwf Hund,f ; B2 += 10
dec Thou ;decf Thou,f ; B3 -= 1
.until Carry? ;btfss 3,0
;goto Lb3 ; while B2 < 0
.repeat ;Lb4: ;do
add Thou, al ;addwf Thou,f ; B3 += 10
dec TenK ;decf TenK,f ; B4 -= 1
.until Carry? ;btfss 3,0
;goto Lb4 ; while B3 < 0
ret ;retlw 0
L@DX2A@EDIr10:
;Takes hex number in dh:dl returns decimal out at [edi] useing local 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 textequ <dh> ;A3*16+A2
NumL textequ <dl> ;A1*16+A0
;temp variables
;=B4*104 + B3*103 + B2*102 + B1*101 + B0*100
;=B4*10000 + B3*1000 + B2*100 + B1*10 + B0
TenK textequ <BYTE PTR [edi-5]> ;B4
Thou textequ <BYTE PTR [edi-4]> ;B3
Hund textequ <BYTE PTR [edi-3]> ;B2
Tens textequ <BYTE PTR [edi-2]> ;B1
Ones textequ <BYTE PTR [edi-1]> ;B0
breakpoint
xor al,al
mov TenK, al
mov Thou, al
mov Hund, al
mov Tens, al
mov Ones, al
mov al, NumH ;swapf NumH,w ;al = A2*16+A3
shr al, 4 ;andlw $0F ;al = A3 *** PERSONALLY, I'D REPLACE THESE 2
add al, 0F0h ;addlw $F0 ;al = A3-16 *** LINES WITH "IORLW 11110000B" -AW
mov Thou, al ;movwf Thou ;B3 = A3-16
add Thou, al ;addwf Thou,f ;B3 = 2*(A3-16) = 2A3 - 32
add al, 0E2h ;addlw $E2 ;al = A3-16 - 30 = A3-46
mov Hund, al ;movwf Hund ;B2 = A3-46
add al, 32h ;addlw $32 ;al = A3-46 + 50 = A3+4
mov Ones, al ;movwf Ones ;B0 = A3+4
mov al, NumH ;movf NumH,w ;al = A3*16+A2
and al, 0Fh ;andlw $0F ;al = A2
add Hund, al ;addwf Hund,f ;B2 = A3-46 + A2 = A3+A2-46
add Hund, al ;addwf Hund,f ;B2 = A3+A2-46 + A2 = A3+2A2-46
add Ones, al ;addwf Ones,f ;B0 = A3+4 + A2 = A3+A2+4
add al, 0E9h ;addlw $E9 ;al = A2 - 23
mov Tens, al ;movwf Tens ;B1 = A2-23
add Tens, al ;addwf Tens,f ;B1 = 2*(A2-23)
add Tens, al ;addwf Tens,f ;B1 = 3*(A2-23) = 3A2-69 (Doh! thanks NG)
mov al, NumL ;swapf NumL,w ;al = A0*16+A1
shr al, 4 ;andlw $0F ;al = A1
add Tens, al ;addwf Tens,f ;B1 = 3A2-69 + A1 = 3A2+A1-69 range -69...-9
add Ones, al ;addwf Ones,f ;B0 = A3+A2+4 + A1 = A3+A2+A1+4 and Carry = 0 (thanks NG)
shl Tens, 1 ;rlf Tens,f ;B1 = 2*(3A2+A1-69) + C = 6A2+2A1-138
;Carry is now 1 as tens register had to be negitive
rcl Ones, 1 ;rlf Ones,f ;B0 = 2*(A3+A2+A1+4) + C = 2A3+2A2+2A1+9
;(+9 not +8 due to the carry from prev line, Thanks NG)
xor Ones,0FFh ;comf Ones,f ;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:
;;comf can be regarded like:
;; comf Ones, f
;; incf Ones, f
;; decf Ones, f
;;First two instructions make up negation. So,
;;Ones = -1 * Ones - 1
;; = - 2 * (A3 + A2 + A1) - 9 - 1
;; = - 2 * (A3 + A2 + A1) - 10
shl Ones, 1 ;rlf Ones,f ;B0 = 2*(-2A3-2A2-2A1-10) = -4A3-4A2-4A1-20
mov al, NumL ;movf NumL,w ;al = A1*16+A0
and al, 0Fh ;andlw $0F ;al = A0
add Ones, al ;addwf Ones,f ;B0 = -4A3-4A2-4A1-20 + A0 = A0-4(A3+A2+A1)-20
;range -215...-5 Carry=0
shl Thou, 1 ;rlf Thou,f ;B3 = 2*(2A3 - 32) = 4A3 - 64
mov TenK, 7 ;movlw $07 ;al = 7
;movwf TenK ;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 al, 0Ah ;movlw $0A ;al = 10
.repeat ;Lb1: ;do
add Ones, al ;addwf Ones,f ; B0 += 10
dec Tens ;decf Tens,f ; B1 -= 1
.until Carry?;btfss 3,0 ;skip no carry
;goto Lb1 ; while B0 < 0 ;jmp carry
.repeat ;Lb2: ;do
add Tens, al ;addwf Tens,f ; B1 += 10
dec Hund ;decf Hund,f ; B2 -= 1
.until Carry?;btfss 3,0
;goto Lb2 ; while B1 < 0
.repeat ;Lb3: ;do
add Hund, al ;addwf Hund,f ; B2 += 10
dec Thou ;decf Thou,f ; B3 -= 1
.until Carry?;btfss 3,0
;goto Lb3 ; while B2 < 0
.repeat ;Lb4: ;do
add Thou, al ;addwf Thou,f ; B3 += 10
dec TenK ;decf TenK,f ; B4 -= 1
.until Carry?;btfss 3,0
;goto Lb4 ; while B3 < 0
retn ;retlw 0