News:

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

Problem with atodw_ex

Started by jj2007, August 15, 2009, 01:46:51 AM

Previous topic - Next topic

hutch--

I can duplicate the problem with the following code, comment out the push and pop of EBX and it crashes. I found the 2004 test piece but it appears to have masked the problem.


; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

main proc

    push ebx

    mov _ebx, ebx
    mov _esi, esi
    mov _edi, edi
    mov _ebp, ebp
    mov _esp, esp

    fn atodw_ex, "1234567890"


    mov ebx_, ebx
    mov esi_, esi
    mov edi_, edi
    mov ebp_, ebp
    mov esp_, esp

    print "Before",13,10
    print str$(_ebx),13,10
    print str$(_esi),13,10
    print str$(_edi),13,10
    print str$(_ebp),13,10
    print str$(_esp),13,10,13,10

    print "After",13,10
    print str$(ebx_),13,10
    print str$(esi_),13,10
    print str$(edi_),13,10
    print str$(ebp_),13,10
    print str$(esp_),13,10,13,10

    pop ebx

    ret

main endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤


LATER: I just did the simple mod of going below EBP rather than above it. This appears to solve the problem at least in the following test piece. From memory (5 years ago) the algo was getting slugged by the stack usage so I avoided the PUSH / POP to keep the speed up. A probable rewrite without a stack frame is probably a better path as it may get the instance call overhead down.


; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    include \masm32\include\masm32rt.inc
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

comment * -----------------------------------------------------
                        Build this  template with
                       "CONSOLE ASSEMBLE AND LINK"
        ----------------------------------------------------- *

    EXTERNDEF decade :DWORD

    atodw_exx PROTO :DWORD

    .data?
      _ebx dd ?
      _esi dd ?
      _edi dd ?
      _ebp dd ?
      _esp dd ?

      ebx_ dd ?
      esi_ dd ?
      edi_ dd ?
      ebp_ dd ?
      esp_ dd ?


    .data
      item db "0001234567",0

    .code

start:
   
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    call main
    inkey
    exit

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

main proc

    LOCAL cnt   :DWORD

    mov cnt, 100000000


    mov _ebx, ebx
    mov _esi, esi
    mov _edi, edi
    mov _ebp, ebp
    mov _esp, esp

  @@:
    fn atodw_exx, "1234567890"
    sub cnt, 1
    jnz @B

    mov ebx_, ebx
    mov esi_, esi
    mov edi_, edi
    mov ebp_, ebp
    mov esp_, esp

    print "Before",13,10
    print "======",13,10
    print str$(_ebx),13,10
    print str$(_esi),13,10
    print str$(_edi),13,10
    print str$(_ebp),13,10
    print str$(_esp),13,10,13,10

    print "After",13,10
    print "=====",13,10
    print str$(ebx_),13,10
    print str$(esi_),13,10
    print str$(edi_),13,10
    print str$(ebp_),13,10
    print str$(esp_),13,10,13,10

    ret

main endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

align 4

atodw_exx proc lpstring:DWORD

    mov [ebp-4], edi

  ; ----------------------------------------------------
  ; unrolled StrLen algo to test up to 12 bytes for zero
  ; ----------------------------------------------------
    mov eax,lpstring                    ; get pointer to string
    lea edx,[eax+3]                     ; pointer+3 used in the end

    mov edi,[eax]                       ; read first 4 bytes
    add eax,4                           ; increment pointer
    lea ecx,[edi-01010101h]             ; subtract 1 from each byte
    not edi                             ; invert all bytes
    and ecx,edi                         ; and these two
    and ecx,80808080h
    jnz @F

    mov edi,[eax]                       ; read next 4 bytes
    add eax,4                           ; increment pointer
    lea ecx,[edi-01010101h]             ; subtract 1 from each byte
    not edi                             ; invert all bytes
    and ecx,edi                         ; and these two
    and ecx,80808080h
    jnz @F

    mov edi,[eax]                       ; read last 4 bytes
    add eax,4                           ; increment pointer
    lea ecx,[edi-01010101h]             ; subtract 1 from each byte
    not edi                             ; invert all bytes
    and ecx,edi                         ; and these two
    and ecx,80808080h

  @@:
    test ecx,00008080h                  ; test first two bytes
    jnz @F
    shr ecx,16                          ; not in the first 2 bytes
    add eax,2
  @@:
    shl cl,1                            ; use carry flag to avoid branch
    sbb eax,edx                         ; compute length
  ; -------------------------------------------

    mov edi, eax                        ; length in EDI
    mov edx, lpstring
    sub edx, 1

    xor eax, eax

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192]
    sub edi, 1
    jz atout

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192+40]
    sub edi, 1
    jz atout

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192+80]
    sub edi, 1
    jz atout

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192+120]
    sub edi, 1
    jz atout

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192+160]
    sub edi, 1
    jz atout

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192+200]
    sub edi, 1
    jz atout

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192+240]
    sub edi, 1
    jz atout

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192+280]
    sub edi, 1
    jz atout

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192+320]
    sub edi, 1
    jz atout

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192+360]

  atout:

    mov edi, [ebp-4]

    ret

