News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

atol, atodw and negative numbers

Started by jj2007, April 15, 2009, 02:12:43 PM

Previous topic - Next topic

jj2007

I seem to have difficulties to interpret the MasmLib help correctly. When I pass a string starting with a minus sign to atol and atodw, I get rubbish:

Positive, atodw:        12345
Positive, atol:         12345
Negative, atodw:        25312345
Negative, atol:         -112345


Any explanation for this?

Thanks,
jj

include \masm32\include\masm32rt.inc

.code
StrPos db "12345", 0
StrNeg db "-12345", 0

start:
print "Positive, atodw: ", 9
invoke atodw, offset StrPos
print str$(eax), 13, 10
print "Positive, atol:  ", 9
invoke atol, offset StrPos
print str$(eax), 13, 10

print "Negative, atodw: ", 9
invoke atodw, offset StrNeg
print str$(eax), 13, 10
print "Negative, atol:  ", 9
invoke atol, offset StrNeg
print str$(eax), 13, 10

getkey
exit

end start

Jimg

Running your code unchanged, atol works properly for me.
Clearly, atodw is not meant for signed strings, and should be documented as such.

drizz

atodw proc:

   cmp al, 2D
   jne proceed


should be 2DH or
cmp al, '-'
The truth cannot be learned ... it can only be recognized.

jj2007

Quote from: Jimg on April 15, 2009, 02:51:33 PM
Running your code unchanged, atol works properly for me.

I get an extra 1:
Negative, atol:         -112345

My atol.asm has 1327 bytes, 13.08.2006

EDIT: Ze bug is here:

atol proc lpSrc:DWORD
    xor eax, eax                ; zero EAX
    mov edx, [esp+4]
    movzx ecx, BYTE PTR [edx]
    add edx, 1

    cmp ecx, "-"                ; test for sign
    jne lbl0
    add eax, 1                  ; set EAX if sign
   
   if 1   ; corrected
      movzx ecx, BYTE PTR [edx+1]
      add edx, 2
   else   ; original
      movzx ecx, BYTE PTR [edx]
      add edx, 1
   endif

  lbl0:
    push eax                    ; store sign on stack
...

Jimg

Mine is 1445 bytes from 28 may 2008.

Time to update.

It still works and looks like-
atol proc lpSrc:DWORD

    xor eax, eax                ; zero EAX
    mov edx, [esp+4]
    movzx ecx, BYTE PTR [edx]
    add edx, 1
    cmp ecx, "-"                ; test for sign
    jne lbl0
    add eax, 1                  ; set EAX if sign
    movzx ecx, BYTE PTR [edx]
    add edx, 1

  lbl0:
    push eax                    ; store sign on stack
    xor eax, eax                ; so eax*10 will be 0 for first digit

  lbl1:
    sub ecx, 48
    jc  lbl2
    lea eax, [eax+eax*4]        ; mul eax by 5
    lea eax, [ecx+eax*2]        ; mul eax by 2 and add digit value
    movzx ecx, BYTE PTR [edx]   ; get next digit
    add edx, 1
    jmp lbl1

  lbl2:
    pop ecx                     ; retrieve sign
    test ecx, ecx
    jnz lbl3
    ret 4

  lbl3:
    neg eax                     ; negative return value is sign set
    ret 4

atol endp

Jimg

Good catch Drizz, (and jj).  Hard to believe it's been around this long with that error.

PBrennick

Very nice catch, JJ. I think it needs to be fixed via the next service pack. I guess not many people have been passing negative numbers to that algo else it may have been caught sooner. You are a very meticulous individual.

Paul
The GeneSys Project is available from:
The Repository or My crappy website

mitchi

These are my results here :

Positive, atodw:        12345
Positive, atol:         12345
Negative, atodw:        25312345
Negative, atol:         -12345








jj2007

#8
I found a newer version on my other machine...

Just for fun:

Intel(R) Celeron(R) M CPU        420  @ 1.60GHz (SSE3)

31      cycles for atodjj, offset StrNeg
45      cycles for atol,   offset StrNeg

31      cycles for atodjj, offset StrNeg
45      cycles for atol,   offset StrNeg

31      cycles for atodjj, offset StrPos
57      cycles for atol,   offset StrPos
45      cycles for atodw,  offset StrPos

31      cycles for atodjj, offset StrPos
57      cycles for atol,   offset StrPos
43      cycles for atodw,  offset StrPos

Positive, atodw:        123456789
Positive, atol:         123456789
Positive, atodjj:       123456789
Negative, atol:         -123456789
Negative, atodjj:       -123456789

Code sizes:
atodjj:         58
atol:           61
a2dw:           71


EDIT: A bit of shuffling, an unrolled loop - and voilà, it's speeding up :bg

[attachment deleted by admin]

lingo

New results:  :lol

Intel(R) Core(TM)2 Duo CPU     E8500  @ 3.16GHz (SSE4)

22      cycles for atodjj, offset StrNeg
18      cycles for a2dLingo, offset StrNeg
40      cycles for atol,   offset StrNeg

22      cycles for atodjj, offset StrNeg
18      cycles for a2dLingo, offset StrNeg
40      cycles for atol,   offset StrNeg

22      cycles for atodjj, offset StrPos
18      cycles for a2dLingo, offset StrPos
38      cycles for atol,   offset StrPos
39      cycles for atodw,  offset StrPos

22      cycles for atodjj, offset StrPos
18      cycles for a2dLingo, offset StrPos
38      cycles for atol,   offset StrPos
42      cycles for atodw,  offset StrPos

Positive, atodw:         123456789
Positive, a2dLingo:      123456789
Positive, atol:          123456789
Positive, atodjj:        123456789
Negative, atol:         -123456789
Negative, atodjj:       -123456789
Negative, a2dLingo:     -123456789

Code sizes:
atodjj:         58
a2dLingo:      113
atol:           61
a2dw:           71

[attachment deleted by admin]

jj2007

Not bad, my young friend, although it's a bit bloated, and on my archaic CPU it's on average a cycle slower :green

:U

              Intel(R) Pentium(R) 4 CPU 3.40GHz (SSE3)

57      cycles for atodjj, offset StrNeg
54      cycles for a2dLingo, offset StrNeg
52      cycles for atol,   offset StrNeg

53      cycles for atodjj, offset StrNeg
54      cycles for a2dLingo, offset StrNeg
52      cycles for atol,   offset StrNeg

51      cycles for atodjj, offset StrPos
53      cycles for a2dLingo, offset StrPos
52      cycles for atol,   offset StrPos
59      cycles for atodw,  offset StrPos

51      cycles for atodjj, offset StrPos
55      cycles for a2dLingo, offset StrPos
52      cycles for atol,   offset StrPos
59      cycles for atodw,  offset StrPos

Positive, atodw:        123456789
Positive, a2dLingo:     123456789
Positive, atol:         123456789
Positive, atodjj:       123456789
Negative, atol:         -123456789
Negative, atodjj:       -123456789
Negative, a2dLingo:     -123456789

Code sizes:
atodjj:         58
a2dLingo:       113
atol:           61
a2dw:           71

MichaelW

I split this topic and put the parts that definitely do not belong in the Campus here:

http://www.masm32.com/board/index.php?topic=11280.0
eschew obfuscation