; PRDEC32.ASM -- Include-able library function file
; Mach32_DecASC: 32-bit unsigned machine integer to ASCII decimal conversion
; K. Heidenstrom (kheidens@actrix.gen.nz)
; Modified:
;
; KH.940729.001 Started
; KH.940730.002 First fully-defined working version, renamed all labels
; KH.941114.003 Version for posting on the net in comp.lang.asm.x86
; Notes
;
; This function converts a 32-bit unsigned machine longword in DX|AX to ASCII
; decimal representation. It is similar to the itoa() function in C.
;
; Output is controlled by two parameters specified in CX on entry.
;
; CL contains the number of digits desired in the output. This may be any
; value, from 0 to 255, but is normally in the range 1 to 10.
;
; CH contains the padder character for right-justified numbers. If this
; register is set to zero, no padding is used, and only the digits necessary
; to represent the number are output. If CH is not zero, then it is taken
; as an ASCII character to be used to pad the number on the left, to the width
; specified in CL. In this case, a space or a "0" are normally used in CH.
;
; If the number of digits specified in CL is insufficient to contain the value
; represented by DX|AX, then all columns are output as "#" characters (this is
; controlled by the PrDecOvrflowChr equate below). In this case, the routine
; will return with carry set. It will also return with carry set if CL was
; zero (i.e. no digits at all).
;
; The subroutine's stack space requirement is sixteen bytes, or twelve bytes
; plus the stack space required by the output function, whichever is greater.
;
; The output method must be specified at assembly time, by defining a
; PrDec_Output macro. This macro will be assembled into the part of the
; subroutine where the character output is required. The requirements for
; the character output macro are as follows:
;
; On entry, AL contains the character to be displayed or output.
;
; AX DX BP DI These MAY be modified by the macro code.
; BX CX SI These MUST NOT be modified by the macro code.
; DI DS ES These are not used at all by the Mach32_DecASC subroutine.
;
; This last group of registers are not used or changed by the subroutine code,
; and may be set up before entering the subroutine, then used by the output
; macro, and will be returned by the subroutine. This is intended to support
; use of STOSB as the output function macro. DI can be set up before entry to
; the subroutine, and the output function macro can contain a STOSB, and on
; return from the subroutine, DI will point past the last stored character.
; Note that the subroutine does not use, or modify, the direction flag.
;
; The output function macro is executed in left-to-right sequence as the
; digits of the output value are calculated.
;
; The total length of the PrDec_Output macro must be limited to 33 bytes (at
; the moment - this may change), in order to avoid a bad branch error at the
; end of the subroutine.
;
; Example PrDec_Output macros:
;
; MACRO PrDec_Output
; stosb ; Add digit to string being generated
; ENDM
;
; MACRO PrDec_Output
; push bx ; Preserve
; xor bx,bx ; Output to first display page
; mov ah,0Eh ; TTY output
; int 10h ; Output to BIOS
; pop bx ; Restore
; ENDM
;
; MACRO PrDec_Output
; mov dl,al ; Digit to DL
; mov ah,2 ; Char output
; int 21h ; Output to DOS
; ENDM
PrDecOvrflowChr = "#" ; Char to display on overflow
PROC Mach32_DecASC near
; Func: Convert unsigned long machine integer
; to ASCII decimal representation
; In: DX|AX = Value to be converted
; CL = Number of digits to display
; (normally in range 1 - 10 but all
; values are handled correctly)
; CH = Padder (typically " " or "0", or
; 0 for no leading padding)
; Out: Characters are output according to the
; PrDec_Output macro which must be defined
; before this file is included.
; CF = Overflow status:
; NC = Alright, no overflow
; CY = Overflow occurred
; Lost: Flags (DF is not affected)
; DI, DS, and ES may be modified by the
; output function macro.
; Note: Input value is treated as an unsigned
; longword, in the range 0 - 4294967295.
; Note: If the value won't fit into the number
; of digits specified, all digits are
; output as '#' symbols, indicating
; overflow, and carry is set on return.
push si
push bp
push dx
push cx
push bx
push ax ; Preserve registers
test cl,cl
jz PrDec_Error ; If no digits specified
xchg ax,bx ; Loword to BX
mov si,dx ; Hiword to SI
; Check digit position is within range
PrDec_DigitLp: cmp cl,11 ; Check that we're at a valid digit
jae PrDec_DoPad ; If not yet, just do space padding
mov dx,1 ; Init loword of divisor to 1
sub cl,dl ; Get digit position
jb PrDec_Exit ; If no digits, or just done last digit
; Calculate divisor in BP|DX as 10 ^ digit position number
push cx ; Keep misc info in CL and CH
xor bp,bp ; Hiword of divisor to zero
PrDec_DivLoop: sub cl,1 ; Count down the shifts
jb PrDec_GotDiv ; If done, have divisor
push bp ; Push hiword
mov ax,dx ; Keep loword
shl dx,1 ; Multiply by two
rcl bp,1 ; Carry into hiword
shl dx,1 ; Multiply by two again
rcl bp,1 ; Carry into hiword
add dx,ax ; Now add original value to value x 4
pop ax ; Restore old hiword
adc bp,ax ; Add hiwords too
shl dx,1 ; Now have value x 5, double it again
rcl bp,1 ; And hiword
jmp SHORT PrDec_DivLoop ; Continue
PrDec_GotDiv: pop cx ; Have divisor, restore CX
; Calculate digit by repeatedly dividing value in SI|BX by divisor in BP|DX
xor ax,ax ; Count of divides
PrDec_CalcLoop: inc ax ; Increment counter
cmp al,10 ; Make sure digit is within range
ja PrDec_Overflow ; If not, display overflow indication
sub bx,dx ; Subtract loword of divisor from value
sbb si,bp ; Borrow from hiword
jnb PrDec_CalcLoop ; Borrowed below zero yet? If not, loop
add bx,dx ; Restore remainder loword
adc si,bp ; Restore hiword too
add al,"0"-1 ; Calculate digit value in ASCII
; Check value of digit
cmp al,"0" ; Is digit zero?
jne PrDec_SetZero ; If not
test cl,cl ; Final position?
jz PrDec_GotDigit ; Force printing final zero
PrDec_DoPad: mov al,ch ; If digit is zero, substitute padder
jmp SHORT PrDec_GotDigit ; Continue
PrDec_Overflow: mov si,-1 ; Force overflow indication from now on
mov al,PrDecOvrflowChr ; Indicate overflow
PrDec_SetZero: mov ch,"0" ; Had non-zero - no more padding now!
PrDec_GotDigit: test al,al
jz PrDec_DigitLp ; If zero, and no padding requested
; Output character in AL using appropriate output mode
PrDec_Output
jmp SHORT PrDec_DigitLp ; Loop for more digits
PrDec_Exit: test si,si
jz PrDec_Exit2 ; If didn't have overflow, exit no carry
PrDec_Error: stc ; If overflow occurred, exit carry set
PrDec_Exit2: pop ax
pop bx
pop cx
pop dx
pop bp
pop si ; Restore registers
ret
ENDP Mach32_DecASC
file: /Techref/intel/16bit/math/radix/32b-xd.htm, 7KB, , updated: 2000/2/16 13:34, local time: 2024/12/25 08:52,
|
| ©2024 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://linistepper.com/techref/intel/16bit/math/radix/32b-xd.htm"> intel 16bit math radix 32b-xd</A> |
Did you find what you needed?
|