atodw_exx endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

end start






Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

sinsi

#16

include \masm32\include\masm32rt.inc

.data
string db '1234',0

.code
myproc: invoke atodw_ex,offset string
        ret
start:  call myproc
        invoke ExitProcess,0

end start

Access violation on the ret from atodw_ex.

edit: wasn't there a thread about using the stack beyond locals/params?

To me this is a pretty major bug that needs to be addressed...
Light travels faster than sound, that's why some people seem bright until you hear them.

hutch--

Thats why I changed the algo and included the code. Your example called the library code, not the example I posted.


include \masm32\include\masm32rt.inc

    EXTERNDEF decade :DWORD

    atodw_exx PROTO :DWORD

    .data
    string db '1234567890',0
   
    .code

start:
    call myproc
    invoke ExitProcess,0

myproc:
    invoke atodw_exx,offset string
    retn


; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

align 4

atodw_exx proc lpstring:DWORD

    mov [ebp-4], edi

  ; ----------------------------------------------------
  ; unrolled StrLen algo to test up to 12 bytes for zero
  ; ----------------------------------------------------
    mov eax,lpstring                    ; get pointer to string
    lea edx,[eax+3]                     ; pointer+3 used in the end

    mov edi,[eax]                       ; read first 4 bytes
    add eax,4                           ; increment pointer
    lea ecx,[edi-01010101h]             ; subtract 1 from each byte
    not edi                             ; invert all bytes
    and ecx,edi                         ; and these two
    and ecx,80808080h
    jnz @F

    mov edi,[eax]                       ; read next 4 bytes
    add eax,4                           ; increment pointer
    lea ecx,[edi-01010101h]             ; subtract 1 from each byte
    not edi                             ; invert all bytes
    and ecx,edi                         ; and these two
    and ecx,80808080h
    jnz @F

    mov edi,[eax]                       ; read last 4 bytes
    add eax,4                           ; increment pointer
    lea ecx,[edi-01010101h]             ; subtract 1 from each byte
    not edi                             ; invert all bytes
    and ecx,edi                         ; and these two
    and ecx,80808080h

  @@:
    test ecx,00008080h                  ; test first two bytes
    jnz @F
    shr ecx,16                          ; not in the first 2 bytes
    add eax,2
  @@:
    shl cl,1                            ; use carry flag to avoid branch
    sbb eax,edx                         ; compute length
  ; -------------------------------------------

    mov edi, eax                        ; length in EDI
    mov edx, lpstring
    sub edx, 1

    xor eax, eax

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192]
    sub edi, 1
    jz atout

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192+40]
    sub edi, 1
    jz atout

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192+80]
    sub edi, 1
    jz atout

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192+120]
    sub edi, 1
    jz atout

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192+160]
    sub edi, 1
    jz atout

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192+200]
    sub edi, 1
    jz atout

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192+240]
    sub edi, 1
    jz atout

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192+280]
    sub edi, 1
    jz atout

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192+320]
    sub edi, 1
    jz atout

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192+360]

  atout:

    mov edi, [ebp-4]

    ret

atodw_exx endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

end start
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

dedndave

wouldn't it be better to:

        push    edi
.
.
.
        pop     edi

hutch--

