Statistics

Members: 1927
News: 293
Web Links: 1
Visitors: 3962394

Who's Online

We have 1 guest online
Damn Vulnerable LinuxDamn Vulnerable Linux (DVL) is a Linux-based (modified Damn Small Linux) tool for IT-Security & IT-Anti- Security and Attack & Defense. [CLICK HERE FOR MORE INFOS! ]

Featured Conference Video

T16-Recon2006-Joe_Stewart-OllyBonE.gif OllyBone - Semi-Automatic Unpacking on IA-32. View the conference video here!
64-bit Integer/ASCII Conversion
User Rating: / 0
PoorBest 
Written by X-Calibre [Diamond]   


The following routines provide an assembly-language library for converting 64-bit integers to and from ASCII, such as would be required when preparing user-supplied data for qword arithmetic or FPU instructions. The library consists of the routines ParseRadixSigned, ParseRadixUnsigned, PrintRadixSigned, and PrintRadixUnsigned, and the macro Divide64. Wrappers for calling the routines from C code have also been provided.

 

 

ParseRadix

ParseRadix is a pair of routines for converting an ASCII string to a signed or unsigned 64-bit integer, using a given radix as a base. The routines take a pointer to a string and an integer radix as input, and return a 64-bit number.

;------------------------------------------------------------------------- ParseRadixUnsigned PROC
; Input: Pointer to zero-terminated string in ESI, radix in EDI ; Output: Parsed number in EDX::EAX
; Uses: EAX, EBX, ECX, EDX, ESI, EDI

xor ebx, ebx

     ; result in EDX::EAX
xor       eax, eax
xor       edx, edx
mov       al, [esi]
inc       esi
test eax, eax
jz        @@endOfParsing
sub       eax, 30h
.IF eax > 9
sub       eax, 7
.ENDIF
mov       bl, [esi]

@@smallParseLoop:

     ; ASCII to number conversion
sub       ebx, 30h
inc       esi
mul       edi
.IF ebx > 9
sub       ebx, 7
.ENDIF
add       eax, ebx
mov       bl, [esi]
jc        @@carry
test ebx, ebx
jnz       @@smallParseLoop
ret

@@carry:

     inc       edx
test ebx, ebx
jz        @@endOfParsing

@@bigParseLoop:

     ; ASCII to number conversion
mov       ecx, eax
mov       eax, edx
sub       ebx, 30h
inc       esi
mul       edi
xchg eax, ecx
mul       edi
.IF ebx > 9
sub       ebx, 7
.ENDIF
add       eax, ebx
mov       bl, [esi]
adc       edx, ecx
test ebx, ebx
jnz       @@bigParseLoop

@@endOfParsing:

ret
ParseRadixUnsigned ENDP

ParseRadixSigned PROC
; Input: Pointer to zero-terminated string in ESI, radix in EDI ; Output: Parsed number in EDX::EAX
; Uses: EAX, EBX, ECX, EDX, ESI, EDI

     .code
; If string does not start with a '-', consider it positive
cmp       byte ptr [esi], '-'
jne       ParseRadixUnsigned
; Number is negative, first parse the absolute value
inc       esi
call ParseRadixUnsigned
; Now negate the absolute value to get the negative result
neg       edx
neg       eax
sbb       edx, 0
ret

ParseRadixSigned ENDP
;-------------------------------------------------------------------------

The following is a wrapper used for calling the ParseRadix routines from C. The wrapper provides the following C functions:

extern unsigned __int64 __stdcall

ParseRadixUnsignedC(char *lpBuffer, unsigned int radix);

extern signed __int64 __stdcall

ParseRadixSignedC(char *lpBuffer, unsigned int radix);

;------------------------------------------------------------------------- .386
.Model Flat, StdCall

.code
include ParseRadix.asm

ParseRadixUnsignedC PROC lpBuffer:PTR BYTE, radix:DWORD

     push esi
mov       esi, [lpBuffer]
push edi
mov       edi, [radix]
push ebx
call ParseRadixUnsigned
pop       ebx
pop       edi
pop       esi
ret

ParseRadixUnsignedC ENDP

ParseRadixSignedC PROC lpBuffer:PTR BYTE, radix:DWORD

     push esi
mov       esi, [lpBuffer]
push edi
mov       edi, [radix]
push ebx
call ParseRadixSigned
pop       ebx
pop       edi
pop       esi
ret

ParseRadixSignedC ENDP

END
;-------------------------------------------------------------------------

Divide64


Divide64 is a macro for doing 64-bit division using 32-bit integer instructions. Note that this is a 'long division' algorithm. It can easily be expanded to be able to divide any number by 32 bits. I only use it for 64 bits here to keep the CPU from getting an exception on overflow when the input is larger than ((2^32)-1)*divisor, so that printing any 64 bit number with any radix is possible.

