home *** CD-ROM | disk | FTP | other *** search
- include compiler.inc
- ttl _XN, 1.04, 08-28-86 jwk
-
- ;binary to ascii conversion
- ;
- ; call is _x?(n,bfr,base) unsigned long n; char *bfr;
- ; int base; /* only _xn takes base */
- ; BUFFER MUST BE AT LEAST 12 BYTES, NO CHECK MADE!!!
- ;
- ;
- ; REGISTERS at entry--
- ; AX: unknown
- ; BX: unknown
- ; CX: unknown
- ; DX: unknown
- ; SI: unknown
- ; DI: unknown
- ; BP: Frame pointer of calling routine.
- ; DS: unknown
- ; ES: unknown
- ;
- ; at exit--
- ; AX: Offset of "bfr" start, same as supplied.
- ; BX: zero
- ; CX: zero
- ; DX: Segment of "bfr" start (if not small model).
- ; SI: Restored.
- ; DI: Restored.
- ; BP: Restored.
- ; DS: Restored.
- ; ES: Segment of "bfr"
- ;
- ; SIDE EFFECTS (including effect on RAM):
- ; Converts its argument (as unsigned long) to ASCII,
- ; using supplied base in range from 2 to 36 inclusive, and
- ; stores characters in buffer as null-terminated string.
- ;
-
- dseg
-
- cseg
-
- procdef _xn <<n1,word>,<n2,word>,<bfr,ptr>,<base,word>>
- pushreg
- mov si,base
- jmp short xc
- ;
- entrdef _xh
- pushreg
- mov si,16
- jmp short xc
- ;
- entrdef _xo
- pushreg
- mov si,8
- jmp short xc
- ;
- entrdef _xd
- pushreg
- mov si,10
-
- xc:
- mov ax,n1 ;LSW of number
- mov dx,n2 ;MSW of number
- ldptr di,bfr ;buffer address to use
- call cvtl ;macro not needed, no args to pass
- clc
- retptrm bfr
-
- pend _xn
-
- internal cvtl
- ;
- ; internal routine to perform the conversion and store chars
- ; (chars are stored in reverse sequence, then un-reversed)
- ;
- ; REGISTERS at entry--
- ; AX: LSW of number to convert
- ; BX: unknown
- ; CX: unknown
- ; DX: MSW of number to convert
- ; SI: base quantity (2 to 36)
- ; DI: buffer address offset to start
- ; BP: Frame pointer of calling routine (_xn).
- ; DS: unknown
- ; ES: buffer address segment
- ;
- ; at exit--
- ; AX: last pair of chars swapped
- ; BX: zero
- ; CX: zero
- ; DX: zero
- ; SI: offset near middle of buffer
- ; DI: offset near middle of buffer
- ; BP: Restored
- ; DS: unchanged
- ; ES: buffer address segment
- ;
- ; SIDE EFFECTS (including effect on RAM):
- ; Stores remainders, converted to ASCII, at ES:DI,
- ; then reverses chars in buffer to the correct sequence
- ; using the K&P "swap the ends" algorithm.
-
- push bp ;don't use macro here; bp-4 offset
- mov bp,sp ;...must not be modified!
- push di ;save buffer start for "reverse"
- xor bx,bx ;clear work register
- push bx ;clear the dividend work reg
- cld ;set for ascending STOSB action
- xchg ax,bx
- stosb ;put in terminating NULL first
- xchg ax,bx
- ;
- ; this does 32-bit division/remainder arithmetic
- ;
- cv0:
- mov cx,32 ;32 bits must be shifted
- cv1:
- xchg cx,[bp-4] ;swap loop count/work reg
- shl ax,1 ;puts 0 bit in quotient
- rcl dx,1
- rcl bx,1
- rcl cx,1
- or cx,cx ;will it go?
- jnz cv2 ;yes since base is < 8 bits
- cmp si,bx ;maybe...
- ja cv3 ;no
- cv2:
- sub bx,si ;32-bit subtract
- sbb cx,0
- inc ax ;sets low bit of Q to 1
- cv3:
- xchg cx,[bp-4] ;swap back
- loop cv1 ;do it for all 32 bits
- ;
- ; quotient in DX:AX, remainder ( < base ) in BL, BH==0
- ;
- xchg ax,bx ;set up to save remainder
- add al,'0' ;convert to ASCII
- cmp al,'9'
- jbe cv4 ;not in A-F range
- add al,7 ;map to UC alpha
- cv4:
- stosb ;put it in buffer
- mov al,ah ;clear work reg for next time
- xchg ax,bx ;get LSW of quotient back
- or ax,ax ;and test for conversion done
- jnz cv0 ;no, go do another divide
- or dx,dx ;maybe...
- jnz cv0 ;no
- ;
- ; this point is not reached until conversion is complete
- ;
- cv5:
- pop ax ;balance the stack (work reg word)
- pop si ;offset to front of buffer
- cv6:
- dec di
- cmp si,di ;check for overlap (or same)
- jae cv7 ;yep, all swapped around
- mov ah,es:[si] ; note that lodsb/stosb would
- mov al,es:[di] ; take more code because one
- mov es:[di],ah ; is incrementing while the
- mov es:[si],al ; other is decrementing
- inc si
- jmp cv6
- cv7:
- mov sp,bp
- pop bp
- ret
-
- cvtl endp ;pend macro is only for public procs
- ;
- finish