Hi,

the following small prog compiles and linkes without errors:




.386
.Model flat,stdcall
option casemap:none

.nolist
.nocref
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
.list
.cref

CStr macro y:req
local sym
CONST segment dword public 'DATA'
ifidni <y>,<"">
sym db 0
else
sym db y,0
endif
CONST ends
exitm <offset sym>
endm

.data

szDef db "default",0

.code

DisplayLine proto :ptr byte

WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,lpszCmdLine:ptr byte,iCmdShow:sdword

local var1:dword

; nop ; program executes ok if activated
mov eax,CStr("Hello")
invoke DisplayLine,eax
xor eax,eax
ret

WinMain endp

DisplayLine PROC pString:ptr byte

local var1:dword

mov eax,pString
.IF (eax == 0)
mov eax,offset szDef
.ENDIF
invoke MessageBox,0,eax,0,MB_OK
ret
DisplayLine ENDP

WinMainCRTStartup proc

invoke GetModuleHandle,0
invoke WinMain,eax,0,0,0
invoke ExitProcess,eax
ret

WinMainCRTStartup endp

end


but the generated code crashes. If the "nop" line in proc WinMain is activated, the prog runs ok.


the generated listing file is very interesting. Heres an excerpt:



00000000 WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,lpszCmdLine:ptr byte,iCmdShow:sdword

local var1:dword

; nop ; program executes ok if activated
00000000 55 * push ebp
00000001 8B EC * mov ebp, esp
00000003 83 C4 FC * add esp, 0FFFFFFFCh
00000000 1 CONST segment dword public 'DATA'
00000000 48 65 6C 6C 6F 1 ??0019 db "Hello",0
00
00000006 1 CONST ends
00000006 B8 00000000 R mov eax,CStr("Hello")
invoke DisplayLine,eax
0000000B 50 * push eax
0000000C E8 00000000 * call DisplayLine
00000011 33 C0 xor eax,eax
ret
00000013 C9 * leave
00000014 C2 0010 * ret 00010h

00000017 WinMain endp

00000017 DisplayLine PROC pString:ptr byte

local var1:dword

00000017 55 * push ebp
00000018 8B EC * mov ebp, esp
0000001A 83 C4 FC * add esp, 0FFFFFFFCh
0000001D 8B 45 08 mov eax,pString
.IF (eax == 0)
00000020 0B C0 * or eax, eax
00000022 75 FF * jne @C0001
00000024 B8 00000000 R mov eax,offset szDef
.ENDIF
00000023 *@C0001:
invoke MessageBox,0,eax,0,MB_OK
00000023 6A 00 * push +000000000h
00000025 6A 00 * push +000000000h
00000027 50 * push eax
00000028 6A 00 * push +000000000h
0000002A FF 15 00000000 E * call _imp__MessageBoxA@16
ret


Have a look at eip 00000024. Here masm calculates wrong as eip of next line is 00000023.

Problem seems to be the use of macro CStr, but only if it is used in the first line of a proc (and the error becomes visible only in the next proc?!?)

Has anyone had a similar problem? Or could anyone explain what is wrong?

japheth
Posted on 2001-12-09 09:24:03 by japheth
If you put a label instead of nop it also works OK. :confused:
Posted on 2001-12-09 09:45:03 by CodeLover
Correct me if I am wrong but there is no indicator to the assembler where the program starts and stops.

Would it work if you used "Start:" and "End Start" ?

Regards,

hutch@movsd.com
Posted on 2001-12-09 16:06:13 by hutch--
Hutch, if /ENTRY is not specified and you don't give a start address
to END, the linker looks for a few predefined symbols, like
WinMainCRTStartup .
Posted on 2001-12-09 16:30:56 by f0dder
This sounds like a MASM bug. Any instruction that you put after "local var1:DWORD" makes the program works perfectly. Replace nop with anything you want and it will work
Posted on 2001-12-09 16:51:15 by CodeLover
Yup, it sure looks like a MASM bug to me. I just tried assembling it with 6.15 and got the same result.

I think it may have something to do with the CONST section in the macro coming right afrer a LOCAL, but the gererated code does look OK there.

The address of @C0001 should be 000029, 6 bytes more than it is, which also happens to be the size of the CONST section. So it sounds like the "internal pointer" in MASM got screwed up some how. Congratulations! :grin:

I guess the good news is that you know how to fix it. :)
Posted on 2001-12-09 17:22:47 by S/390
Naaaa...

Its just his funny code. :)


I comment out and replaced these two lines and all works well...


;CONST segment dword public 'DATA'
.data

...

;CONST ends
.code


I cant say i know where one learns that form (seen others use simular stuff), but .data and .code always worked for me... and seems to be winning the race at this point :)

Hope this helps..
:alright:
NaN
Posted on 2001-12-10 01:57:36 by NaN
NaN,

you are right, it works when using the predefined segment directives. But it still is a bug. BTW, I have deliberately used the old style directive so the macro can also be used to define string pointers in the .data section.

japheth
Posted on 2001-12-10 02:57:58 by japheth
to define string pointers in the any section you can use this macro.



$TO MACRO sText
; $TO defines text both in .data or .code sections and returns its offset
local szText, SegName
SegName TEXTEQU @CurSeg
.data
IF @SizeStr(<sText>) NE 0
szText db sText, 0
ELSE
szText db 0
ENDIF
@CurSeg ENDS
SegName SEGMENT
EXITM <offset szText>
ENDM



Works fine in your code.
Posted on 2001-12-10 10:20:53 by Four-F
Four-F, great :) . Didnt know that predefined @CurSeg "macro".
Posted on 2001-12-10 11:21:07 by japheth