I'm debugging the following code
MOV dword ptr[ebp - 24H], eax // value in eax is 0xd0005500
CMP dword ptr[ebp - 24H], 0
JE blahhhh
Now it always takes the jump but because the CMP instruction sets the zero flag. However I thought that CMP simply subtracted the source from the dest - so how does (0 - 0xd0005500 == 0)?
Do I have the cmp instruction wrong? Is it producing a negative value which is being clamped to zero?
Thanks for any help,
Mac.
Substitute this and see if it works.
test eax, eax
jz label
While its hardly good code you are debugging,your results don't make sense. JE is neither signed OR unsigned so it should branch id EQUAL.
Quote from: hutch-- on June 02, 2008, 08:01:57 AM
Substitute this and see if it works.
test eax, eax
jz label
While its hardly good code you are debugging,your results don't make sense. JE is neither signed OR unsigned so it should branch id EQUAL.
Thanks for the response Hutch, it doesn't make sense to me either. I can't change the code since it's not mine, it's part of the Microsoft Direct Draw WinCE 6.0 implementation. I pass an address back to it (value in EAX) and then it returns a failure back to the API. When I debugged it to try and work out why, this looked like the offending code. The best I can tell it's doing NULL check on the memory address but the check is always failing.
I tried changing the value in eax to 0 and it *still* took the jump - really confused now. It doesn't seem matter what I pass to the CMP instruction it always sets the zero flag.
Mac.
Trying to emulate the code, but no success either...
include \masm32\include\masm32rt.inc
.code
;read-only data before start
AppName db "Test app:", 0
start:
invoke MessageBox, 0, chr$("Int 3?"), addr AppName, MB_YESNO
.if eax==IDYES
int 3
.endif
call TestWin
invoke ExitProcess, 0
TestWin proc
LOCAL a,b,c1,d,e,f,g,h,i,j
mov i, 0d0005500h
cmp [i], 0
je IsEqual
invoke MessageBox, 0, chr$("not equal"), addr AppName, MB_OK
ret
IsEqual:
invoke MessageBox, 0, chr$("is equal"), addr AppName, MB_OK
ret
TestWin endp
Thanks for looking at this.
My only thought now is that the debugger is not giving me a true representation of what is happening. Perhaps there's some out of order instruction execution going on and by the time I've edited the values the expression has already been evaluated. It seems unlikely but I can't think of anything else.
Regards,
Mac.
Mac,
Just dead list it (decompile the code) and see if its the same as you were getting in the debugger.
Hi Hutch,
when I said instruction reordering I meant by the CPU not the compiler. If that's the case then there's little I can do about it - apart from trying to edit the register value even earlier (ie. before the CMP instruction enters the pipeline).
I seriously doubt this is what's happening, just can't think of any other explanation at the moment.
Mac.
Mac,
Instruction reordering occurs in the pipeline stage, they come out the back end and are retired in the correct order so you don't have to worry about that aspect of instruction scheduling. Without this garrantee of instruction ordering code would not run so you have nothing to worry about here.
the couple of instructions you posted test eax to see if its zero, its a poor technique which is probably either poor compiler optimisation or perhaps the use of a LOCAL in the compiler where it did not need to be done.
It may be the case that you have not recognised the correct piece of code, its easy enough to do in messy looking compiler code.
Below Olly V2 listing, behaving as expected. You are absolutely sure that eax is non-zero in that moment?
CPU Disasm
0040101C ³? B8 005500D0 mov eax, D0005500
00401021 ³? 8945 DC mov dword ptr [ebp-24], eax
00401024 ³? 837D DC 00 cmp dword ptr [ebp-24], 0
00401028 ³. 74 15 je short wrong_JE.0040103F ; ÚExitCode = 4198463.
0040102A À. 6A 00 push 0 ; ÀKERNEL32.ExitProcess
0040102C ? 68 00104000 push wrong_JE.00401000 ; ASCII "Test app:"
00401031 ³? 68 1E304000 push offset wrong_JE.004030 ; ASCII "not equal"
00401036 ³? 6A 00 push 0
00401038 ³? E8 17000000 call <jmp.&user32.MessageBo ; Jump to user32.MessageBoxA
0040103D ³? C9 leave
0040103E ³? C3 retn
0040103F ³? 6A 00 push 0
00401041 ³? 68 00104000 push wrong_JE.00401000 ; ASCII "Test app:"
00401046 ³? 68 28304000 push offset wrong_JE.004030 ; ³ASCII "is equal"
0040104B ³? 6A 00 push 0 ; ³
0040104D ³? E8 02000000 call <jmp.&user32.MessageBo ; ³Jump to user32.MessageBoxA
Quote from: jj2007 on June 02, 2008, 12:25:37 PM
Below Olly V2 listing, behaving as expected. You are absolutely sure that eax is non-zero in that moment?
Yep definitely, eax and the memory location [ebp - 24h] both show the same non-zero value. Then again I am assuming that the debugger is telling me the truth about the register and memory contents. I just tried a complete OS recompile to make sure the symbols were matching and got the same result - thanks for looking into it though.
I should probably point out that I'm remote debugging this, I guess it could be something to do with the WinCE platform builder not showing me the correct information - some latency caused by the remote link perhaps?
I'm pretty sure it's not the code now but some WinCE/Platform-Builder artifact, I've posted a question on one of the WinCE forums so I'll see where that gets me.
Hatch - thanks for the info about the CPU pipeline. My knowledge of CPU architecture isn't exactly comprehensive.
Thanks again,
Mac.
Quote from: bigmacx on June 02, 2008, 12:36:40 PM
I should probably point out that I'm remote debugging this, I guess it could be something to do with the WinCE platform builder not showing me the correct information
That is one track to keep an eye on. Sometimes (often?) MS uses the same old source code for different platform-specific API's. Can you test your code on XP instead of CE, and debug it directly?