Statistics

Members: 1925
News: 293
Web Links: 1
Visitors: 3826369

Who's 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!
Home arrow Articles - Programming arrow Assembly arrow String to Numeric Conversion
String to Numeric Conversion
User Rating: / 0
PoorBest 
Written by Laura Fairhead   


Here I present you with a library routine that scans a value from a string and converts it to an integer. It is very useful, not only when you have to convert string->value but also if you are parsing and want to recognise a numeric token.

 

 

The routine will scan values in any radix from 0 to 36. Characters for the digit values from 10-35 are naturally "A"-"Z"/"a"-"z".

With this routine there are 2 API's 'scanur' and 'scanu'. 'scanur' is used to set the radix of the scan conversion. Once this value is set the main routine 'scanu' can be called freely to scan values from the string.

The scan routine is called with a string pointer which is updated on exit to the first invalid character. It will return with the carry flag set if the value was too big to fit into the return register EAX. If the carry flag is clear, there is no error, however now the zero flag indicates if a valid value was actually scanned. This return status convention gives the most flexibility to the application programmer, also if a valid value MUST be scanned they can detect the condition via:-

CALL NEAR PTR scanu
JNA error ;get out if overflow/no value

The branch will be taken if CF=1 or ZF=1. Hence, if a value has to be scanned errors may be picked up with only one test.

=========START OF CODE===================================================== ;
;(current scan radix)
;
scanuradi:

DB ?

;
;scanur- set up for scanu routine
;
;entry: AL=radix
;
; !! radix must be in range 0<=radix<=36 ;

;        !! radix must be set by calling this routine prior to
;        !! using scanu
;
;exit:      (all registers preserved)

;

scanur PROC NEAR

        MOV BYTE PTR CS:[scanuradi],AL
RET

scanur ENDP

;
;scanu- scan string value returning result ;

;entry:     DS:SI=address of string
;           DF=0
;
;        !! radix must be set previously by calling 'scanur'
;
;exit:      SI=updated to offset of first invalid character
;
;           CF=1
;            a numeric overflow has occurred, ie: the number being scanned
;           has become too big to fit into EAX
;
;           CF=0
;            if ZF=0 then a valid value was scanned, if ZF=1 then no
;           valid digits were scanned
;
;           EAX=converted value

;

scanu PROC NEAR
;
;preserve registers
;

        PUSH EDX
PUSH EBX
PUSH ECX
PUSH DI

;
;initialise
; EBX=radix constant
; EAX=total
; ECX=0, bits8-24 of ECX always=0 to pad byte digit to dword ; DI=holds original offset
;

        XOR EAX,EAX
XOR EBX,EBX
XOR ECX,ECX
MOV DI,SI
MOV BL,BYTE PTR CS:[scanuradi]

;
;main loop start
; EAX,ECX change roles so that we can use AL for the digit calculation ; saving code length
;
lop: XCHG EAX,ECX

LODSB
;
;if "0"-"9" map to 0-9 and skip to radix check ;

        SUB AL,030h
CMP AL,0Ah
JC SHORT ko
ADD AL,030h

;
;map "A"-"Z"-/"a"-"z"- to 10-35- aborting on the one invalid value (040h) ;that won't get trapped in the next stage ;

        AND AL,0DFh
SUB AL,037h
CMP AL,0Ah
JC SHORT ko2

;
;digit value checked that it is valid for the current radix ;this also weeds out previous invalid values (since they would be >35) ;jump out of loop is delayed so that EAX can be restored for exit ;

ko:     CMP AL,BL
CMC
ko2:    XCHG EAX,ECX
JC SHORT erriv

;
;accumalate the digit to the total. the total must be pre-multiplied. ;checks for overflow are done at both points so the routine can never ;generate false results
;

        MUL EBX
JC errovr
ADD EAX,ECX
JNC lop

;
;overflow error
; adjust SI index to current char and exit, note ; that CF =1 already
;
errovr: DEC SI

JMP SHORT don
;
;invalid character
; main exit point, SI is adjusted to the current char ; the CMP ensures that CF =0, and also that ZF =1 iff ; no chars have been read
;
erriv: DEC SI

CMP SI,DI
;
;(restore registers and exit)
;
don: POP DI

        POP ECX
POP EBX
POP EDX
RET

scanu ENDP

=========END OF CODE=======================================================