Assembly 8086 listening keyboard interrupt

邮差的信 提交于 2019-12-11 04:36:09

问题


I have exactly the same question as this: Listen to keyboard while drawing

But the first answer (accepted one) listens keyboard for exactly once. So how can I modify my code so that I can listen keyboard interrupt for more then once.

This is my code:

.model small
draw_row Macro x
    Local l1
; draws a line in row x from col 10 to col 300
    MOV AH, 0CH
    MOV AL, 4
    MOV CX, 0
    MOV DX, x
L1: INT 10h
    INC CX
    CMP CX, 320
    JL L1
    EndM
.stack 100h
.data
height1 dw 51 
width1 dw 65
 v1 dw ?
 v2 dw ?
CUR_POSX_USER  DW 61
CUR_POSY_USER  DW 75
VAR DB ?
POSX DW 100
POSY DW 141


CAR_X DW  '0','0','0','0','0','0'
CAR_Y DW   '0','0','0','0','0','0'
CAR_TIMEM DW   '0','0','0','0','0','0'
CAR_TIMES DW   '0','0','0','0','0','0' 
RANDOM DW 257
TDELAY DW ?

.code

drawcar proc

    PUSH AX
    MOV V1, CX
    MOV AX,WIDTH1
    ADD V1,AX
    MOV V2, DX
    MOV AX,HEIGHT1
    ADD V2,AX
    POP AX
    MOV AH, 0CH

    MOV BX,V1
L1: 
    INC CX

    PUSH DX 
       l2:INT 10H
          INC DX
          CMP DX,V2
          JL L2
    POP DX
    CMP CX, V1        
    JL L1
    ;MOV AH,0
    ;int 16H

    ret



    RET 
drawcar endp
main proc
MOV AX,@DATA
MOV DS,AX
call drawscreen

INFINITE:

         MOV AL,1
         MOV CX,CUR_POSX_USER
         MOV DX,CUR_POSY_USER
         CALL DRAWCAR 
         CALL DRAW1
         CALL LISTEN_KEYBOARD



         JMP INFINITE
main endp

DELAY PROC
PUSH AX
PUSH CX
PUSH DX
PUSH BX
PUSH DI


  MOV DI, TDELAY
  MOV AH, 0
  INT 1Ah
  MOV BX, DX
  GO1:
  MOV AH, 0
  INT 1Ah
  SUB DX, BX
  CMP DI, DX
  JA GO1
       POP DI
       POP BX
       POP DX
       POP CX
       POP AX 


     RET  



DELAY ENDP


LISTEN_KEYBOARD PROC

   PUSH AX
   MOV AH,1
   INT 16H
   CMP AH,48H
   JE UP
   CMP AH,50H
   JE DOWN
   JMP GO
   UP:
      CMP CUR_POSY_USER,66
      JL GO
      CALL REMOVECAR
      SUB CUR_POSY_USER,66
      PUSH CX
      PUSH DX
      MOV CX,CUR_POSX_USER
      MOV DX,CUR_POSY_USER
      MOV AL,1
      CALL DRAWCAR
      POP DX
      POP CX
      JMP GO
   DOWN:
       CMP CUR_POSY_USER,133
       JG GO
       CALL REMOVECAR
       ADD CUR_POSY_USER,66
       PUSH CX
       PUSH DX
       MOV CX,CUR_POSX_USER
       MOV DX,CUR_POSY_USER
       MOV AL,1
       CALL DRAWCAR
       POP DX
       POP CX
       JMP GO 
    GO:
      MOV ZF,1
      POP AX
      RET   



LISTEN_KEYBOARD ENDP
REMOVECAR PROC
PUSH CX
PUSH DX

MOV AH,0CH
MOV DX,CUR_POSY_USER
MOV CX,CUR_POSX_USER
CALL DRAWCAR

POP DX
POP CX
RET




REMOVECAR ENDP


drawscreen proc
mov al,13H
mov ah,0h
int 10h
mov ax,10
draw_row 66
draw_row 133

ret
drawscreen endp

DRAW1 PROC


MOV CX,POSX
MOV DX,POSY
MOV AL,0
CALL DRAWCAR         

SUB POSX,5
MOV CX,POSX
MOV DX,POSY 
MOV AL,15
CALL DRAWCAR
MOV TDELAY,5
CALL DELAY


RET    
DRAW1 ENDP

end main

回答1:


In your LISTEN_KEYBOARD procedure you check the keyboard but you fail to interpret the ZeroFlag before comparing the scancode in the AH register. If the ZF is set then there is nothing of any importance in the AH register!

PUSH AX
MOV AH,1
INT 16H
jz GO               Add this line.
CMP AH,48H
JE UP
CMP AH,50H
JE DOWN
JMP GO

Below the label GO you've written MOV ZF,1. I don't see any variable ZF in your program. If you want to set the ZF then use mov ah,40h sahf.

Finally to solve the issue of listening to the keyboard more than once you need to actually remove the key that you've just used.

PUSH AX
MOV AH,1
INT 16H
jz GO
mov ah,0            Add these lines.
int 16h             Add these lines.
CMP AH,48H
JE UP
CMP AH,50H
JE DOWN
JMP GO


来源:https://stackoverflow.com/questions/37340604/assembly-8086-listening-keyboard-interrupt

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!