Hey There...
I am posting to report a bug in the latest version of the MASM32 compiler, which I discovered earlier today (8/1/2005).
I discovered the bug by chance when testing out the CALL instruction. Instead of using the standard form CALL <offset>, I was using the longer form CALL <segment>:<offset>. This is where the bug lies.
My code performed a segment:offset CALL from the starting point to it's "main" function, and from there another segment:offset CALL to get to a seperate function called "funct1". When compiling this code, I encountered a run-time error.
I decided to add some MessageBox error-checking to see what was going on. The results I got were
>> funct1 about to return
>> main about to return
>> ****PROGRAM CRASH****
The error message showed the following information
offset - ffff001b
eip - ffffffffffff0
After opening the EXE in a debugger I discovered the problem.
It turns out that the code
call cs:main
is compiled to
push cs
call main
Now I knew that the program was crashing very near the point of the RET instruction in "main". My guess was that CS had been PUSH'ed on to the stack too many times, not having been POP'ed off. This would corrupt the stack making RET instruction in "main" fail.
I was able to prove that I had guessed correctly by inserting:
pop eax
before the RET instruction in "main". With this modification the program worked fine.
This is a serious flaw in the compiler, and should deffinately be corrected in the next version of MASM. I have included the code I used below, for anyone who wants proof that the bug exists.
For any questions or comments I can be contacted at
suma_ds@hotmail.com
Regards,
Suma
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
.data
msg3 byte "funct1 is about to return", 0
msg2 byte "main is about to return", 0
msg1 byte "start is about to end", 0
.code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
call cs:main
push 0
push offset msg1
push offset msg1
push 0
call MessageBox
push 0
call ExitProcess
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
main proc
call cs:funct1
push 0
push offset msg2
push offset msg2
push 0
call MessageBox
pop eax ; IF THIS IS REMOVED, THE PROGRAM WILL CRASH
ret
main endp
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
funct1 proc
push 0
push offset msg3
push offset msg3
push 0
call MessageBox
ret
funct1 endp
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start
Using segments is a mistake in win32 as they are all set to the same start address. Remove ALL reference to CS and most of your problems will go away.
suma,
MASM is encoding what is effectively a far call (actually a PUSH CS followed by a CALL rel32), so you can correct the problem by using a far return in the called procedure. In my quick search I couldn't find any Microsoft documentation that listed that form of the call instruction. I think, properly speaking, a "bug" is a deviation from documented behavior. If in fact that form of the call instruction is not documented, it's not a bug -- it's just a deviation from the behavior you expected. Personally, I would have expected MASM to encode a far call, and I would have expected it to not work in a Win32 program.
If you declare the function with a far prototype, MASM will use the right call/ret instruction.
main proto far
call main
main proc far
ret
main endp
There is no point in using a far call as flat memory model code is all NEAR addressing.
Ok my bad... It's not a bug. I will try to rename this thread\topic. I dont know if that's even possible...
What i do not get is this whole flat memory model thing.
If all segments are at the same start address then the segments essentially don't exist. If this is the case, then how is the code segment kept seperate from the data or stack segments?
Is it even possible to write self-modifying code without referencing the code segment? I guess in theory it would be, but it would be pretty hard to calculate where everything is in memory. Is this how it has to be done?
So far i am under the impression that flat memory model is one huge segment, and every address in the entire system is an offset of that segment. Is this accurate?
If anybody knows of a paper which explains this stuff in detail i think it might help bring me up to speed and answer some of those questions above. Any help would be appreciated!
Cheers,
Suma
suma,
Download MASM32 at www.masm32.com . It has a mountain of stuff that will get you up to pace.