Hello

this day I stumbled upon the following MASM "feature":


        .386
        .MODEL FLAT, stdcall
        option casemap:none
        option proc:private

        .CODE

GetHWnd proc pThis:dword, phwnd:ptr HWND

mov ecx, pThis
        mov edx, phwnd
        ret

GetHWnd endp

SetHWnd proc pThis:dword, hwnd:HWND

mov ecx, pThis
        mov edx, hwnd
        ret

SetHWnd endp

        END



You might think it doesn't assemble because type HWND is undeclared, but it assembles fine with MASM 6.15.

The problem, however, shows in the listing file only:


00000000     .CODE

00000000 GetHWnd proc pThis:dword, phwnd:ptr HWND

00000000  55   *   push  ebp
00000001  8B EC   * mov    ebp, esp
00000003  8B 4D 08 mov ecx, pThis
00000006  8B 55 0C mov edx, phwnd
        ret
00000009  C9   *     leave 
0000000A  C2 0008 *   ret    00008h

0000000D GetHWnd endp

0000000D SetHWnd proc pThis:dword, hwnd:HWND

0000000D  55   *   push  ebp
0000000E  8B EC   * mov    ebp, esp
00000010  8B 4D 08 mov ecx, pThis
00000013  8B 55 0C mov edx, hwnd
        ret
00000016  C9   *   leave 
00000017  C2 0004 *    ret    00004h

0000001A SetHWnd endp


As one can see, SetHWnd is generated with a RET 0004, although it is called with 2 DWORD parameters.

Pretty annoying!

Japheth

Posted on 2005-10-22 13:45:20 by japheth
japheth, ive checked it and its present in all versions :(

here are some more to be aware of (1 & 2 also in all versions)

1. goes berserker with initialized structs that need to be aligned
2. cant push correctly unsigned byte and word variables to cdecl vararg proc
  (but it can signed variables ( sbyte sword ) - funny)
3. pushw without prefix for registers - fixed in >= 8.0

this are, that i know of, afect code generation.


.686
.model flat,stdcall
option casemap:none
includelib kernel32.lib
extern stdcall ExitProcess:proto stdcall :dword

; BUG1 {
.data
bug1_s1 struct 4
a1 dd ?
b1 db ?
bug1_s1 ends

.data
bug1_m1 bug1_s1 2 dup (<0ffffffffh,0ffh>)
; }

; BUG2 {
.data
bug2_b db 1
; }

.code

; BUG2 {
bug2_p0 proto c :vararg
; }

start:
int 3
; BUG1 {
mov eax,bug1_m1[0*(sizeof bug1_s1)].a1
movsx edx,bug1_m1[1*(sizeof bug1_s1)].b1
sub eax,edx
jnz buggy
; }
; BUG2 {
mov edi,esp
invoke bug2_p0,bug2_b
sub edi,esp
jnz buggy
; }

IF @Version LE 710
; BUG3 {
mov edi,esp
pushw ax
pop ax
sub edi,esp
jnz buggy
; }
ENDIF

notbuggy:
invoke ExitProcess,0
ret

buggy:
invoke ExitProcess,1
ret

; BUG2 {
bug2_p0 proc c args:vararg
ret
bug2_p0 endp
; }

end start
Posted on 2005-10-22 16:35:00 by drizz