Making it work is easy, when I originally wrote this one I was after speed and the stack calls slowed it up. It can be done qanother way but if its not fast, you may as well use the smaller one.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

sinsi

Yeah, the point is it trashes a part of the stack that can be used by other stuff.
Sorry hutch, but this is a major bug in part of the masm32 project...kudos to jj in finding it.

As dave said, as I've said, as others have said (sorry, me lazy MichaelW), it is a problem in a reproducible fashion. It is a coding error and should be fixed.
Light travels faster than sound, that's why some people seem bright until you hear them.

dedndave

the prologue/epilogue in this case probably looks like this:

        push    ebp
        mov     ebp,esp
.
.
.
        leave
        ret     4

we push ebp, a register not used other than for accessing lpstring 2 times, but not edi ?
it makes no sense to me why you would want to risk the contents of edi being lost because it is below [esp]
if you want no push's/pop's, you may as well do this:

        OPTION  PROLOGUE:NONE
        OPTION  EPILOGUE:NONE
.
.
        sub     esp,4
        mov     [esp],edi
        mov     eax,[esp+8]
.
.
.
        mov     edx,[esp+8]
.
.
.
        mov     edi,[esp]
        add     esp,4
        ret     4
.
.
        OPTION  PROLOGUE:PrologueDef
        OPTION  EPILOGUE:EpilogueDef

sinsi

Yeah, the problem I have is that it seems to be an 'option prologue:none' and then reconfigured with the 'lpstring' arg.
It's fucked though, with the [ebp+12] for sure.
Light travels faster than sound, that's why some people seem bright until you hear them.

hutch--

I did post the example for a reason, its called "proof". here is the output in hex.


Before
======
7FFDF000 ebx
00050004 esi
00000004 edi
0012FFBC ebp
0012FFB8 esp

After
=====
7FFDF000 ebx
00050004 esi
00000004 edi
0012FFBC ebp
0012FFB8 esp

Press any key to continue ...
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

sinsi

Sorry hutch, did you try this (proof) code from earlier?
Quote from: sinsi on August 15, 2009, 10:09:47 AM

include \masm32\include\masm32rt.inc

.data
string db '1234',0

.code
myproc: invoke atodw_ex,offset string
        ret
start:  call myproc
        invoke ExitProcess,0

end start

Access violation on the ret from atodw_ex.
Light travels faster than sound, that's why some people seem bright until you hear them.

dedndave

we need a new "invoke" macro...

        mov dword ptr [esp-4],parm3
        mov dword ptr [esp-8],parm2
        mov dword ptr [esp-12],parm1
        mov dword ptr [esp-16],RetLabel
        jmp     SomeFunction
RetLabel:
.
.
.
        OPTION  PROLOGUE:NONE
        OPTION  EPILOGUE:NONE

SomeFunction PROC

        mov     [esp-20],edi  ;save edi
        mov     [esp-24],esi  ;save esi
        mov     [esp-28],ebx  ;save ebx
.
.
        mov     ebx,[esp-12]  ;get parm1
        mov     esi,[esp-8]   ;get parm2
        mov     edi,[esp-4]   ;get parm3
.
.
        mov     ebx,[esp-28]  ;restore ebx
        mov     esi,[esp-24]  ;restore esi
        mov     edi,[esp-20]  ;restore edi
        jmp dword ptr [esp-16]

SomeFunction ENDP

        OPTION  PROLOGUE:PrologueDef
        OPTION  EPILOGUE:EpilogueDef

hutch--

Yes as a matter of fact, thats why the algo in the code I posted id DIFFERENT, it has "xx" at the end of it. You have kept testing the version that is broken that I reproduced in a test piece.

To keep everyone hap-py, mainly myself, here is a version with the stack frame removed and a global used to store the register. Its about 7 - 8% faster without the stack frame and faster means better here.

NOTE this version has two algos, the "xx" version and the faster "xxx" version.


; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    include \masm32\include\masm32rt.inc
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

