Can somebody tell me why this does not work? I looked at a dump and it seems like invoking "atoi" is trying to push a word-sized value when the string address should be a dword.

Any ideas? : (

.386
.model flat, stdcall
option casemap :none

include windows.inc
include kernel32.inc
include user32.inc

includelib user32.lib
includelib kernel32.lib

.DATA
MsgCaption byte "Helloooo George!", 0
MsgConvert byte "12345", 0

.CODE
atoi proc StringLoc:dword
push esi
lea esi, StringLoc
xor eax, eax
conv_loop:
xor edx, edx ; clear previous character
mov dl, byte ptr
cmp dl, 0 ; null character?
je atoi_end
cmp dl, 30h ; compare character to ASCII '0'
jb atoi_error ; below character '0'? outta here!
cmp dl, 39h ; compare character to ASCII '9'
ja atoi_error ; above ASCII '9'? outta here!
sub dl, 30h
add eax, edx
inc esi
jmp conv_loop
atoi_error:
mov eax, 1
sub eax, 2 ; this should set some flags, worry about it later
atoi_end:
pop esi
atoi endp

MAIN:

SHOW_MESSAGEBOX:
invoke atoi, addr MsgConvert
cmp eax, 12345
je MainExit
invoke MessageBox, NULL, addr MsgConvert, addr MsgCaption, MB_OK OR MB_SYSTEMMODAL

MainExit:
invoke ExitProcess, 0
end MAIN
Posted on 2002-05-07 12:07:13 by Citrus538
atoi proc StringLoc:dword

push esi
[b]mov[/b] esi, StringLoc
Address was put on the stack - LEA would get the address of the parameter on the stack, not the parameter (which is an address).
Posted on 2002-05-07 12:12:27 by bitRAKE
You know what?

I changed it and saved in a new file. Compiled, and still didn't work.

Turns out I was running the old executable. Ran the newly named EXE and worked perfectly. : ) Thanks.
Posted on 2002-05-07 12:25:11 by Citrus538
You may also want a ret in your code, and I think you should also be multiplying eax by 10 at some point too (add eax, eax / lea eax, eax*4 + eax).

Mirno
Posted on 2002-05-07 12:49:22 by Mirno
Yes, I added a ret and neglected to mention it.

But where would I want to multiply eax by 10? It seems to work after changing lea to mov and adding a ret. . .

DUH, I see it now. . . : )
Posted on 2002-05-07 15:34:16 by Citrus538
This mistake is somewhat common (i still do it once in a while), but a good way of avoiding it is coming up and following a naming convention.

I personally like using 'lp' (for long pointer) before the name of a parameter if its to be an address:

atoi proc lpStringLoc:dword

Other people like thier own ways, but the thought is the same. Ernie i believe like using just p's (for pointer). This is because his COM work often involves many levels of pointing:

ppInterface --> long pointer to a long pointer to an interface handle. (this tells him in code that he has a pointer to start with, and has to go through another level of abstraction just to get to the actual data (interface handle).

This is extreme i will admit, most pointing is one level deep, but following a naming convetion that reflects this abstraction can help you *alot* when your up to your knees in code. ;)

Enjoy..
:alright:
NaN
Posted on 2002-05-07 17:12:36 by NaN
Ah yes, the horrors of Hungarian notation.

Anyways, it still does not work. Attached is the updated code.
Posted on 2002-05-07 17:18:13 by Citrus538
You loop needs more work:
conv_loop:

mov dl, byte ptr [esi]
cmp dl, 0 ; null character?
je atoi_end
cmp dl, 30h ; compare character to ASCII '0'
jb atoi_error ; below character '0'? outta here!
cmp dl, 39h ; compare character to ASCII '9'
ja atoi_error ; above ASCII '9'? outta here!
sub dl, 30h
mul edi ; make room for the next digit!
add eax, edx
inc esi
jmp conv_loop


It all looks good (didnt test it), but the multiply by edi=10 and add edx to eax is wrong.

try this:
  xor ecx, ecx  ; Final Answer in ECX

conv_loop:
mov dl, byte ptr [esi]
cmp dl, 0 ; null character?
je atoi_end
cmp dl, 30h ; compare character to ASCII '0'
jb atoi_error ; below character '0'? outta here!
cmp dl, 39h ; compare character to ASCII '9'
ja atoi_error ; above ASCII '9'? outta here!
sub dl, 30h
mov eax, edx
xor edx, edx
mul edi ; make room for the next digit!
add ecx, eax
inc esi
jmp conv_loop


