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
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.
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