comment * -----------------------------------------------------
                        Build this  template with
                       "CONSOLE ASSEMBLE AND LINK"
        ----------------------------------------------------- *

    EXTERNDEF decade :DWORD

    atodw_exx  PROTO :DWORD
    atodw_exxx PROTO :DWORD

    .data?
      _ebx dd ?
      _esi dd ?
      _edi dd ?
      _ebp dd ?
      _esp dd ?

      ebx_ dd ?
      esi_ dd ?
      edi_ dd ?
      ebp_ dd ?
      esp_ dd ?


    .data
      item db "0001234567",0

    .code

start:
   
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    call main
    inkey
    exit

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

main proc

    counter equ <100000000>

    LOCAL cnt   :DWORD

    REPEAT 4

  ; ================================================

    mov cnt, counter

    invoke GetTickCount
    push eax

    mov _ebx, ebx
    mov _esi, esi
    mov _edi, edi
    mov _ebp, ebp
    mov _esp, esp

  @@:
    fn atodw_exx, "1234567890"
    sub cnt, 1
    jnz @B

    mov ebx_, ebx
    mov esi_, esi
    mov edi_, edi
    mov ebp_, ebp
    mov esp_, esp

    invoke GetTickCount
    pop ecx
    sub eax, ecx

    print str$(eax)," ms with stack frame",13,10

  ; ================================================

    mov cnt, counter

    invoke GetTickCount
    push eax

    mov _ebx, ebx
    mov _esi, esi
    mov _edi, edi
    mov _ebp, ebp
    mov _esp, esp

  @@:
    fn atodw_exxx, "1234567890"
    sub cnt, 1
    jnz @B

    mov ebx_, ebx
    mov esi_, esi
    mov edi_, edi
    mov ebp_, ebp
    mov esp_, esp

    invoke GetTickCount
    pop ecx
    sub eax, ecx

    print str$(eax)," ms no stack frame",13,10

  ; ================================================

    ENDM

    print "Before",13,10
    print "======",13,10
    print hex$(_ebx)," ebx",13,10
    print hex$(_esi)," esi",13,10
    print hex$(_edi)," edi",13,10
    print hex$(_ebp)," ebp",13,10
    print hex$(_esp)," esp",13,10,13,10

    print "After",13,10
    print "=====",13,10
    print hex$(ebx_)," ebx",13,10
    print hex$(esi_)," esi",13,10
    print hex$(edi_)," edi",13,10
    print hex$(ebp_)," ebp",13,10
    print hex$(esp_)," esp",13,10,13,10

    ret

main endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

align 4

OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE

atodw_exxx proc lpstring:DWORD

    .data?
      align 4
      @@var@@ dd ?
    .code

    mov @@var@@, edi

  ; ----------------------------------------------------
  ; unrolled StrLen algo to test up to 12 bytes for zero
  ; ----------------------------------------------------
    mov eax,[esp+4]                     ; get pointer to string
    lea edx,[eax+3]                     ; pointer+3 used in the end

    mov edi,[eax]                       ; read first 4 bytes
    add eax,4                           ; increment pointer
    lea ecx,[edi-01010101h]             ; subtract 1 from each byte
    not edi                             ; invert all bytes
    and ecx,edi                         ; and these two
    and ecx,80808080h
    jnz @F

    mov edi,[eax]                       ; read next 4 bytes
    add eax,4                           ; increment pointer
    lea ecx,[edi-01010101h]             ; subtract 1 from each byte
    not edi                             ; invert all bytes
    and ecx,edi                         ; and these two
    and ecx,80808080h
    jnz @F

    mov edi,[eax]                       ; read last 4 bytes
    add eax,4                           ; increment pointer
    lea ecx,[edi-01010101h]             ; subtract 1 from each byte
    not edi                             ; invert all bytes
    and ecx,edi                         ; and these two
    and ecx,80808080h

  @@:
    test ecx,00008080h                  ; test first two bytes
    jnz @F
    shr ecx,16                          ; not in the first 2 bytes
    add eax,2
  @@:
    shl cl,1                            ; use carry flag to avoid branch
    sbb eax,edx                         ; compute length
  ; -------------------------------------------

    mov edi, eax                        ; length in EDI
    mov edx, [esp+4]
    sub edx, 1

    xor eax, eax

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192]
    sub edi, 1
    jz atout

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192+40]
    sub edi, 1
    jz atout

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192+80]
    sub edi, 1
    jz atout

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192+120]
    sub edi, 1
    jz atout

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192+160]
    sub edi, 1
    jz atout

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192+200]
    sub edi, 1
    jz atout

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192+240]
    sub edi, 1
    jz atout

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192+280]
    sub edi, 1
    jz atout

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192+320]
    sub edi, 1
    jz atout

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192+360]

  atout:

    mov edi, @@var@@

    ret 4