The multiply changes EDX and EAX contents! So im storing the answer in ECX.
Posted on 2002-05-07 18:59:19 by NaN
I *think*that code above just multiplies each digit by 10 (e.g. 5 -> 50) and adds it to the result. So the string "123" would be 10+20+30 == 60. I could be wrong though.

I modified my loop, but it still does not work:

xor ecx, ecx ; Stores result
xor eax, eax ; Temp used to multiply result by 10
xor edx, edx ; We MOV to DL but there may be some other bits set EDX, clear them!

conv_loop:
mov dl, byte ptr
cmp dl, 0 ; null character?
je atoi_end

cmp dl, 30h ; compare character to ASCII '0'
jb atoi_error ; below character '0'? outta here!
cmp dl, 39h ; compare character to ASCII '9'
ja atoi_error ; above ASCII '9'? outta here!

sub dl, 30h ; char '0' == 30h, we want char '0' == 00h

mov eax, ecx ; store result to append 0
mov ecx, edx ; store the char to append

mul edi ; make room for next digit, clobbers eax and edx
add ecx, eax ; eax had result, ecx had current character: now ecx has result including cur digit
inc esi ; move to next character
jmp conv_loop
Posted on 2002-05-07 20:43:54 by Citrus538
Sorry your right, it does. I did it hastily, as my GF was on my backt to get groceries ;)

Here is how i would go about it:


atoi PROC USES ESI lpszNum:DWORD

mov esi, lpszNum ; Get the String Address
xor ecx, ecx ; ECX == 0 (accumulates answer)
xor eax, eax ; EAX == 0 (data holding reg )
@@:
mov al, [esi] ; Get al -> 000000XX h
cmp eax, NULL ; see if its zero (NULL)
je @Done ; Yes, then done
sub eax, 30h ; Strip hex number
js @Error ; if NOW less than zero ERROR( <30h )
cmp eax, 0Ah ; compare to 0Ah (10)
jns @Error ; if still postve, then ERROR( >30h )
imul ecx, 10 ; shift accumulated by base 10
add ecx, eax ; add new "ones" amount ( 000000AL h)
inc esi ; Onto next string digit.
jmp @B
@Done:
mov eax, ecx ; mov accumulated to eax
ret ; and return binary integer

@Error:
xor eax, eax ; eax == 00000000 h
dec eax ; eax == FFFFFFFF h (neg 1)
ret
atoi ENDP


Sorry for the shoddy help ;)
:NaN:
Posted on 2002-05-07 22:23:08 by NaN
Why do u use imul? Since imul is for signed multiply, but you couldn't parse anything that would be signed right?

A '-' would cause your loop to fail at:
jns @Error ; if still postve, then ERROR( >30h )


I know that you could handle the '-' properly but I was mainly wondering about the difference between imul and mul in this bit of code.

Is there something here that I'm not seeing correctly?

Thanks,
gorshing
Posted on 2002-07-11 16:15:21 by gorshing
Can't remember if i wrote it by myself or not.
Signed atosi and unsigned atoi versions.
Both expect dec digits in string.



atosi proc pString:LPSTR

option PROLOGUE:NONE
option EPILOGUE:NONE

push esi

xor eax, eax
mov esi, [esp + sizeof DWORD * 2]

xor ecx, ecx
mov al, [esi]
xor edx, edx

cmp al, "-"
jne @F
inc esi
not edx
jmp @F

atosi_loop:
inc esi
lea ecx, [ecx + ecx*4]
lea ecx, [eax + ecx*2]
@@:
mov al, [esi]
sub al, "0"
jns atosi_loop

lea eax, [edx + ecx]
pop esi
xor eax, edx

ret sizeof DWORD

option PROLOGUE:PROLOGUEDEF
option EPILOGUE:EPILOGUEDEF

atosi endp

;::::::::::::::::::::::::::

atoi proc pString:LPSTR

option PROLOGUE:NONE
option EPILOGUE:NONE

push esi
xor eax, eax
mov esi, [esp + sizeof DWORD * 2]
xor ecx, ecx
jmp @F

atoi_loop:
inc esi
lea ecx, [ecx + ecx*4]
lea ecx, [eax + ecx*2]
@@:
mov al, [esi]
sub al, "0"
jns atoi_loop

pop esi
mov eax, ecx

ret sizeof DWORD

option PROLOGUE:PROLOGUEDEF
option EPILOGUE:EPILOGUEDEF

atoi endp
Posted on 2002-07-12 03:57:34 by Four-F