A really simple program but one button works while the exit button doesn't. Why? I tried to logically understand what is going on with the processor and registers, and have modified it repeatedly but still no cigar.
Is it possible it has something to do with the structure of .rc file? I tried to arrange that as well as I could but don't know if that made a large difference. BTW the program works so this is a bug you could say.
(The whole thing isn't important but I'm just playing around with asm and trying to learn it along the way). Thanks.

wmcommand:
xor ebx, ebx
mov eax, dword ptr
cmp eax, BTN_GO
jne @Next
call loop1, hwnd_
xor ebx, ebx;added recently but made no difference
cmp eax, BTN_EXIT
je wmdestroy
RET
@Next:
nop
RET


The first BTN_GO works fine but not the second button(BTN_EXIT). Is the order a problem?Like I should place the instructions for BTN_EXIT first before BTN_GO?
Thanks

PS: I'm not looking for a code(unless I missed something specific) I'm rather looking for the explanation, the logic behind it.
Thanks again.
Posted on 2002-05-30 11:53:29 by BeHereNow
don't compare wParam with your button-ID but the LOWWORD of wParam:

Mov eax, wParam
Cmp ax, BTN_EXIT
Jz ...


///// MSDN /////////////////////////////////////////////////
WM_COMMAND
wNotifyCode = HIWORD(wParam); // notification code
wID = LOWORD(wParam); // item, control, or accelerator identifier
hwndCtl = (HWND) lParam; // handle of control
Posted on 2002-05-30 12:22:49 by Rennsemmel
there's some errors in your code:

line
1 xor ebx, ebx
2 mov eax, dword ptr
3 cmp eax, BTN_GO
4 jne @Next
5 call loop1, hwnd_
6 xor ebx, ebx;added recently but made no difference
7 cmp eax, BTN_EXIT
8 je wmdestroy
9 RET
10 @Next:
11 nop
12 RET

the first point is a Rennemmel said:
you need to either zero the upper 16 bits of "eax" or do the compare on lines 3 and 7 on "ax"

Next on line 4 after the first cmp you are jumping over everything including the "cmp" for BTN_EXIT. you need to place @next between lines 6 and 7

Also If the first cmp is true i.e(ax==BTN_GO) then what you have written will execute lines 5,6,7,9,10,11,12 and if by chance the return value (in eax) from the call on line 5 is equal to BTN_EXIT then your program will exit mysteriously.

You must remember that all Windows functions return their value in eax and so do most other functions which you'll encounter.
Posted on 2002-05-30 12:36:51 by MArtial_Code
Problem solved by altering the order of the buttons and the registers?:

xor ebx, ebx
mov eax, dword ptr ;couldn't change it without affectin bttn_go function??
Cmp ax, BTN_EXIT
Je wmdestroy
cmp ax, BTN_go
jne @Next
call loop1, hwnd_

This worked but so did this:

xor ebx, ebx
mov eax, dword ptr
Cmp eax, BTN_EXIT
Je wmdestroy
cmp eax, BTN_go
jne @Next
call loop1, hwnd_

A couple of questions though to MARTIAL_CODE:

"Also If the first cmp is true i.e(ax==BTN_GO) then what you have written will execute lines 5,6,7,9,10,11,12 and if by chance the return value (in eax) from the call on line 5 is equal to BTN_EXIT then your program will exit mysteriously".


1)Why not line 8 also? because there isn't a jump or a call in between?

7 cmp eax, BTN_EXIT
8 je wmdestroy

2)Also how do you zero the upper 16 bits on eax?

"the first point is a Rennemmel said:
you need to either zero the upper 16 bits of "eax" or do the compare on lines 3 and 7 on "ax""


3)The last question is why in line one am Isetting ebx to zero when I'm dealing with eax?(I didn't write the whole thing, I'm simply modifying it).

1 xor ebx, ebx


Thanks a lot for both your help and explanations?
Posted on 2002-05-30 12:57:41 by BeHereNow
Is that how you reset the high 16 bits of eax or
xor eax, eax?
I think it's the first one because the second one resets all 32 bits. Is that right?

what about?
mov eax, 0
Thanks again.
Posted on 2002-05-30 15:28:57 by BeHereNow
to answer your questions:

Q1) Line 8 will be evaluated but it's unlikely the jump will be
made...

Q2) To clear the upper 16 bits while retaining the lower 16 you need to :

xor eax,0000FFFFh

Q3) I've no idea...Just make sure you save ebx before you alter it
and restore ebx before you leave the callback...

push ebx
do stuff here
pop ebx
Posted on 2002-05-30 16:02:59 by MArtial_Code
um...
xor eax,0FFFFh doesn't clear the top bits. I think you mean and eax,0FFFFh

The xor ebx,ebx looks like it does nothing because you return before you do anything with it. Unless it happens to be used in wmdestroy.