atodw_exxx endp

OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef


; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

align 4

atodw_exx proc lpstring:DWORD

    mov [ebp-4], edi

  ; ----------------------------------------------------
  ; unrolled StrLen algo to test up to 12 bytes for zero
  ; ----------------------------------------------------
    mov eax,lpstring                    ; get pointer to string
    lea edx,[eax+3]                     ; pointer+3 used in the end

    mov edi,[eax]                       ; read first 4 bytes
    add eax,4                           ; increment pointer
    lea ecx,[edi-01010101h]             ; subtract 1 from each byte
    not edi                             ; invert all bytes
    and ecx,edi                         ; and these two
    and ecx,80808080h
    jnz @F

    mov edi,[eax]                       ; read next 4 bytes
    add eax,4                           ; increment pointer
    lea ecx,[edi-01010101h]             ; subtract 1 from each byte
    not edi                             ; invert all bytes
    and ecx,edi                         ; and these two
    and ecx,80808080h
    jnz @F

    mov edi,[eax]                       ; read last 4 bytes
    add eax,4                           ; increment pointer
    lea ecx,[edi-01010101h]             ; subtract 1 from each byte
    not edi                             ; invert all bytes
    and ecx,edi                         ; and these two
    and ecx,80808080h

  @@:
    test ecx,00008080h                  ; test first two bytes
    jnz @F
    shr ecx,16                          ; not in the first 2 bytes
    add eax,2
  @@:
    shl cl,1                            ; use carry flag to avoid branch
    sbb eax,edx                         ; compute length
  ; -------------------------------------------

    mov edi, eax                        ; length in EDI
    mov edx, lpstring
    sub edx, 1

    xor eax, eax

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192]
    sub edi, 1
    jz atout

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192+40]
    sub edi, 1
    jz atout

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192+80]
    sub edi, 1
    jz atout

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192+120]
    sub edi, 1
    jz atout

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192+160]
    sub edi, 1
    jz atout

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192+200]
    sub edi, 1
    jz atout

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192+240]
    sub edi, 1
    jz atout

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192+280]
    sub edi, 1
    jz atout

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192+320]
    sub edi, 1
    jz atout

    movzx ecx, BYTE PTR [edx+edi]
    add eax, [ecx*4+decade-192+360]

  atout:

    mov edi, [ebp-4]

    ret

atodw_exx endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

end start



Here are the timings with the PUSH POP code added. Its a clear 10% slower than the no stack frame version.


1640 ms with stack frame
1500 ms no stack frame
1641 ms with stack frame
1484 ms no stack frame
1641 ms with stack frame
1703 ms no stack frame
1641 ms with stack frame
1500 ms no stack frame
Before
======
7FFDF000 ebx
00050004 esi
00000004 edi
0012FFBC ebp
0012FFB4 esp

After
=====
7FFDF000 ebx
00050004 esi
00000004 edi
0012FFBC ebp
0012FFB4 esp

Press any key to continue ...

Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

sinsi

hutch, a simple push/pop is all that is needed, n'est pas?
The code that you have included in the masm32 project is wrong, it doesn't matter how many x's you put on the end of the function name...
I'm not (not) having a go at you, but the function trashes a part of the stack that it shouldn't access.
Light travels faster than sound, that's why some people seem bright until you hear them.

hutch--

sinsi,

I have posted TWO (2) different versions since the error was found and that is after verifying that the original was an error by reproducing it.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

jj2007

Masm32 Security Advisory (15082009)
Vulnerability in atodw_ex Could Allow Remote Code Execution

Published: August 15, 2009

Hutch has completed the investigation into a public report of this vulnerability. We have issued SH15082009 to address this issue. For more information about this issue, including download links for an available security update, please contact Steve Hutchesson. The vulnerability addressed is the stack corruption when using atodw_ex.
:bg