简体   繁体   中英

Keyboard Input in Assembly 8086

I'm trying to create an animation in assembly 8086, controlled by the keyboard, using ctrl and shift as left and right.

I tried to look how to recieve input from the keyboard in 8086, and than how to find out that the key that was pressed is ctrl or shift (and generally, which key was pressed).

Thank you very much!

Are you sure you wouldn't rather use the arrow keys for left and right? The problem with control and shift is that they don't "return" a key, they modify another key that is pressed. This is handled in the keyboard interrupt handler (9, IIRC), and you could "hook" that. I think it would be easier to look in the "Bios Data Area" and watch where the interrupt handler keeps track of the state of control and shift keys. Seems to me the BDA was in segment 40h. Keyboard status flags at... 17h and 18h? Don't take my word for those offsets, look it up. Ralf Brown's Interrupt List. This all assumes that "8086" means, like... antiquities. :)

Assuming that you're doing this running under only BIOS, you may find it easier to use the higher level BIOS keyboard interrupts - int 0x16 AH=0x01 for general keystrokes, and int 0x16 AH=0x02 for ctrl/shift etc are likely possibilities, although there are a number of other possibilities (including other int 0x16 command and -as has been previously suggested - the low level keyboard int 0x09 and the BIOS data area.. I strongly second the recommendation of Ralf Brown's Interrupt List - an excellent resource!

The Bios stores the keys in a 16 letter buffer. Meaning if an os is too slow, whenever it reads the next keystroke it reads from the buffer.

You can use int 16h with ah set to 02h to set al as the next char in the buffer. HOWEVER if you are checking the status of the buffer (is there a key) look at this. It basically goes into more depth of ah 02h

Since you are asking about the arrow keys, here are their hex codes:

  1. U 0x18
  2. D 0x19
  3. L 0x1B
  4. R 0x1A

The usual choice to control movement is through the arrow keys on the keyboard. The Shift , Ctrl , and Alt keys are often used as action keys: think of actions like firing, jumping, using gadgets, ...

Using the arrow keys

In your main loop you check whether a keystroke is available. BIOS has the CheckKeystroke function 01h for this. If it returns with the zero flag set (ZF=1) then no key is waiting and you can just continue the loop. But if the zero flag is clear (ZF=0) then a key (at least one) is waiting in the keyboard buffer that BIOS maintains. It is imperative that you remove this key from the buffer. If you didn't, the buffer would rapidly fill up to its maximum of 15 keys and you could be loosing control of your program. BIOS has the GetKeystroke function 00h to fetch the oldest key from the buffer, returning its ASCII code in the AL register and its scancode in the AH register. (If the buffer were empty this function would wait for a key to get pressed, but in our case this will not be happening since we checked the availability of a key beforehand).
The arrow keys that interest us are identified by their scancode in the AH register: Up =48h, Left =4Bh, Right =4Dh, Down =50h.

Using the modifier keys

In your main loop you ask BIOS for its keyboard flags. If you don't need to distinguish between the Left-Ctrl , Left-Alt , Right-Alt , Right-Ctrl keys then you can use the BIOS GetKeyboardFlags function 02h that returns the following items in the AL register:

76543210
.......1  Right shift key is depressed
......1.  Left shift key is depressed
.....1..  Either ctrl key is depressed
....1...  Either alt is depressed
...1....  Scroll lock is enabled
..1.....  Num lock is enabled
.1......  Caps lock is enabled
1.......  Insert key is enabled

If you do need to distinguish between the Left-Ctrl , Left-Alt , Right-Alt , Right-Ctrl keys then you can use the BIOS GetKeyboardFlags function 12h that additionally returns the following items in the AH register:

76543210
.......1  Left ctrl key is depressed
......1.  Left alt key is depressed
.....1..  Right ctrl key is depressed
....1...  Right alt is depressed
...1....  Scroll lock is depressed
..1.....  Num lock is depressed
.1......  Caps lock is depressed
1.......  SysRq key is depressed (Acer reports Insert key)

