News:

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

invoke bug

Started by ecube, March 25, 2009, 02:33:26 AM

Previous topic - Next topic

ecube

"the infamous "invoke" bug: using invoke with variables of type BYTE
      (or WORD in 32bit code) causes bad code to be generated in MASM."

anyone know about this, and can confirm/deny/elaborate? i've never experienced this bug that i'm aware of, but I use invoke a lot actually with byte so it has me uncomfotable.

MichaelW

As far as I know, the "bug" is in the use of AL as a scratch register when passing a byte memory operand or 8-bit register other than AL.

CORRECTION: for 8-bit memory operands, eax is use as a scratch register.


; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    .data
      b db 123
    .code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
test1 proc arg:BYTE
    ret
test1 endp

test2 proc arg:BYTE
    movzx eax, arg
    ret
test2 endp
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    mov al, 255
    mov bl, 123
    invoke test1, bl
    movzx eax, al
    print ustr$(eax),13,10

    mov al, 255
    mov bl, 123
    invoke test1, b
    movzx eax, al
    print ustr$(eax),13,10

    mov bl, 123
    invoke test2, bl
    print ustr$(eax),13,10

    inkey "Press any key to exit..."
    exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start


123
123
123


IMO it's no big deal once you are aware of it, and even when you first encounter it, it's fairly easy to intuit what's happening. But still, if Microsoft went to the trouble to warn about EAX being overwritten when it's used to pass the address of a stack variable, they should have warned about this problem as well.
eschew obfuscation


ecube

MichaelW so you're saying the bug is caused if you try and use al as a byte param since eax is used as a scratch register? nothing else is a issue?

MichaelW

I'm simply saying that AL will be unexpectedly changed when it is not apparently involved in the call. I first noticed this in 16-bit code for a byte to decimal conversion macro that was supposed to preserve all registers, but which corrupted AX. If you pass AL, invoke does a PUSH EAX so there is no problem. If you pass some other byte register or an 8-bit memory operand invoke moves it into AL and then does a PUSH EAX. I was wrong about invoke using EAX as a scratch register.

Testing just now, for this procedure and call:

test3 proc arg1:DWORD, arg2:BYTE
  print ustr$(arg1),13,10
  ret 
test3 endp
...
invoke test3, eax, bl


MASM will return "register value overwritten by INVOKE", but if you reverse the order of the parameters it assembles silently.

eschew obfuscation

ToutEnMasm

explain is here

Quote

test1 PROTO :BYTE
   mov al, 255
   mov bl, 123
   invoke test1, bl
   movzx eax, al

;------------------------ listing ---------------------------

               mov bl, 123
            .LISTALL   
00000041  A0 00000000 R   *       mov    al, b
00000046  50         *       push   eax
00000047  E8 0000003C      *       call   test1
0000004C  0F B6 C0         invoke test1, b
               movzx eax, al
;--------------------------------------------------------------

This appear with the translate of byte to dword.Masm don't push byte or word in stack
correction:

test1 PROTO :DWORD and no more problem

ecube

can't believe this bug has gone through so many masm verisons unrectified.

askm

Hello bug world !

I have tested in my layman manner this so called bug.

It is not a bug. I would call it 'larvae'.

I see it as .LISTALL listlessness and by design could it be ?

I did not a .LISTALL but ran it through OLLYDBG

and it shows, after the call

push ebp
mov ebp, esp
leave
retn 4


drizz

actually ToutEnMasm's example is ok :), redefine test1 to "proto :dword" to experience the bug.

test1 proc aa:dword
   ret
test1 endp

it will also happen if you use vararg

myprintf proc c fmt:dword, args:vararg
ret
myprintf endp


LOCAL ab:word
int 3
  invoke myprintf,edi,bl,ab,123


size override prefix not added by ml
004012A1        6A 7B           push 7B
004012A3        6A 00           push 0
004012A5        66:FF75 F2      push word ptr [ebp-E]
004012A9        6A 00           push 0
004012AB        8AC3            mov al, bl
004012AD        66:0FB6C0       movzx ax, al
004012B1        66:50           push ax
004012B3        57              push edi
004012B4        E8 D2FFFFFF     call 0040128B
004012B9        83C4 10         add esp, 10

also look how zero extension is silly

this bug is fixed in ml v9.00.30729.01

and the code produced by it:
0040138C        6A 7B           push 7B
0040138E        66:6A 00        push 0
00401391        66:FF75 FE      push word ptr [ebp-2]
00401395        66:6A 00        push 0
00401398        8AC3            mov al, bl
0040139A        66:0FB6C0       movzx ax, al
0040139E        66:50           push ax
004013A0        57              push edi
004013A1        E8 D7FFFFFF     call 0040137D
004013A6        83C4 10         add esp, 10
The truth cannot be learned ... it can only be recognized.

ecube

can you upload ML 9 somewhere please drizz

drizz

you can find it in VS2008 Express With SP1, if you don't want to install it ml.exe is in "Ixpvc.exe/vs_setup.cab" SFX (unpackable by 7zip)
The truth cannot be learned ... it can only be recognized.

ecube

ugh I got customers whos I need to contact to get this fixed, im just gonna install this annoying gig sdk in vmware, take out the new ml.exe etc files thats needed and zip up somewhere with download link to the Visual C++ 2008 Redistributable Package. others shouldn't have to go through all this non-sense too just for the new masm.


ecube

Yeah I just saw that guide Vortex, seems to be a lot simpler just to install the package since its tiny.

ecube

I replaced the ml and link with the new verisons is compiling ok except when I try

/SECTION:.text,RWX

says invalid argument anyone know how to get it to work?

*update doesn't appear to allow a /section anymore? I replaced new link with the old and it seems to compile fine with the new ml and old link, is there any risk in this?