I want to change "negative" Strings to Longwords.
The function atodw only works ok with "positive" Strings.
I need a atodw function, that converts e.g. the string "-2519" to -2519, and not to 2532519 ???
Can you please help ?

Posted on 2003-10-18 08:46:57 by Nordwind64
Use a neg afterwards if you know that the integer is below zero.

BufferOfText contains: "-2159",0

.IF b$ == "-"
invoke atodw, offset BufferOfText+1
neg eax
invoke atodw, offset BufferOfText
Posted on 2003-10-18 09:08:14 by JimmyClif
As JimmyClif said you hae only to make a slight mod to the atodw function to have it support signs:
atodws proc String:DWORD

mov eax,String
mov al,[eax]
.IF al == "-"
inc String
push TRUE
.ELSEIF al == "+"
inc String
push FALSE
push FALSE
; ----------------------------------------
; Convert decimal string into dword value
; return value in eax
; ----------------------------------------

push esi
push edi

xor eax, eax
mov esi, [String]
xor ecx, ecx
xor edx, edx
mov al, [esi]
inc esi
cmp al, 2D
jne proceed
mov al, byte ptr [esi]
not edx
inc esi
jmp proceed

sub al, 30h
lea ecx, dword ptr [ecx+4*ecx]
lea ecx, dword ptr [eax+2*ecx]
mov al, byte ptr [esi]
inc esi

or al, al
jne @B
lea eax, dword ptr [edx+ecx]
xor eax, edx

pop edi
pop esi

pop ecx
.IF ecx
neg eax


atodws endp
Posted on 2003-10-18 10:11:09 by donkey

I need a atodw function, that converts e.g. the string "-2519" to -2519, and not to 2532519 ???

sorry, JimmyClif. With your method in my example I got -2532519 !!!

Donkey: I read about atodw function from The Svin. Is that the function you use ? I'll test the code.

Posted on 2003-10-18 14:51:48 by Nordwind64
Hi Nordwind64,

I usually use atodw, it is part of the MASM32 library but you are right that it does not do signs. The routine I posted is just a quick patch of that function to add support for signed strings. It should work as there is no change to the actual conversion routine except to strip off the sign if any.
Posted on 2003-10-18 15:08:53 by donkey
I normally write my own routines (procedures) for converting alphanumeric input from other users instead of relying on procedures written by someone else. Although it may add a slight overhead, I always allow for the possibility of leading spaces. I thus test the start of the string for leading spaces and skip over them to prevent erroneous results and make the program a little more user friendly.

Posted on 2003-10-18 23:57:25 by Raymond
For user input I almost always use GetDlgItemInt, it is certainly slow but I'm waiting for input anyway or I will use numeric only edit controls (my own not the ES_NUMBER ones). I always assume that internal stuff will be preformatted so I don't worry too much about formatting the string before hand but I agree that it is a good idea to strip leading spaces.
Posted on 2003-10-19 00:59:31 by donkey


donkey: Sorry, your code don't work correct, after some modifications of my code with your idea , it works now :tongue:

Raymond: You're right. I'm testing for leading spaces, too.

New problem. what about strings with decimal numbers, e.g. "-1047.58" ?
I found a solution, but the number of decimals have only the same for all numbers...
I think, somebody should rewrite atodw for negative and decimal numbers... And not I - please a really good asm-coder.

Posted on 2003-10-19 06:10:25 by Nordwind64
Hi Nordwind64,

I would be interested to know what doesn't work in the code I posted, it looks ok on a glance.
Posted on 2003-10-19 09:23:26 by donkey
You must realise that atodw is intended for just converting strings (ie in decimal but without any decimal place) to dword. A tool has its own purpose, you do not use hammer to screw in a screw. Use some other tools for that purpose, maybe the ones coded by raymond in his fpu library.
Posted on 2003-10-19 09:26:32 by roticv
I think what is needed here is a seperate algo "atolong" or similar that is designed to deal with signed numbers. The "atodw" is actually designed to handle unsigned integers so it is not an error that it will not handle signed values.

Anyone who feels like writing a bulletproof and rocket fast ascii to LONG algo is welcome and I will be happy enough to add it to the MASM32 libray next release.

Posted on 2003-10-19 09:31:39 by hutch--
Using the ES_NUMBER style edit control is great to avoid unacceptable characters in the input. However, this cannot be used when you can also expect negative numbers as input. You cannot use the "-" character with ES_NUMBER.

A proper "atodw" routine should thus also have error checking. The programmer must NOT "assume" that an unknown user will always provide an acceptable input. Simply imagine how an input of 23.4 would get converted with the supplied "atodw" or "a2dw" routines in the M32lib.


You would use a procedure such as "atodw" ONLY IF you expect the input of an integer number. If the input can be a string containing decimals, you would normally want to convert it to a floating point format or some other fixed point decimal format.

If you need a procedure for converting from alphanumeric to the standard floating point format, you can find one (FpuAtoFL) in the Fpulib supplied with MASM32v8. The source code is also available so you can see the type of error checking being performed for that function.

Posted on 2003-10-19 10:01:16 by Raymond

Using the ES_NUMBER style edit control is great to avoid unacceptable characters in the input. However, this cannot be used when you can also expect negative numbers as input. You cannot use the "-" character with ES_NUMBER.

Hi Raymond,

I don't use ES_NUMBER, I have my own subclassed edit code that I use instead (as I said in my post).
Posted on 2003-10-19 10:10:43 by donkey
Thanks guys !