BTW, what's with the nop/ret? Looks like you could get rid of this and just fix up your code to jump to the first return instead of to the nop/ret

Cya

--Chorus
Posted on 2002-05-30 16:09:26 by chorus
Indeed Chorus that's what I meant...
Posted on 2002-05-30 16:13:38 by MArtial_Code
Thought so :)
Just thought I'd make sure...

--Chorus
Posted on 2002-05-30 16:17:01 by chorus
Hi and Thanks for all your help.
I tried to edit my code as per chorus' suggestion, but couldn't take out either xor ebx, ebx
or also : the jne @Next
This crashed my program(not my computer though) and illicited an upset message from windoz. The code as it stands(and actually working):
1)xor ebx, ebx
2)mov eax, dword ptr
3)Cmp eax, BTN_EXIT
4)Je wmdestroy
5)cmp eax, BTN_go
6)jne @Next
7)call loop1, hwnd_
8)RET

@Next:
1)nop
2)RET

My thinking is that : jne @Next
is acting as a pause untill the user places a string in editbox(another place in the program. If I seperate the buttons into 2 different sections, then perhaps I can JNE to the place for button_Exit to check there again, and then return it to button_go section to see if user pressed button. I don't know if I'm correct except to try it. Like

button1:

1)xor ebx, ebx
2)mov eax, dword ptr
3)Cmp eax, BTN_EXIT
4)Je wmdestroy
5)jne button2
6)ret

button2:

1)xor ebx, ebx
2)mov eax, dword ptr
3)cmp eax, BTN_go
4)jne button1
5)call loop1, hwnd_
6)RET
What do you think?

I also think ebx is used in wmdestroy through Dlgprocedure.

What do you think?
Thanks to all again for your help and explanations which are great.
Posted on 2002-05-30 17:48:33 by BeHereNow
Heres what the code you posted is doing...

xor ebx,ebx :this clears ebx i.e ebx==0 (anything xor'd with itself is zero)

mov eax, dword ptr : eax now contains the value held in wParam(ax==the ID of the button/menu)

Cmp eax, BTN_EXIT: Did we press the exit button?

Je wmdestroy: if yes then jump to label wmdestroy(presumably to exit program) if not then proceed to the next line

cmp eax, BTN_go: Did we press the go button?

jne @Next: if no then jump to label @Next, if yes then proceed to the next line

call loop1, hwnd_ : the go button was pressed and we ended up here

ret: return after function call.

line 6 is not acting as a pause, if BTN_go is pressed then the program will do what ever it's supposed to do.

There's no need to separate anything as what your coding is a standand message processing...

I don't know why removing the xor ebx.ebx crashed your program...is the program big? why don't you post it all then we can see what's really happening...
That'll have to wait till tommorrow though...
happy hunting...
Posted on 2002-05-30 18:19:49 by MArtial_Code
Thank you for the detailed explanation.
That was good. I can't upload the code or the program as they might be in violation of the rules of the forum and I don't want to get booted off because I do like this forum's explanations and members. However, here is the part dealing with the buttons(that's the part I coded myself):

wmcommand:

xor ebx, ebx
mov eax, dword ptr
Cmp eax, BTN_EXIT
Je wmdestroy
cmp eax, BTN_GO
jne @Next
call Loop1, hwnd_
RET
@Next:
nop
RET

I don't know if that clarifies it, but after it goes to label "@Next:" it's returned to "call Loop1, hwnd_" is that right? so if I take "jne @Next"
and take Label "@Next along with nop & RET" it shouldn't make a difference right? but it crashes the program, and I don't see any other calls to that @Next label.


(P---- caused an invalid page fault in
module KERNEL32.DLL at 017f:bff7c006.
Registers:
EAX=00540484 CS=017f EIP=bff7c006 EFLGS=00010202
EBX=00000000 SS=0187 ESP=00540000 EBP=00540434
ECX=004020db DS=0187 ESI=00000000 FS=c797
EDX=00000008 ES=0187 EDI=005404b4 GS=0000
Bytes at CS:EIP:
56 89 45 e8 57 8b 75 08 c7 45 f4 00 04 00 00 80
Stack dump:
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 )

So this call is important but why? I don't know. I even tried to place

je Loop1 instead of


cmp eax, BTN_GO
jne @Next <---------je Loop1
call Loop1, hwnd_ <-----took it out
RET
@Next: <-----took it out
nop <------took it out
RET <------took it out

the program assembled(Tasm) fine but when I pressed button go it send a similar message as above but the stack dump had values in them.

My thinking is that this jne @Next is creating a loop between comparing the go button and the @Next call. This can be only true if the ret from the @next call is taking us back to cmp eax, BTN_GO
I don't think that's the case because I think ret will take us back to
call Loop1, hwnd_

