*/
Know a good article or link that we're missing? Submit it!
*/

View \fast_binary_to_radix.c

Fast 32-bit binary to compact radix conversion - Keil Shell V1.0

Submitted By: Graham Cole
Rating: (Not rated) (Rate It)


//
//  binary_to_radix()
//
//  Author: Graham Cole
//
//  This function will convert an unsigned 32-bit value in
//  registers R4...R7 into 11 digits of the specified radix.
//
//  The radix may range from 8 to 16 inclusive. Radix 16 is a
//  special case as it is a null operation.
//
//  Two digits are compacted into each byte. The 8 least
//  significant radixal digits are placed in R4...R7 and the 3
//  most significant radixal digits are returned in R2 and R3.
//
//  Call fast_binary_to_radix from assembly language with
//  required radix in accumulator.
//
//  The function uses the currently selected register bank.
//
//  20-May-04 Slight improvement by making use of XCHD.
//  20-May-04 Use B register to store remainder.
//  20-May-04 Divide MS byte in one operation.
//  08-Jun-04 Use DPL to store radix.
//

#pragma ASM

    $REGUSE _fast_binary_to_radix( A, B, PSW, R0, R1, R2, R3, R4, R5, R6, R7, DPH, DPL )

#pragma ENDASM

unsigned long int fast_binary_to_radix( unsigned long int value, unsigned char radix ) small
{

    radix = radix;                      // Suppress UNUSED warning.
                                        // value in: R4,R5,R6,R7
    #pragma ASM

radix_pointer   SET     R0              ;
hex_pointer     SET     R1              ;
partial         SET     DPH             ;
radix           SET     DPL             ;
                                        ;
                                        ;
        MOV     A,radix?041             ;
                                        ;
fast_binary_to_radix:                   ;Check for the special case of radix 16.
                                       
        CJNE    A,#16,?binary_to_radix_convert
                                       
        CLR     A                       ;Radix 16 is a special case
        MOV     R2,A                    ; a null operation apart from clearing
        MOV     R3,A                    ; R2 and R3.
        RET                             ;
                                        ;
?binary_to_radix_convert:               ;
                                        ;
        MOV     radix,A                 ;Store the radix.
                                        ;
        MOV     A,PSW                   ;Get the base address of
        ANL     A,#0x18                 ; the current register bank.
        ORL     A,#0x02                 ;Point to register R2.
        MOV     radix_pointer,A         ;radix_pointer is a pointer to R2.
                                        ;
?binary_to_radix_byte_loop:             ;
                                        ;
        SETB    F0                      ;F0 used to iterate twice for each byte.
                                        ;
?binary_to_radix_digit_loop:            ;
                                        ;
        MOV     A,radix_pointer         ;radix pointer -> hex_pointer
        MOV     hex_pointer,A           ;           R2 -> R4
        ANL     A,#0x07                 ;           R3 -> R4
        CJNE    A,#0x02,?radix_skip_inc ;           R4 -> R5
        INC     hex_pointer             ;           R5 -> R6
?radix_skip_inc:                        ;           R6 -> R7
        INC     hex_pointer             ;
                                        ;
        MOV     A,@hex_pointer          ;Read the most significant byte.
        MOV     B,radix                 ;Divide entire byte by divisor
        DIV     AB                      ; leaving remainder in B.
        MOV     @hex_pointer,A          ; Write result back.
                                       
        SJMP    ?divide_by_radix_loop_end
                                       
?divide_by_radix_loop:                  ;
                                        ;
        MOV     A,@hex_pointer          ;Get the MS nibble of the
        SWAP    A                       ; dividend into the accumulator.
        ANL     A,#0x0F                 ;
        ORL     A,B                     ;
                                        ;
        MOV     B,radix                 ;Divide MS nibble by the radix.
        DIV     AB                      ;
                                        ;
        SWAP    A                       ;Save partial result (which must be
        MOV     partial,A               ; in the range 0...15) shifted 4 bits.
                                        ;
        MOV     A,B                     ;Save remainder (which must be in
        SWAP    A                       ; the range 0...9) shifted 4 bits left.
                                        ;
        XCHD    A,@hex_pointer          ;Get next nibble of the dividend into
                                        ; LS nibble of the accumulator.
        MOV     B,radix                 ;
        DIV     AB                      ;Divide by the radix.
                                        ;
        ORL     A,partial               ;Or in the previously saved partial result.
        MOV     @hex_pointer,A          ;Save the MSB of the quotient ready
                                        ; to be returned.
?divide_by_radix_loop_end:              ;
                                        ;
        MOV     A,B                     ;Save remainder shifted 4 bits left.
        SWAP    A                       ;
        MOV     B,A                     ;
                                        ;
        INC     hex_pointer             ;Increment pointer and iterate
                                        ;
        MOV     A,hex_pointer           ; ...until pointer overflows past R7.
        ANL     A,#0x07                 ;
                                        ;
        JNZ     ?divide_by_radix_loop   ;
                                        ;
        MOV     A,B                     ;Put the remainder in Accumlator.
                                        ;
        JNB     F0,?radix_ms_digit      ;F0 used to iterate twice for each byte.
                                        ;
        SWAP    A                       ;
        MOV     @radix_pointer,A        ;Write ls digit to memory (R2..R6)
                                        ;
        SJMP    ?radix_ls_digit         ;
                                        ;
?radix_ms_digit:                        ;
                                        ;
        ORL     A,@radix_pointer        ;
        MOV     @radix_pointer,A        ;Write digit to memory (R2..R6)
                                        ;
?radix_ls_digit:                        ;
                                       
        JBC     F0,?binary_to_radix_digit_loop
                                       
        INC     radix_pointer           ;Increment radix_pointer...
                                        ;
        MOV     A,radix_pointer         ;...and iterate until pointer overflows
        ANL     A,#0x07                 ;to point at R7.
                                       
        CJNE    A,#0x06,?binary_to_radix_byte_loop
                                       
        MOV     A,R7                    ;Extract the last most significant
        MOV     B,radix                 ; digits from R7 - of which there
        DIV     AB                      ; can be no more than 3 digits
        MOV     R1,B                    ; (in the case of radix = 8 ).
        MOV     B,radix                 ;
        DIV     AB                      ;
        XCH     A,B                     ;
        SWAP    A                       ;
        ORL     A,R1                    ;
        MOV     R1,A                    ;
        MOV     R0,B                    ;
        MOV     A,R1                    ;
                                        ;
        XCH     A,R3                    ;De-uxmuglification...
        MOV     R6,A                    ;
        MOV     A,R4                    ;Place the least significant radix digits
        XCH     A,R5                    ;in R4...R7.
        MOV     R4,A                    ;
        MOV     A,R2                    ;Leave MS radix digits in R3 and...
        MOV     R7,A                    ;
        MOV     A,R0                    ;
        MOV     R2,A                    ;...in R2.
                                        ;
?binary_to_radix_end:                   ;
                                        ;
        RET                             ;

    #pragma ENDASM

    return(value);                      //

}

corner
© 1996-2008 CommunityHeaven LLC. All rights reserved. Reproduction in whole or in part, in any form or medium without express written permission is prohibited.
Violators of this policy may be subject to legal action. Please read our Terms Of Use and Privacy Statement for more information.
North American business development: Nicolai Wadstrom. Publisher: Lars Hagelin.