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:
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, ...
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.
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.