I hope you understand this very long message. Thanks again for the help.
BTW now this is all code optimizing, correct or rather asm theory 101 for the absolute beginner(me). :)
Thanks
Posted on 2002-05-30 21:36:00 by BeHereNow
BeHereNow,
the following two lines of blocks of code are equivalent in any universe I know of...



yours:
xor ebx, ebx
mov eax, dword ptr [wparam_]
Cmp eax, BTN_EXIT
Je wmdestroy
cmp eax, BTN_GO
jne @Next
call Loop1, hwnd_
RET
@Next:
nop
RET

modified:
xor ebx, ebx
mov eax, dword ptr [wparam_]
Cmp eax, BTN_EXIT
Je wmdestroy
cmp eax, BTN_go
jne @Next
call loop1, hwnd_
@Next: RET


there's a couple things to note. First of all, nop doesn't do anything. It's an alias for xchg eax,eax which quite plainly does nothing but advance EIP. Because it does nothing you can safely remove it. Then you can move the label @Next and remove the second ret.
Second, that report from windows you posted seems very strange. For instance, the contents as CS:EIP starting with hex 56. Last I checked, that's not an opcode... Also, the stack is filled with zeroes. That's pretty impressive in and of itself.
Third, how is it that you get call loop1, hwnd_ to compile? are you using MASM?? Doesn't compile on my machine..

edit

didn't see you were using TASM. Nevermind that question

edit

Fourth, when you jump to @Next, it doesn't return to call loop1. It returns to the windows message loop (or whereever your windows message handler was called *from*)

The only way I could see this crashing is if there was some hard-coded jump some where. Like a relative short jump that expected a certain number of bytes between the jump and the destination. This would make sense seeing as how it dumps out opcode 56.

One way to test this theory. Take the working code and throw in 3 or 4 nops. Doesn't matter where they go, they don't do anything. If this crashes your program, then likely you have a jmp $+20 or something in your code and you're throwing it off. This wouldn't surprise me, especially if this is something of a ... "rule bending" program

--Chorus
Posted on 2002-05-30 22:09:34 by chorus
Your explanation made a lot of sense so I tried it out.
wmcommand:
xor ebx, ebx
mov eax, dword ptr
Cmp eax, BTN_EXIT
Je wmdestroy
cmp eax, BTN_GO
nop
nop
nop
nop
jne @Next
call Loop1, hwnd_
RET
@Next:
nop
nop
nop
nop
nop
RET


Program worked fine with no crashes. BTW, I'm just disecting the small program because it's very easy to do and because it has a function I can see the effects.(In other words I'm not using it for any bending of rules). :)
Should have I placed more nops between the buttons perhaps?
edit: I just did that and again it ran fine.
Posted on 2002-05-30 22:24:20 by BeHereNow
I took out the nop after @next:
and it works fine.
I don't know why a call that doesn't do anything is that important unless I placed the nops wrong.(I don't see any hardcoded jumps based on values but maybe I didn't look long enough.
anyway your equivalent code is working fine.
Posted on 2002-05-30 22:30:05 by BeHereNow
If one nop didn't do it, then I don't think it'll matter how many you put in. Quite frankly, without any more code around it we're shooting in the dark. Love to help you more, but I really have nothing else to say. Maybe someone else has an idea??

--Chorus

PS. the xor ebx,ebx is probably used in loop1. If I'm correct, that'd be a loop :grin: and if it uses ebx as an index pointer or something it'd have to be initialized outside the loop.
You can't post loop1 can you? That's probably where the crash is happening (which would only happen if you hit the OK button btw). If it's happening before you press any buttons then it must be something else
Posted on 2002-05-30 22:33:09 by chorus
The call isn't to the nop/ret. It's somewhere else in your code under the label loop1. The nop/ret is executed from the jmp @Next instruction.
Posted on 2002-05-30 22:35:04 by chorus
I can't really post loop 1 but here is a part of the code that I think you were talking about earlier(hard coded):
mov eax, offset Whatever1
push esi
mov esi, 00DB95DB95h <---a value perhaps in memory?

push eax
or esi, 00000378h<---same thing
call Sub1
mov ecx, offset whatever2
add esi, eax
push ecx
call Sub1
add esp, 00000008<---a value
add eax, esi
pop esi

Anyway I hve to look at it in detail tomorrow. I'm brain dead at the moment but thanks for your posts.
Posted on 2002-05-30 23:03:55 by BeHereNow
I got it finally(I was on the wrong track) thanks chorus and martial_code for the help.
Now I understood your message chorus:
the ret from @next isn't returning us to the routine checking the
cmp BTN_GO
it's actually taking us back to the routine that called "wmcommand:" which had the cmp BTN_GO instruction.
so it is doing something that "RET" it's taking us out of "wmcommand:" completely.
Thanks for your incredible patience(it only took me 2 days to get this, lol)(talk about having tunnel vision).
Thanks again for your help.
Posted on 2002-05-31 12:36:53 by BeHereNow