//
// 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); //
}