The included demo program shows a paddle floating near the bottom of the screen going back and forth from left to right.
If UseArrows is enabled (non-zero), then pressing Left-Arrow or Right-Arrow will change the paddle's direction.
If UseShifts is enabled (non-zero), then pressing Left-Shift or Right-Shift will change the paddle's direction.
You can have UseArrows and UseShifts enabled together.
Press Esc to stop the program.

  ORG  256              ; Assembled with FASM
  UseShifts = 0
  UseArrows = 1

  mov  ax, 0003h        ; BIOS.SetVideoMode 80x25 text
  int  10h
  mov  dx, 1724h        ; DX is position (36,23)
  xor  bx, bx

MainEx:
  mov  cx, bx           ; CX is direction [-1=Left,0=Right]
Main:
  call Delay

  jcxz .Right
.Left:
  cmp  dl, 2            ; Left border
  ja   .Move
  jmp  .Turn
.Right:
  cmp  dl, 72           ; Right border
  jb   .Move
.Turn:
  not  cx               ; -> CX is new direction
.Move:
  call MovePaddle       ; -> DX is new position
  call MovePaddle       ; -> DX is new position

  IF UseShifts
    mov  ah, 02h          ; BIOS.GetKeyboardFlags
    int  16h              ; -> AL
    test al, 00000011b
    jz   .Neither
    xor  bx, bx
    test al, 00000001b
    jnz  MainEx           ; Set direction=0 on <RIGHT-SHIFT>
    not  bx
    jmp  MainEx           ; Set direction=-1 on <LEFT-SHIFT>
  .Neither:
  END IF

  mov  ah, 01h          ; BIOS.CheckKeystroke
  int  16h              ; -> AX ZF
  jz   Main             ; No key available
  mov  ah, 00h          ; BIOS.GetKeystroke
  int  16h              ; -> AX
  IF UseArrows
    xor  bx, bx
    cmp  ah, 4Dh
    je   MainEx           ; Set direction=0 on <RIGHT-ARROW>
    not  bx
    cmp  ah, 4Bh
    je   MainEx           ; Set direction=-1 on <LEFT-ARROW>
  END IF
  cmp  al, 27
  jne  Main             ; Ignore all other keys except <ESC>
Exit:
  int  20h              ; DOS.TerminateProgram
; ----------------------
; IN () OUT ()
Delay:
  push ds ax
  xor  ax, ax
  mov  ds, ax
  mov  ax, [046Ch]      ; BIOS.TimerTick
.Again:
  cmp  ax, [046Ch]
  je   .Again           ; TimerTick didn't change
  pop  ax ds
  ret
; ----------------------
; IN (cx,dx) OUT (dx)
MovePaddle:
  push ax bx cx
  mov  ax, 0001h        ; Move right .. Wipe at +0, Draw at +1
  jcxz .Wipe
  mov  ax, 05FAh        ; Move left  .. Wipe at +5, Draw at -6
.Wipe:
  push ax               ; (1)
  add  dl, ah           ; AH is {0,5}
  mov  bx, 0007h        ; BH is DisplayPage, BL is Attribute
  mov  ah, 02h          ; BIOS.SetCursorPosition
  int  10h
  mov  cx, 1            ; ReplicationCount (PaddleStep)
  mov  ax, 0920h        ; BIOS.WriteCharacterAndAttribute, AL is Space
  int  10h
.Draw:
  pop  ax               ; (1)
  add  dl, al           ; AL is {1,-6}
  mov  ah, 02h          ; BIOS.SetCursorPosition
  int  10h
  mov  cx, 6            ; ReplicationCount (PaddleLength)
  mov  bl, 0Eh          ; BL is Attribute
  mov  ax, 09DCh        ; BIOS.WriteCharacterAndAttribute, AL is HalfBlock
  int  10h
  pop  cx bx ax
  ret
; ----------------------

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM