??? 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 |