I am programming a WinApi in assembly language in which the program reacts to keypress, problem is, if the routine is not completed and the key is pressed in meantime again, it starts accumulate, which means once the routine gets finished, it goes again and again given the times user pressed the key while the routine was in progress.
Classic message loop:
.MessageLoop:
invoke PeekMessage,Message,NULL,0,0,PM_REMOVE
test eax,eax
jz near .NoMess
cmp dword [Message + MSG.message],WM_QUIT
jz near .Finish
invoke TranslateMessage,Message
invoke DispatchMessage,Message
.NoMess:
; some code
jmp .MessageLoop
And handle for messages:
function WndProc,hWnd,wMsg,wParam,lParam
begin
mov eax,dword [wMsg]
cmp eax,WM_DESTROY
je near .Destroy
cmp eax,WM_CLOSE
je near .Destroy
cmp eax, WM_KEYDOWN
je near .keyDown ; when key is pressed, then it is checked what key it is, meanwhile I need program to ignore all keypressed
cmp eax, WM_PAINT
je near .Paint
invoke DefWindowProc,[hWnd],[wMsg],[wParam],[lParam]
return eax
Let's say I have routine to handle W button, in proccess of the routine I want all other W keys to be ignored.
Related
I am trying to set a breakpoint to with 'gdb'.
From here I understood how to break specific line of function.
But I want to break specific offset of function.
0xb7eecfa8 <error+184> mov eax, dword ptr [ebx - 0x40]
0xb7eecfae <error+190> sub esp, 4
0xb7eecfb1 <error+193> push dword ptr [eax]
gdb> break error+184
Function "error+184" not defined.
Is there any command to break on 0xb7eecfa8 <error+184>?
(except for just typing b *0xb7eecfa8)
Is there any command to break on <error+184>
Both of these appear to do what you want:
b *(&error+184)
b *(error+184)
I have too much time on my hands and decided to write a simple program in MASM32 for no good reason. However, I can't get my SetWindowPos call to the WinApi to work. Here's the relevant code bit:
invoke GetForegroundWindow
mov ecx,eax
invoke GetWindowLong, ecx, GWL_EXSTYLE
AND eax,WS_EX_TOPMOST ; check if window-
.if eax==0 ; is already on top
mov edx,HWND_TOPMOST; nope, make it on top
.else
mov edx,HWND_NOTOPMOST; yes, make it not on top
.endif
push ecx ; window handle
push edx ; placement handle
push edi ; edi=0, someone told me this is faster
push edi
push edi
push edi
push 0043h ; SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE
call SetWindowPos
cmp eax,0
jne mLoop1 ; jump to message loop
invoke HandleError, addr appname ; make message box with error message
; ^^^^^^^^ this shows "Invalid Window Handle"
jmp mLoop1 ; jump to message loop
I'm sure I'm missing somehting very obvious, but with my limited knowledge of assembly I have no idea what.
I am trying to move stuff from a register to a variable in .CODE, but trying to do so makes my program start over in an infinite loop (no crash and no error message, but obviously broken). I don't understand what I'm doing wrong. Here is the beginning of my code where I am trying to move data; the program never even gets past this part when I include it:
.CODE
screenX DWORD 0
screenY DWORD 0
...
ProcName PROC
mov ebx, edx ;; Copy srcBitmap into ebx
mov eax, edi ;; Take given y-location (edi)
mov edx, (EECS205BITMAP PTR [ebx]).dwHeight
shr edx, 1 ;; Subtract dwHeight/2 to center
sub eax, edx
mov screenY, eax ;; Program jumps back to beginning with no error message
Seems like I'm missing something obvious, anyone have a clue?
Your application's code segment (which is actually it's .text section under Windows) isn't writable. If you want to modify these variables you need to put them in the data segment.
in assembly, i am trying to do a animation. In the below code, move_object animates an object, while move_arrow animates another object. however, the problem is both uses the same timer function ( which i actually didn't understand how works, I just copied it from a source.) both runs finely in norma case. but what i want to do is that the object will keep animating from the start but the arrow will wait for user to press a specific key. when user presses that key, then the arrow will start. but whenever i call the interrupt function for keyboard press (MOV AH,0 INT 16H) the program gets halted there and waits for the user to press a key. but i want to have the previous to object to still move in that time. but no matter however i write the code it seems like the code gets halted in that line and no other lines get executed. below is the fragment of my code.
; dont know how it works , just know that it works as a timer :D
TIMER_TICK PROC
PUSH DS ; SAVE DS
PUSH AX
MOV AX,SEG TIMER_FLAG ; GET SEGMENT OF FLAG
MOV DS,AX ; PUT IN DS
MOV TIMER_FLAG,1 ; SET FLAG
; RESTORE REGISTER
POP AX
POP DS
IRET ; IT IS DIFFERENT FROM "RET". IF WE USE "IRET" THEN
; IF WILL REMAIN 1 WHICH MEANS IT CAN BE INTERRUPT AGAIN
TIMER_TICK ENDP
;; other codes
;WAIT FOR TIMER TICK BEFORE MOVING THE OBJECT
TT:
CMP TIMER_FLAG,1 ; TIMER TICKED?
JNE TT ; NO , KEEP TESTING
MOV TIMER_FLAG,0 ; YES, CLEAR FLAG
CMP LAP,1 ; CHECKS IF ARROW HAVE FINISHED CROSSING
JE GAME
CALL MOVE_OBJECT ;animates the object to a new position
CMP KEY,0
JNE CONT
MOV AH,0
INT 16H ;**whole program gets halted here untill user presses a key**
OR AL,AL
JNE EXIT
CMP AH,3BH
JNE GAME
MOV KEY,1
CONT:
; CHECK FOR KEYBOARD
CALL MOVE_ARROW ;animates the object in a new position
; DELAY 1 TIMER CLICK
TT2:
CMP TIMER_FLAG,1 ; TIMER TICKED?
JNE TT2 ; NO , KEEP TESTING
MOV TIMER_FLAG,0 ; YES , CLEAR FLAG
JMP TT ; GO GET NEXT OBJECT POSITION
;; other codes
The BIOS function you're using does indeed halt until a key is available from the keyboard. It's meant to work like that.
Consider using function 1 instead. That one will return immediately and report through the zero flag ZF if a key is waiting. So if ZF=1 you would probably jump back to TT.
mov ah,1
int 16h
jz TT
mov ah,0
int 16h
Use the function ah=1 in int 16h. If a key was pressed until the moment, when the function ah=1 was called, the ZF is set and AX contains the values that would be set, if you had used ah=0. Otherwise, if no key had been pressed, the ZF is not set and AX won't contain a useful value. Notice: If you use the function ah=1, you have to use function ah=0 if a key had been pressed, cause the keybuffer wouldn't be changed otherwise.
I really do not understand why this simple code works fine in the first attempt but when
putting it in a procedure an error shows:
NTVDM CPU has encountered an illegal instruction
CS:db22 IP:4de4 OP:f0 ff ff ff ff
The first code segment works just fine:
.model small
.stack 100h
.code
start:
mov ax,#data
mov ds,ax
mov es,ax
MOV AH,02H ;sets cursor up
MOV BH,00H
MOV DH,02
MOV DL,00
INT 10H
EXIT:
MOV AH,4CH
INT 21H
END
However This generates an error:
.model small
.stack 100h
.code
start:
mov ax,#data
mov ds,ax
mov es,ax
call set_cursor
PROC set_cursor near
MOV AH,02H ;sets cursor up
MOV BH,00H
MOV DH,02
MOV DL,00
INT 10H
RET
set_cursor ENDP
EXIT:
MOV AH,4CH
INT 21H
END
Note: Nothing is wrong with windows config. I have tried many sample codes that work fine
Thanks
You left out a JMP:
call set_cursor
jmp EXIT ; <== you forgot this part
PROC set_cursor near
What's happening is that after call set_cursor, you're then falling through to the proc and and executing it again, then when you hit the ret it pops the stack and you jump to, well, who knows?
Edit: As someone else pointed out, you're better off putting your PROC after your main code ends, instead of sticking it in the middle and jumping around it. But you've probably figured that out already :)
You should move the code of the procedure after the part where you exit the program (or follow egrunin's advice).
The reason for your segfault is that the code in the procedure is executed again after you first call it. During the second execution the code crashes on RET because there is no valid return address on the stack.