| ??? 09/12/04 16:11 Read: times Msg Score: +2 +2 Informative -2 Gimmee Code +2 Good Answer/Helpful |
#77273 - RE: Quesiton about bin to dec Responding to: ???'s previous message |
Conversion of wide numbers in binary format to an ASCII decimal representation is a question that comes up often on this forum. I choose to add to the available pool of information by offering a specific solution to the problem posed by WONF CHI FAI by showing some standard 8051 assembly language code that can convert 40-bit (5 byte numbers) into a decimal ASCII string. You can see the code below. Alternately you may link to it in a separate WEB page by clicking this link: http://www.8052.com/users/mkaras/CVT_DEC.A51
I want to direct attention to some nice code that one member here, Graham Cole, has posted at http://www.programmersheaven.com/zone5/cat.../32144.htm . I extended his fast 32-bit divide routine to make the 40-bit routine used in the code I present below. Michael Karas
;
;
; This program permits conversion of a 40-bit number to decimal
; for display.
;
$NOMOD51
$INCLUDE(REG51FX.INC) ; register definitions compatible
; with standard Intel architecture FX cpu
ASCII EQU '0' ; set to the offset to add to each result digit
; use zero for decimal binary digits
; use '0' for decimal ascii digits
USING 0 ; use register block 0
;***************************************************
; INTERNAL DATA BIT DEFINITIONS, locations 20H-2FH
;---------------------------------------------------
BSEG AT 00
TEMPB:
DBIT 1 ; temporary bit number
;***************************************************
; INTERNAL DATA BYTE DEFINITIONS
;---------------------------------------------------
;internal data area variables.
;
DSEG AT 30H ; word locations are HIGH:LOW
BITS40:
DS 5 ; the 5 byte (40 bit number to convert)
DS 11 ; make memory dump nice
RESULT:
DS 15 ; result buffer string
STACK:
DS 20 ; reserve 20 bytes of space
RAM_END:
DS 1 ; end of allocated RAM marker
;***************************************************
; INTERRUPT VECTOR DEFINITIONS
;---------------------------------------------------
CSEG AT 0000H ; reset vector
JMP PWR_UP ; power-on entry point
CSEG AT 0003H ; intr 0 vector
CLR EX0 ; external int 0 not used
RETI
CSEG AT 000BH ; timer 0 vector
RETI ; not used
CSEG AT 0013H ; intr 1 vector
CLR EX1 ; external int 1 not used
RETI
CSEG AT 001BH ; timer 1 vector
RETI ; not used
CSEG AT 0023H ; UART vector
CLR ES ; serial port int not used
RETI
;***************************************************
; BASE OF CODE AREA
;---------------------------------------------------
CSEG AT 040H
DB 'Copyright (C) Carousel Design 2004',0
;***************************************************
; NAME: DIV_BY_10
; This routine divides a five byte number in RAM
; @R0 by 10 and leaves the quotient at same
; location and returns the remainder in A
;
; Note: This routine is an adapted version of
; code from one of Graham Cole's submissions at
; www.programmersheaven.com. I changed his 32-bit
; divide by 1->16 to a fixed 40-bit divide by 10
;---------------------------------------------------
DIV_BY_10:
PUSH B ; save entry B register
MOV B, R0 ; save the entry pointer R0 value
PUSH B
MOV B, R2 ; save entry R2 value
PUSH B
MOV B, R3 ; save entry R3 value
PUSH B
;
MOV A, @R0 ; get the MS byte of dividend and divide
MOV B, #10 ; it by the divisor of 10.
DIV AB
MOV @R0, A ; store result of division as quotient.
;
MOV A, B ; save the remainder (which must be in
SWAP A ; the range 0...9) shifted four bits
MOV B,A ; to the left.
;
INC R0 ; point to next byte of the number
MOV R2, #4 ; load loop counter.
;
DIV_BY_10_LOOP:
MOV A, @R0 ; get the MS nibble of the
SWAP A ; dividend into the accumulator.
ANL A, #0x0F
ORL A, B ; or in remainder from last iteration.
;
MOV B, #10 ; divide MS nibble by the divisor of 10
DIV AB
SWAP A ; save partial result (which must be
MOV R3, A ; in the range 0...9) shifted 4 bits.
;
MOV A, B ; read remainder (which must be in
SWAP A ; the range 0...9) and shift 4 bits left.
;
XCHD A, @R0 ; get next nibble of the dividend into acc
;
MOV B, #10 ; divide by the divisor of 10.
DIV AB
ORL A, R3 ; or in the previously saved partial result.
MOV @R0, A ; save the MSB of the quotient ready
; to be returned.
;
MOV A, B ; save remainder
SWAP A ; shifted 4 bits left
MOV B, A ; in B.
;
INC R0 ; increment the pointer through number buffer
DJNZ R2, DIV_BY_10_LOOP ; decrement number of bytes we are working across
SWAP A ; final remainder is in upper nibble
;
POP B
MOV R3, B ; restore original R3
POP B
MOV R2, B ; restore original R2
POP B
MOV R0, B ; restore the original R0
POP B ; restore entry B
RET
;***************************************************
; NAME: CHK_FOR_0
; This routine checks the five byte number @R0
; for being zero/non-zero. The result is returned
; in A. A=0 if number is zero.
;---------------------------------------------------
CHK_FOR_0:
PUSH B
MOV B, R0 ; save entry pointer
PUSH B
MOV B, R2 ; preserve R2
;
CLR A ; start out with a zero value marker
MOV R2, #5 ; test a 5 byte number
CHK_FOR_0_LOOP:
ORL A, @R0 ; just or each byte into A
INC R0 ; advance to next byte
DJNZ R2, CHK_FOR_0_LOOP ; decrement the byte counter
;
MOV R2, B ; restore R2 value
POP B
MOV R0, B ; restore the entry pointer
POP B
RET ; exit A as final or of all 5 bytes
;***************************************************
;NAME: CVT_TO_DEC
; This routine converts the 5 byte number @R0
; to a decimal representation of the number
; at the buffer @R1. The ASCII decimal digits are
; ordered in the result buffer from high to
; low order with leading zeros stripped off
;
; The caller must ensure that the buffer at R1
; has enough room for the maximal result decimal string
; plus one spot for the trailing null byte. 40-bit
; numbers can represent up to 13 decimal digits so
; the buffer should have at least 14 bytes of space
;---------------------------------------------------
CVT_TO_DEC:
MOV A, R2 ; save entry R2 value
PUSH ACC
MOV A, R0 ; save the entry pointers
PUSH ACC
MOV A, R1
PUSH ACC
;
MOV A, #14 ; offset R1 to the end of buffer
ADD A, R1
MOV R1, A
MOV R2, #0 ; setup converted digit counter
;
CVT_TO_DEC_1: ; loop to divide by 10 till quotent goes to zero
CALL DIV_BY_10 ; get next result digit
ADD A, #ASCII ; add on the desired type of digit offset
MOV @R1, A ; save the decimal ascii digit
DEC R1 ; decrement the digit pointer
INC R2 ; count the digit just stored
CALL CHK_FOR_0 ; check for remainder all zeros
JNZ CVT_TO_DEC_1 ; convert till completed
;
POP ACC ; get a copy of the pointer to out buffer
PUSH ACC
MOV R0, A
INC R1 ; adjust back to last stored digit
CVT_TO_DEC2:
MOV A, @R1 ; copy the result to head of buffer
MOV @R0, A
INC R0 ; bump the copy pointers
INC R1
DJNZ R2, CVT_TO_DEC2
MOV A, #0 ; put a trailing null onto buffer
MOV @R0, A
;
POP ACC
MOV R1, A ; restore entry R1 pointer
POP ACC
MOV R0, A ; restore entry R0 pointer
POP ACC
MOV R2, A ; restore the entry R2 value
RET
;***************************************************
; MAIN PROGRAM INITIALIZATION
;---------------------------------------------------
PWR_UP:
MOV SP, #STACK ; set stack pointer
;
MAIN_LOOP:
;; MOV BITS40+0, #10011001B ; initialize a 40 bit number from High to Low
;; MOV BITS40+1, #10011001B ; 1001100110011001100110011001100110011001B is
;; MOV BITS40+2, #10011001B ; same as:
;; MOV BITS40+3, #10011001B ; 659706976665 in decimal
;; MOV BITS40+4, #10011001B
;
;; MOV BITS40+0, #11111111B ; initialize a 40 bit number from High to Low
;; MOV BITS40+1, #11111111B ; 1111111111111111111111111111111111111111B is
;; MOV BITS40+2, #11111111B ; same as:
;; MOV BITS40+3, #11111111B ; 1099511627775 in decimal
;; MOV BITS40+4, #11111111B
;
;; MOV BITS40+0, #00000000B ; initialize a 40 bit number from High to Low
;; MOV BITS40+1, #00000000B ; 0000000000000000000000000000000000000001B is
;; MOV BITS40+2, #00000000B ; same as:
;; MOV BITS40+3, #00000000B ; 1 in decimal
;; MOV BITS40+4, #00000001B
;
MOV BITS40+0, #00011111B ; initialize a 40 bit number from High to Low
MOV BITS40+1, #01110001B ; 0001111101110001111110110000010011001011B is
MOV BITS40+2, #11111011B ; same as:
MOV BITS40+3, #00000100B ; 135056262347 in decimal
MOV BITS40+4, #11001011B
;
MOV R0, #BITS40 ; convert the 40-bit number
MOV R1, #RESULT
CALL CVT_TO_DEC
;
JMP MAIN_LOOP ; go wait for next tick time
END
|
| Topic | Author | Date |
| Quesiton about bin to dec | 01/01/70 00:00 | |
| RE: Quesiton about bin to dec | 01/01/70 00:00 | |
| RE: Quesiton about bin to dec | 01/01/70 00:00 | |
| RE: Quesiton about bin to dec | 01/01/70 00:00 | |
RE: Quesiton about bin to dec | 01/01/70 00:00 |



