会检查是否按下了某个键并读取是哪个键的

时间:2019-05-18 15:13:49

标签: assembly x86-16 bios

作为学校项目的一部分,我正在尝试制作蛇游戏。到目前为止,我设法绘制了一个像素并使它使用a,w,s,d键作为箭头移动。我的问题是,我的蛇不等仅在按下某个键时移动并改变方向,而是等待按键(这意味着暂停整个程序),然后才继续移动。据我了解,我一直在使用错误的中断(int 16h \ 00),我想知道我可以使用哪些其他中断。

我已经尝试了int 16h \ 01,但它所做的只是一次改变了方向,然后继续朝该方向移动。

这是我代码中负责更改像素位置的部分:

      proc check_press


        ; check for a key press
            mov ah,0
            int 16h 


        ;check what key
        check_key:
            cmp al,119
            je down
            cmp al,97
            je left
            cmp al,100
            je right
            cmp al,115
            je up
            cmp al, 27
            je escape

        up:
        inc [y]
        jmp bye

        left:
        dec [x]
        jmp bye

        down:
        dec [y]
        jmp bye

        right:
        inc [x]
        jmp bye

        escape:
        mov ah, 0
        mov al, 2
        int 10h 

        bye:

    ret 
   endp check_press 

我要感谢任何想法的人,或者即使有人曾经在汇编中编写过蛇游戏,也会有很大帮助

2 个答案:

答案 0 :(得分:3)

  

我已经尝试了int 16h \ 01,但它所做的只是一次改变了方向,然后继续朝该方向移动。

Ralph Brown's interrupt list包含几乎所有MS-DOS和BIOS中断的描述。

本页上关于int 16h,功能01的描述是:

  

...
  返回:
  如果没有可用的击键,则设置ZF
  ZF清除是否有按键操作
  AH = BIOS扫描代码
  AL = ASCII字符

     

注意:如果存在击键,则不会从键盘缓冲区中将其移除
  ...

这意味着该函数将返回AX中的值,该值表示以后调用函数00时将返回的值。

假设您按下“ A”,“ B”,“ C”和“ D”键,并且您没有调用任何int 16h函数。稍后,您将函数00调用四次。在这种情况下,您希望第一次返回“ A”,第二次返回“ B”,第三次返回“ C”,第四次返回“ D”。

如果在第一次调用函数01之前调用函数00,该函数将始终返回“ A”(尽管稍后您按了“ B”,“ C”和“ D”),因为函数00在下次调用时将返回“ A”。

如果您不调用函数00,则函数01将永远返回“按键'A'被按下”。

如果函数int 16h返回了00,您必须调用01,函数ZF=clear

  mov ah, 1
  int 16h
  jz noKeyPressed
  mov ah, 0
  int 16h
  ; AX contains information about the key pressed
  ...
noKeyPressed:
  ...

答案 1 :(得分:2)

通常,您希望蛇自行移动,而不是在您按向左键时向左移动一个方块。因此,您应该设置方向变量,而不要修改xy 。您的整个设计都是基于这种“按动”行为构建的,因此您必须重写很多设计。

您可能想在蛇更新之前使用非阻塞键盘读取来检查键盘输入。或钩住键盘中断并从那里更新方向变量。

您可以使用hlt睡觉直到下一个中​​断(例如计时器或键盘),然后醒来,看看是否该重绘蛇了。

另一种选择可能是从计时器中断中提取蛇,但是在中断处理程序中做很多工作是不好的。