home *** CD-ROM | disk | FTP | other *** search
- title BIN2ASC -- Copyright 1997, Morten Elling
- subttl Binary-to-Ascii number conversion
-
- include model.inc
- include modelt.inc
- include bin2asc.ash
-
- @CODESEG
-
- ;//////////////////////////////////////////////////////////////////////
- ;// Name bin2asc
- ;// Desc Convert signed binary number to decimal Asciiz string.
- ;//
- ;//
- ;// Entry Passed args
- ;// Exit Left-justified Asciiz string returned to destination.
- ;// Acc = string length (0 if bad srcsz).
- ;//
- ;// Note Destination storage must hold sufficient space.
- ;// Insignificant leading zeros are not output.
- ;//
- ;// Uses a shift-and-subtract algorithm whose primary
- ;// virtue is its ability to handle very large numbers.
-
- MAX_SIZEOF_BIN = 20h
- DIVISOR = 10d ; Decimal conversion
-
- bin2asc proc
- arg dstStr :dataptr, \ ; Addr of Asciiz destination
- srcBIN :dataptr, \ ; Addr of signed binary source
- srcsz :@uint ; Byte size of source (even, min. 2)
- local @@src :byte :MAX_SIZEOF_BIN ; Work buffer
- @uses ds,es,rsi,rdi,rbx,rcx,rdx
- ;.
- ; ----- Check size parameter
- @cld
- mov rax, [srcsz]
- shr rax, 1
- jbe sh @@err
- add rax, rax
- cmp rax, MAX_SIZEOF_BIN
- jbe sh @@cpy
- @@err: @LES rdi, [dstStr] ; Set up pointer
- jmp @@end
-
- ; ----- Copy src to local storage
- @@cpy: xchg rbx, rax ; rbx = size of src
- @LDS rsi, [srcBIN]
- @LDSEGM es, ss, rdi
- lea rdi, [@@src]
- mov rcx, rbx
- rep movsb
- mov ah, [rsi-1] ; Get src's sign
-
- ; ----- Load pointers
- @LES rdi, [dstStr]
- if @isStackFar
- @LDSEGM ds, ss, rsi
- endif
- lea rsi, [@@src]
- test ah, 80h
- mov al, '+' ; Assume positive
- jns sh @@sgn ; sf = 0 if positive
-
- ; ----- Source is negative, negate it
- mov rcx, rbx
- ; cf = 0 after 'test'
- @@neg: mov al, 00h
- sbb al, [rsi]
- mov [rsi], al
- inc rsi
- dec rcx
- jnz @@neg
- mov al, '-'
-
- ; ----- Store sign character
- @@sgn: stosb
-
-
- ; ----- Perform the conversion by repeatedly dividing source
- ; by DIVISOR to extract one Ascii digit on each loop.
- ; Repeat until quotient is zero.
- @@looptop:
- mov rdx, rbx ; Byte size of src
- @shl rdx, 3 ; * 8 = no. of bits in source
- lea rsi, [@@src] ; Addr of source
- sub rax, rax ; Clear remainder
- @@shl: dec rdx ; Decrement bit counter
- js sh @@stor ; Loop done when < 0
- mov rcx, rbx ; Loop count =
- shr rcx, 1 ; no. of source words, cf=0
- @alignn
- @@shm: rcl @wptr [rsi], 1 ; Rotate word thru carry left
- inc rsi ; Step
- inc rsi ; source pointer
- dec rcx ; Loop
- jnz @@shm ; thru whole source
- rcl rax, 1 ; Update remainder
- ;
- sub rsi, rbx ; Point to @@src[0]
- cmp rax, DIVISOR ; Compare remainder against divisor
- jb @@shl ; Not yet
- sub rax, DIVISOR ; One hit
- inc @bptr [rsi] ; Update quotient (in low source)
- jmp @@shl ; Keep going thru all bits
-
- ; ----- Store digit in wrong order
- ; (acc = source MOD DIVISOR)
- @@stor: or al, '0' ; Make Ascii
- stosb ; Store digit
-
- ; ----- Check if quotient is zero
- ; rsi -> @@src[0]
- mov rcx, rbx
- sub al, al
- dec rsi
- @@qzr: inc rsi
- or al, [rsi]
- jnz @@looptop ; Keep going until quotient = 0
- dec rcx
- jnz @@qzr
-
-
- ; ----- Reverse digits in destination
- mov rsi, @uiptr [dstStr]
- inc rsi ; Remove this line to make
- ; ; the sign char. a suffix
- mov rcx, rdi
- sub rcx, rsi
- sar rcx, 1
- jle sh @@end
- push rdi
- if @isDataFar
- @LDSEGM ds, es
- endif
- dec rsi
- @@rv: inc rsi
- dec rdi
- mov al, [rsi]
- mov ah, [rdi]
- mov [rdi], al
- mov [rsi], ah
- dec rcx
- jnz @@rv
- pop rdi
-
- ; ----- Return string length
- @@end: mov al, 00h ; Zero-terminate string
- stosb
- lea rax, [rdi-1]
- sub rax, @uiptr [dstStr]
- RET
- bin2asc endp
-
-
- ;//////////////////////////////////////////////////////////////////////
- ;// Name HexN
- ;// Desc Convert unsigned binary word/dword to hexadecimal
- ;// Asciiz string.
- ;//
- ;//
- ;// Entry Passed args
- ;// Exit Acc = string length.
-
- HexN proc
- arg pStr :dataptr, \ ; Addr of destination Asciiz string
- mval :@uint ; 16-bit: word; 32-bit: dword value
- @uses es,rdi,rbx,rcx
- ;.
- MSZ = @WordSize
- @cld
- @LES rdi, [pStr]
- lea rbx, [mval+MSZ-1] ; Start at high byte
- mov ch, MSZ
- @@hb: if @isStackFar
- mov al, ss:[rbx] ; ('SEGSS' hangs TASM32 v5.0)
- else
- mov al, [rbx]
- endif
- mov ah, al ; Convert high nibble
- @shr al, 4
- cmp al, 10d
- sbb al, 69h
- das
- stosb
- mov al, ah ; Convert low nibble
- and al, 0fh
- cmp al, 10d
- sbb al, 69h
- das
- stosb
- dec rbx ; Next byte
- dec ch
- jnz @@hb
- sub rax, rax
- stosb
- mov al, MSZ*2 ; Return string length
- RET
- HexN endp
-
- END