Search code examples
assemblykeyboardasciix86-16bios

How do i check if the arrow keys are pressed in assembly 16 Bits bare bones


I try to check if the arrow keys are pressed and i started with the up key but

cmp al, 48h ;if you press the up arrow
je  .up_pressed

nor

cmp al, 48  ;if you press the up arrow
je  .up_pressed

work, it is or 8 or none, and i cant find anything that works for me! does anyone know what the correct code is? it can be hexadecimal ascii or binary. (i need the left, right, down & up keys)

but these DO work:

cmp al, 13  ;if you press enter
je  .done

cmp al, 8       ;if you press backspace
je  .backspace

i do not get input via:

mov ah, 00h
int 16h

but:

cmd:
call newline
mov si, prompt
call    Print
mov di, input_buffer
mov al, 0
mov cx, 256
rep stosb
mov ax, input_buffer
mov di, input_buffer
;check for characters typed
.loop:
call    keyboard

cmp al, 13  ;if you press enter
je  .done

cmp al, 8       ;if you press backspace
je  .backspace

cmp al, 27  ;if you press ESC
je  .escape_pressed

cmp al, 48h ;if you press the up arrow
je  .up_pressed

jmp .character  ;otherwise just register a character

.up_pressed:
call newline
mov si, debug
call Print
jmp cmd

.backspace:     ;remove a character
mov ah, 0Eh
mov al, 8
int 10h
mov al, 32
int 10h
mov al, 8
int 10h
dec di
jmp .loop

.escape_pressed:
call newline
mov si, escape_pressed_message
call Print
jmp cmd

.character:     ;register a character
mov ah, 0Eh
int 10h
stosb
jmp .loop

.done:          ;start comparing input<->commands
mov ax, 0
stosb

call    newline ;but first make a new line

mov si, input_buffer
cmp BYTE [si], 0

je  cmd

there is a call to keyboard so here the keyboard code:

keyboard:
       pusha
       mov  ax, 0
       mov  ah, 10h
       int  16h
       mov  [.buffer], ax
       popa
       mov  ax, [.buffer]
       ret

       .buffer  dw  0

Solution

  • First off, simplify the code a bit. Pushing and popping here was quite useless.

    keyboard:
        mov  ah, 00h
        int  16h
        mov  [.buffer], ax
        ret
        .buffer  dw  0
    

    If there's no particular reason then don't use the 10h function on int 16h. Stick with the 00h function to retrieve a key from int 16h.

    For the up key this function will give you a scancode in the AH register, so that is where your program needs to look:

    cmp al, 27      ;if you press ESC
    je  .escape_pressed
    
    cmp AH, 48h     ;if you press the up arrow
    je  .up_pressed
    
    jmp .character  ;otherwise just register a character
    

    Important

    Don't look for the up key by comparing the whole AX register!
    You will not always recieve AX=4800h.

    • When the up key on the numerical keypad was used, you will get AX=48E0h instead.
    • When you combine the up key with Shift, Alt (or AltGr), or Ctrl you will get values like 4838h, 0008h, 8D00h, 48E0h, 9800h, 8DE0h respectively.

    The other keys are:

    cmp AH, 50h     ;if you press the down arrow
    je  .down_pressed
    cmp AH, 4Bh     ;if you press the left arrow
    je  .left_pressed
    cmp AH, 4Dh     ;if you press the right arrow
    je  .right_pressed