home *** CD-ROM | disk | FTP | other *** search
- name LCVT
- title LCVT - format 32-bit number
- page 55,132
- ;
- ;
- ; LCVT.ASM --- Convert signed long (32-bit) integer
- ; to formatted ASCII decimal string
- ;
- ; Copyright (C) 1988 Ziff Communications Co.
- ; PC Magazine * Ray Duncan
- ;
- ; Call with: BH = decimal places
- ; BL = field width
- ; CH = conversion flags
- ; bit meaning
- ; 7 = 0 if left justify
- ; 1 if right justify
- ; 6 = 0 fill field with *
- ; if number too large
- ; 1 truncate to fit
- ; 5 = 0 prefix with - only
- ; 1 prefix with + or -
- ; 4 = 0 pad with blanks
- ; 1 pad with char in CL
- ; 0-3 = reserved
- ; CL = pad character
- ; (if bit 4 of CH is set)
- ; DX:AX = 32-bit signed integer
- ; DS:SI = buffer to receive string
- ;
- ; Returns: if successful,
- ; Carry = clear
- ; DS:SI = formatted string
- ; AX = output field length
- ;
- ; if error (number too large,
- ; and bit 6 of CH was not set),
- ; Carry = set
- ; and output buffer filled with '*'
- ;
- ; DX destroyed, other registers preserved
- ;
- ; At least one significant digit is always stored.
- ; Calling this function with a field width of zero
- ; results in an error return.
-
-
- DGROUP group _DATA
-
-
- _DATA segment word public 'DATA'
-
- buflen equ 16 ; length of working buffers
-
- buf1 db buflen dup (?) ; LTOA builds string here
- buf2 db buflen dup (?) ; formatted string built here
-
- _DATA ends
-
- ; names for local variables
- flags equ [bp-1] ; formatting flags
- fpad equ [bp-2] ; pad character, if any
- fdecpl equ [bp-3] ; decimal places in output
- fwidth equ [bp-4] ; width of output field
- fseg equ [bp-6] ; segment of output field
- foffs equ [bp-8] ; offset of output field
- fsign equ [bp-10] ; sign of original number
-
-
- _TEXT segment word public 'CODE'
-
- assume cs:_TEXT
-
- extrn LTOA:near ; we will call the separately
- ; assembled LTOA routine
-
- public lcvt ; make LCVT available to Linker
-
- lcvt proc near ; format 32-bit integer
-
- push es ; save registers
- push di
- push bp
- push cx
- push bx
-
- mov bp,sp ; set up local variables
- sub sp,10
-
- mov fpad,cx ; save flags and pad char.
- mov fwidth,bx ; save width and dec. places
- mov fseg,ds ; save output field segment
- mov foffs,si ; save output field offset
- mov fsign,dx ; save sign of number
-
- or bl,bl ; is output width zero?
- jnz lcvt01 ; no, proceed
- jmp lcvt15 ; error if width = zero
-
- lcvt01: cmp bh,(buflen+2) ; too many decimal places?
- jbe lcvt02 ; no, proceed
- jmp lcvt14 ; error if buffer too small
-
- lcvt02: or dx,dx ; test sign of number...
- jns lcvt03 ; jump if number positive
-
- neg dx ; negative, take abs. value
- neg ax ; of number so we can control
- sbb dx,0 ; sign placement
-
- lcvt03: mov cx,10 ; use decimal base
- mov si,DGROUP ; set DS:SI = local buffer
- mov ds,si
- mov si,offset DGROUP:buf1
-
- call LTOA ; convert DX:AX to ASCII
- ; returns DS:SI -> string,
- ; AX = length
-
- ; now format the string...
-
- add si,ax ; point to end of string
- dec si ; returned by LTOA
- mov cx,ax ; let CX = string length
-
- push ds ; point to end of buffer
- pop es ; for formatted string
- mov di,offset DGROUP:buf2+buflen-1
-
- std ; set direction flag
- ; for backwards move
- xor bx,bx ; init. places counter
-
- lcvt04: movsb ; transfer one char.
- inc bx ; count characters
- cmp bl,fdecpl ; need decimal point?
- jne lcvt05 ; no, jump
- mov al,'.' ; yes, store it
- stosb
-
- lcvt05: loop lcvt04 ; until all chars. transferred
-
- cmp bl,fdecpl ; decimal taken care of?
- ja lcvt08 ; yes, jump
-
- je lcvt07 ; well, partially...
-
- lcvt06: ; no, need decimal point
- mov al,'0' ; store zeros up to
- stosb ; decimal point
- inc bx
- cmp bl,fdecpl
- jne lcvt06
- mov al,'.' ; store decimal point
- stosb
-
- lcvt07: mov al,'0' ; force leading zero
- stosb
-
- lcvt08: ; was number negative?
- test word ptr fsign,-1
- jns lcvt09 ; no, jump
- mov al,'-' ; yes, store '-' sign
- stosb
- jmp lcvt10
-
- lcvt09: ; positive number, is
- ; '+' sign needed?
- test byte ptr flags,20h
- jz lcvt10 ; no, jump
- mov al,'+' ; yes, store '+' sign
- stosb
-
- lcvt10: cld ; string now formatted
- ; with dec. point & sign
- mov si,di ; copy address
- inc si ; point to formatted string
- ; and calculate its length
- mov ax,offset DGROUP:buf2+buflen
- sub ax,si ; now AX = formatted length
-
- mov es,fseg ; set ES:DI = address and
- mov di,foffs ; CX = length of user's
- mov cl,fwidth ; output buffer
- xor ch,ch
-
- jcxz lcvt15 ; return error if output
- ; field width = zero
-
- cmp cx,ax ; is string too big for
- ; user's output field?
- jae lcvt11 ; no, jump
-
- ; OK to truncate string?
- test byte ptr flags,40h
- jz lcvt14 ; no, error has occurred
-
- mov ax,cx ; truncate formatted length
- ; to output field length
-
- lcvt11: push ax ; save formatted length
-
- mov al,' ' ; default pad char = blank
-
- ; test special padding flag
- test byte ptr flags,10h
- jz lcvt12 ; jump if use ASCII blank
-
- mov al,fpad ; else use special char
-
- lcvt12: rep stosb ; flood output field with
- ; padding character
-
- mov di,foffs ; restore output buffer address
- pop cx ; length of formatted string
-
- ; left or right justify?
- test byte ptr flags,80h
- jz lcvt13 ; jump if left justify
-
- mov al,fwidth ; right justify, length of
- xor ah,ah ; user's output buffer
- sub ax,cx ; - formatted string length
- add di,ax ; = offset into output field
-
- lcvt13: rep movsb ; transfer formatted string
- ; to user's buffer
-
- clc ; success signal: clear Carry
- jmp lcvt16 ; go clean up and exit
-
- lcvt14: ; error encountered, fill
- ; output field with '*' chars.
-
- mov es,fseg ; ES:DI -> output field
- mov di,foffs
- mov cl,fwidth ; CX = output field length
- xor ch,ch
- mov al,'*' ; character = asterisk
- rep stosb ; flood the output buffer
-
- lcvt15: stc ; error signal: set Carry
-
- lcvt16: mov ds,fseg ; return DS:SI = address
- mov si,foffs ; of output field
- mov al,fwidth ; AX = output field width
- mov ah,0 ; (protect carry flag)
-
- mov sp,bp ; discard local variables
-
- pop bx ; restore registers
- pop cx
- pop bp
- pop di
- pop es
-
- ret ; back to caller
-
- lcvt endp
-
-
- _TEXT ends
-
- end
-