donkey: I cannot say, what get wrong in your code. I use/need the converter function for sorting my listviews (with iczelions codesample), and with your code the sorting was wrong... sorry. Could be my error...?

Raymond: Thanks for giving me the Fpulib idea, but it's a little bit slow for sorting listviews...

hutch--: Yes !!! Can you please post the function, I anybody finished a a2long function ?

Thanks alot,
Posted on 2003-10-19 14:08:55 by Nordwind64
The routine works perfectly as posted, I ran it through every possible combination of data and it did not fail:
numfmt	BYTE	"%i",0

numbuf BYTE 256 DUP (0)

mov eax,0FFFFFFFh

push eax
invoke wsprintf,OFFSET numbuf,OFFSET numfmt,eax
invoke atodws,OFFSET numbuf
mov ecx,eax
pop eax
.IF ecx != eax
PrintText "error"
dec eax
.until eax == -0FFFFFFFh

Took a while though :)
Posted on 2003-10-19 15:15:21 by donkey
The following sa2long procedure should cover the conversion of a null-terminated source string to a signed DWORD with full error checking.

A similar procedure could be prepared for "unsigned" string conversions with full error checking if required.

One problem I have observed is that such procedures may often be suggested to newbies without telling them about their limitations. Use that!!! It's in the library!!!:rolleyes:


; #####################################

; sa2long
; Written by
; Raymond Filiatreault
; October, 2003

; This procedure converts an alphanumeric string to a signed DWORD.
; It allows leading spaces and a "-" or "+" sign in the string.
; The binary result is returned in EAX if no error is detected.
; It returns the value of 80000000h in EAX if one of the following errors
; is detected:
; - the string does not contain any numerical digit;
; - the string contains unacceptable characters;
; - the absolute value of the result would exceed the upper limit of
; 7FFFFFFFh for the absolute value of a signed DWORD
; All registers preserved except EAX
; Requires a pointer to a null-terminated source string as the parameter

.model flat, stdcall
option casemap :none ; case sensitive


; #####################################

sa2long proc public uses esi ecx edx lpSource:DWORD

mov esi,lpSource
xor eax,eax
xor ecx,ecx ;to be used as an accumulator
xor edx,edx ;to hold sign flag

mov al,[esi]
inc esi
cmp al," "
jz @B ;skip all leading spaces

;check for a sign and keep result in EDX

.if al == "-"
inc edx ;sets bit0 if negative
mov al,[esi]
inc esi
.elseif al == "+"
mov al,[esi]
inc esi

;check next character for end of string without numerical input

or al,al
jnz @F

mov eax,80000000h
jmp sa_exit

sub al,"0"
jc sa_error ;unacceptable non-numerical character
cmp al,9
ja sa_error ;unacceptable non-numerical character

; At this point, the cumulative value in ECX must be multiplied by 10.
; As a preventive measure against overflow, it is compared to 10000000h.
; If it is higher, the result could have caused an overflow or
; have become a negative DWORD, neither being acceptable.
; (The lea instruction used for multiplication and addition
; never modifies the flag register.)

cmp ecx,10000000h
jae sa_error
lea ecx,[ecx+ecx*4] ;multiplies the value in ECX by 5
lea ecx,[eax+ecx*2] ;multiplies again by 2 and adds EAX

mov al,[esi] ;get next character
inc esi
or al,al ;check for terminating 0
jz @F
jmp @B ;process next character

or ecx,ecx ;last check for unacceptable negative number
js sa_error
mov eax,ecx
shr edx,1 ;bit0 would have been set if negative
jnc sa_exit
neg eax

sa2long endp

; #####################################

Posted on 2003-10-20 13:20:24 by Raymond
Thank you !!!

Posted on 2003-10-21 23:49:57 by Nordwind64

This is a form of addiction but it will make your leading blank stripper a bit faster.

replace this,

mov al,[esi]
inc esi
cmp al," "
jz @B

with this

add esi, 1 ; add is preferred for PIV
cmp BYTE PTR [esi], 32
je @B


hutch at movsd dot com
Posted on 2003-10-22 01:21:16 by hutch--
I'm not sure about what Intel manual says in this case. inc is discouraged when the next instruction reads the flag register. I think Raymond's code is just fine as it is, for his code does not read eflags right after inc.

Anoter part to improve the speed is to eliminate one Jcc at the end. This can be done by dec edx instead of inc edx to indicate the negative number, and, then, before return, we can xor eax,edx/sub eax,edx to obtain the negative number, instead of shr edx,1/jnc sa_exit/neg eax. (And shorter code, too.)

And, if one is really concerned about Pentium 4, then lea might not be the best method of multiplication in this case.
Posted on 2003-10-22 03:16:11 by Starless
This is a form of addiction but ....
I don't think anyone would disagree.:grin:

We should not loose sight of the fact that this procedure would be used for converting user input which may have taken several seconds (or minutes). Worried about saving a few nanoseconds? :o

If those nanoseconds are SO important, a much more significant saving can be obtained by scraping the procedure altogether and write it as inline code.:alright:

If such procedure would also be adopted for the M32lib (or any other public lib), it would generally be used by "newbies" and should therefore be kept as simple as possible for educational purposes. We should certainly not encourage newbies to waste their time (and get addicted:tongue: ) on optimizing the conversion of user input.

And we know what optimization did for the atodw procedure! KISS

Posted on 2003-10-22 10:15:55 by Raymond