Key Input Using Interrupt

BIOS interrupts provide a way to interact with various hardware components. One such interrupt, int 0x16, allows us to interface with the keyboard. By using BIOS interrupt int 0x16 with function AH=00h, we can wait for a key press and retrieve the scancode of the pressed key.

BIOS Interrupt 16H

  • AH = 00h: Wait for key press and retrieve scan-code
    • AH: Function number
    • AL: Scan-code of the pressed key
    • This service waits for a key press and returns the scan-code of the pressed key in the AL register.

Code:

[ORG 0x7C00]   ; Set the origin to the BIOS boot sector address

    ; Clear the screen
    mov ah, 0x07    ; AH = 07h (Scroll down function)
    mov al, 0       ; AL = 0 lines to scroll (clear the entire screen)
    mov bh, 0x07    ; BH = 07h (attribute byte, white on black)
    mov cx, 0x0000  ; CH = 0, CL = 0 (upper left corner)
    mov dx, 0x184F  ; DH = 24, DL = 79 (lower right corner)
    int 0x10        ; Call BIOS video interrupt

    ; Move cursor to top-left corner
    mov ah, 0x02    ; AH = 02h (Set cursor position)
    mov bh, 0x00    ; BH = 0 (Page number)
    mov dh, 0x00    ; DH = 0 (Row)
    mov dl, 0x00    ; DL = 0 (Column)
    int 0x10        ; Call BIOS video interrupt

; Get And Write Characters                                              
; Gets character from keyboard and displays it                          
characterLoop:                                   
        mov ah, 0x0      ; Get Key                           
        int 16h          ; Run keyboard command              
                         ; al now contains ascii character
        mov ah, 0xE      ; Display al character
                         ; al still set
        mov bh, 0x00     ; BH = 0 (Page number)
        mov bl, 0x07     ; BL = 07h (Attribute, white on black)
        int 10h          ; Run display command

	jmp characterLoop    ; Keep Looping    
; Loop Never Ends

    ; Infinite loop
    cli             ; Clear interrupts
.endloop:
    hlt             ; Halt processor
    jmp .endloop    ; Infinite loop

times 510 - ($-$$) db 0   ; Fill the rest of the sector with zeros
dw 0xAA55                 ; Boot signature
image-125.png

This code does not handled the line change on press of enter key.

Let's handle the enter key press:

Code Snippet:

characterLoop:
    mov ah, 0x00        ; AH = 00h (Get Key)
    int 0x16            ; Call BIOS keyboard interrupt
                        ; AL now contains ASCII character

    cmp al, 0x0D        ; Check if Enter key is pressed
    je nextLine         ; Jump to next line if Enter is pressed

    mov ah, 0x0E        ; AH = 0Eh (Display character)
    mov bh, 0x00        ; BH = 0 (Page number)
    mov bl, 0x07        ; BL = 07h (Attribute, white on black)
    int 0x10            ; Call BIOS video interrupt

    jmp characterLoop   ; Keep looping

nextLine:
    mov ah, 0x02        ; AH = 02h (Set cursor position)
    mov bh, 0x00        ; BH = 0 (Page number)
    inc dh              ; DH = 1 (Move to next line)
    mov dl, 0x00        ; DL = 0 (Column)
    int 0x10            ; Call BIOS video interrupt

    jmp characterLoop   ; Continue looping

times 510 - ($-$$) db 0   ; Fill the rest of the sector with zeros
dw 0xAA55                 ; Boot signature

In this modified code:

  • cmp al, 0x0D checks if the Enter key (ASCII code 0x0D) is pressed.
  • If the Enter key is pressed, it jumps to the nextLine label, where the cursor is moved to the beginning of the next line.
  • If any other key is pressed, it continues to display the character and stays on the same line.
image-126.png

Now, let's handle TAB press to erase the last character:

TODO

Code Snippet:

waitForKey:
    mov ah, 0x00    ; AH = 00h (Wait for key press)
    int 0x16        ; Call BIOS keyboard interrupt
                    ; AL now contains scancode of pressed key

    cmp al, 0x0D    ; Check if Enter key is pressed
    je enterPressed ; Jump if Enter key is pressed

    cmp al, 0x08    ; Check if Backspace key is pressed
    jne notSpecial  ; Jump if not Enter or Backspace

backspacePressed:
    ; Move cursor back one position
    mov ah, 0x02    ; AH = 02h (Set cursor position)
    mov bh, 0x00    ; BH = 0 (Page number)
    dec dl          ; Decrement DL to move back one column
    int 0x10        ; Call BIOS video interrupt
    jmp waitForKey ; Wait for the next key press

enterPressed:
    ; Move cursor to the beginning of the next line
    mov ah, 0x02    ; AH = 02h (Set cursor position)
    mov bh, 0x00    ; BH = 0 (Page number)
    inc dh          ; Increment DH to move to the next line
    mov dl, 0x00    ; DL = 0 (Column)
    int 0x10        ; Call BIOS video interrupt
    jmp waitForKey ; Wait for the next key press

notSpecial:
    ; Display the pressed character
    mov ah, 0x0E    ; AH = 0Eh (Display character)
    mov bh, 0x00    ; BH = 0 (Page number)
    mov bl, 0x07    ; BL = 07h (Attribute, white on black)
    int 0x10        ; Call BIOS video interrupt
    jmp waitForKey ; Wait for the next key press