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