Keyboard Interrupt Handler 16 bit

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
thebayliff
Posts: 4
Joined: Sat Nov 05, 2022 2:55 am

Keyboard Interrupt Handler 16 bit

Post by thebayliff »

I'm having some issues with trying to get multiple instances of keyboard input (more than one key). I have looked at https://wiki.osdev.org/Babystep5 and various tutorials online. I'll keep the mostly relevant portions of my code down below. This is still in 16 bit mode. I am using qemu inside of WSL to test.

A few of the common sense self checks that I have done so far:
1. I am registering the handler (it gets called the first time!)
2. The handler does read the input it is being sent and sends the EIO back to the PIC.
3. Interrupts are enabled.
4. The main loop is just a hlt statement.

Code: Select all

keyboard_handler: # 0x7d11 
    push %ax
    push %cx

    in $0x60, %al # We read from i/o port 0x60, this is the key code
    mov %al, %cl

    in $0x61, %al
    mov %al, %ah
    or $0x80, %al
    xchg %al, %ah
    out %al, $0x61

    mov $0x20, %al
    out %al, $0x20

    and $0x80, %cl

    push $0x1d
    push $detect
    call print_string

    pop %bx
    pop %ax
    iret

main:
    xor %ax, %ax
    mov %ax, %ds
    mov %ax, %ss
    mov $0xFFFF, %bp 
    mov %bp, %sp 

    mov $0x09, %bx # The interrupt handler for keyboard
    shl $2, %bx # left shift 2 = multiply by 4
    cli
    movw $keyboard_handler, (%bx)
    mov %ax, 2(%bx)
    sti

    mov $0xB800, %ax 
    movw $0x0000, %bx
    mov %ax, %gs 
    call clear_screen

    push $0xFF
    push $hello # Put the parameter on the stack
    call print_string
    add $4, %sp

    push %ax
    push $hex_array + 2 # hex_array points to the first byte ('0'), but we will only overwrite the 3rd and 4th bytes. 
    call convert_16_bit_num_to_hex_string
    add $4, %sp

    push $0x07
    push $hex_array
    call print_string
    add $4, %sp

end:
    hlt
    jmp end
    . = _start + 510
    .byte 0x55
    .byte 0xAA 

nullplan
Member
Member
Posts: 1790
Joined: Wed Aug 30, 2017 8:24 am

Re: Keyboard Interrupt Handler 16 bit

Post by nullplan »

So, one thing I see immediately is that at the beginning of the keyboard handler, you push AX and CX, and at the end you pop BX and AX. That is going to cause register corruption one the main program gets longer.

The second thing I notice is that after calling print_string in the main program, you increase SP by four, but you don't do that in the keyboard handler. Is it possible you are corrupting the stack? In that case, the IRET instruction would not return you to the HLT loop but somewhere else, and then everything would go off the rails from there.
Carpe diem!
Octocontrabass
Member
Member
Posts: 5562
Joined: Mon Mar 25, 2013 7:01 pm

Re: Keyboard Interrupt Handler 16 bit

Post by Octocontrabass »

thebayliff wrote:

Code: Select all

    in $0x61, %al
    mov %al, %ah
    or $0x80, %al
    xchg %al, %ah
    out %al, $0x61
You're trying to manipulate a register that doesn't exist in any AT-compatible or newer PC, and you're doing it incorrectly. What exactly is your target hardware?
thebayliff
Posts: 4
Joined: Sat Nov 05, 2022 2:55 am

Re: Keyboard Interrupt Handler 16 bit

Post by thebayliff »

nullplan wrote:So, one thing I see immediately is that at the beginning of the keyboard handler, you push AX and CX, and at the end you pop BX and AX. That is going to cause register corruption one the main program gets longer.

The second thing I notice is that after calling print_string in the main program, you increase SP by four, but you don't do that in the keyboard handler. Is it possible you are corrupting the stack? In that case, the IRET instruction would not return you to the HLT loop but somewhere else, and then everything would go off the rails from there.
This was exactly it. The stack corruption was messing me up. Changing the registers worked.
Octocontrabass wrote:
thebayliff wrote:

Code: Select all

    in $0x61, %al
    mov %al, %ah
    or $0x80, %al
    xchg %al, %ah
    out %al, $0x61
You're trying to manipulate a register that doesn't exist in any AT-compatible or newer PC, and you're doing it incorrectly. What exactly is your target hardware?
This was me copying from the https://wiki.osdev.org/Babystep5 trying to see if I was missing something from there (hail mary's sometimes work). Now that I got it working, I'll remove the parts that aren't necessary.
Post Reply