;------------------------------------------------------------------------- Divide64 MACRO
; Input: 64 bit dividend in EBX::ECX, 32 bit divisor in ESI ; Output: 64 bit result in EBX::EAX, 32 bit remainder in EDX ; Uses: EAX, EBX, ECX, EDX, ESI

     ; Divide high dword by divisor.
mov       eax, ebx
xor       edx, edx
div       esi
; Put remainder as high dword of the original dividend.
mov       ebx, eax
mov       eax, ecx
div       esi

ENDM
;-------------------------------------------------------------------------

PrintRadix


PrintRadix is a pair of routines for converting signed and unsigned 64-bit numbers to an ASCII, string, using a given radix as base. These routines take a 64-bit number and an integer radix as inpit, and return the pointer to a character buffer.

;------------------------------------------------------------------------- PrintRadixUnsigned PROC
; Input: 64 bit unsigned number in EBX::ECX, radix in ESI, pointer to output ; buffer in EDI
; Output: Zero-terminated ASCII string in output buffer, length of string in

;           EAX
; Uses:        EAX, EBX, ECX, EDX, ESI, EDI, EBP
xor       ebp, ebp  ; StringLength counter
; If the high dword of the number is larger than the divisor, we
; have to do a 'long division' to prevent overflow.
cmp       ebx, esi
jb        smallDiv
longDiv

Divide64

     ; Convert the remainder to an ASCII char.
add       edx, 30h
dec       esp
.IF  edx > 39h
add       edx, 7
.ENDIF
; Store char on stack.
inc       ebp
; While result is not 0, we loop.
test eax, eax
mov       ecx, eax
mov       [esp], dl
jz        lowDWORDIsZero
cmp       ebx, esi
jae       longDiv
smallDiv

; Set EBX::ECX to EDX::EAX for a normal 64->32 division. mov edx, ebx mov eax, ecx

radixLoopSmall

div esi

     ; Convert the remainder to an ASCII char.
add       edx, 30h
dec       esp
.IF  edx > 39h
add       edx, 7
.ENDIF
; Store char on stack.
inc       ebp
mov       [esp], dl
; Clean out high dword for next division.
xor       edx, edx
; While result is not 0, we loop.
test eax, eax
jnz       radixLoopSmall
toBuffer

mov eax, ebp ; Return stringlength (not including 0-terminator)

toBufferLoop

; Copy the string from stack to the destination buffer. inc edi mov dl, [esp] inc esp dec ebp mov [edi-1], dl jnz toBufferLoop

     ; Zero terminate the string.
mov       byte ptr [edi], 0
ret
lowDWORDIsZero

test ebx, ebx jnz longDiv

     ; We have the final string, time to copy it to the destination buffer.
jmp       toBuffer

PrintRadixUnsigned ENDP

PrintRadixSigned PROC
; Input: 64 bit signed number in EBX::ECX, radix in ESI, pointer to output ; buffer in EDI
; Output: Zero-terminated ASCII string in output buffer, length of string in

;           EAX
; Uses:        EAX, EBX, ECX, EDX, ESI, EDI, EBP
; If number is non-negative, use the normal PrintRadix
test ebx, ebx
jns       PrintRadixUnsigned
; Prefix the number with a - sign
mov       byte ptr [edi], '-'
inc       edi
; Negate the 64 bit number
neg       ebx
neg       ecx
sbb       ebx, 0
; Do a normal PrintRadix
call PrintRadixUnsigned
inc       eax
ret

PrintRadixSigned ENDP
;-------------------------------------------------------------------------

The following is a wrapper used for calling the PrintRadix routines from C. The wrapper provides the following C functions:

extern unsigned int __stdcall

        PrintRadixUnsignedC(char *lpBuffer, unsigned __int64 number, 
unsigned int radix);

extern unsigned int __stdcall

        PrintRadixSignedC(char *lpBuffer, signed __int64 number, 
unsigned int radix);

;------------------------------------------------------------------------- .386
.Model Flat, StdCall

.code
include PrintRadix.asm

PrintRadixUnsignedC      PROC lpBuffer:PTR BYTE, number:QWORD, radix:DWORD
push ebp
mov       ecx, dword ptr [number]
push ebx
mov       ebx, dword ptr [number+sizeof DWORD]
push esi
mov       esi, [radix]
push edi
mov       edi, [lpBuffer]
call PrintRadixUnsigned
pop       edi
pop       esi
pop       ebx
pop       ebp
ret
PrintRadixUnsignedC      ENDP
PrintRadixSignedC        PROC lpBuffer:PTR BYTE, number:QWORD, radix:DWORD
push ebp
mov       ecx, dword ptr [number]
push ebx
mov       ebx, dword ptr [number+sizeof DWORD]
push esi
mov       esi, [radix]
push edi
mov       edi, [lpBuffer]
call PrintRadixSigned
pop       edi
pop       esi
pop       ebx
pop       ebp
ret
PrintRadixSignedC        ENDP

END
;-------------------------------------------------------------------------