Can't Handle IRQ's in Real Mode

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
yasar11732
Member
Member
Posts: 28
Joined: Thu Sep 27, 2018 5:10 pm
Libera.chat IRC: yasar
Location: Turkey
Contact:

Can't Handle IRQ's in Real Mode

Post by yasar11732 »

I am using following code to handler timer and keyboard IRQ's

Code: Select all

.code16
.text

setup:
    cli
    # setup stack segment
    xor %ax, %ax
    mov %ax, %ss
    mov $0x7bf, %ax
    mov %ax, %sp

    # setup data segment
    xor %ax,%ax
    mov %ax, %ds

    # setup video memory
    mov $0xB800, %ax
    mov %ax, %gs
    sti

init_random_value:
    mov $0,%ah
    int $0x1a
    mov %dx,random

register_interrupt_handlers:
    cli
    # timer (int $0x08)
    push %es
    push $0
    pop %es

    # IRQ0->INT 8 (4*8 = 32)
    mov $32,%bx

    movw $timer_handler,%es:(%bx)
    inc %bx
    inc %bx
    movw $0,%es:(%bx)
    inc %bx
    inc %bx
    movw $keyboard_handler,%es:(%bx)
    inc %bx
    inc %bx
    movw $0,%es:(%bx)

    pop %es
    sti

busy_loop:
    mov timer_ticks,%ax
    add $18,%ax
_wait:
    mov timer_ticks,%bx
    cmp %ax,%bx
    jg stop_waiting
    hlt
    jmp _wait
stop_waiting:
    call get_random
    mov $0x0E, %ah
    int $0x10 # output random value
    jmp busy_loop

timer_handler:
    pusha
    incw timer_ticks

    mov $20,%al
    out %al,$20
    popa
    iret

keyboard_handler:
    pusha
    in $0x60,%al
    mov %al,scancode
    
    mov $20,%al
    out %al,$20
    popa
    iret

/* Returns 16bit pseudo-random number in ax */
.global get_random
.type get_random,@function
get_random:
    mov random,%ax
    shl $2,%ax
    inc %ax
    mov %ax,random
    ret

.data
.align 2
random:
    .2byte 0

timer_ticks:
    .2byte 0

scancode:
    .2byte 0
I run this code in VirtualBox and check the memory address where timer_ticks and scancode supposed to be. It appears that IRQ handlers are not fired.

How can I make this work?
MichaelPetch
Member
Member
Posts: 799
Joined: Fri Aug 26, 2016 1:41 pm
Libera.chat IRC: mpetch

Re: Can't Handle IRQ's in Real Mode

Post by MichaelPetch »

You could be having issues because of how you build this or how it is run .I don't know if this was in a bootloader or not. Are you using a linker script, if not what linker command do you use? Showing us exactly how you generate the code, and tell us how you run it.

With that being said the most obvious thing I see wrong is how you send EOI to the PIC. You do:

Code: Select all

mov $20,%al
out %al,$20
(youdo this in two places). That should be 0x20 hex not decimal. Try

Code: Select all

mov $0x20,%al
out %al,$0x20
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Can't Handle IRQ's in Real Mode

Post by Brendan »

Hi,
yasar11732 wrote:I am using following code to handler timer and keyboard IRQ's
There's multiple issues here (in addition to the EOI problem MichaelPetch mentioned).

The BIOS will probably need a few KiB of stack space, but you set SS:SP to 0x0000:0x07BF so that there's only about half a KiB of space before the BIOS overwrites its own data in the BDA. It's also strange to misalign the stack. I'm thinking that this might have been a typo (and that you actually wanted SS:SP to 0x0000:0x7C00 so that the first word pushed on the stack ends up just below the code at 0x00007BFE).

If you're not using a linker (which doesn't make too much sense given that most tools don't support real mode); then you're missing an "ORG 0x7C00" at the top or something to define sections.

When registering your interrupt handlers, you're saving and restoring ES for no reason (because it wasn't set to anything that matters in the first place) and could use DS instead of ES (because DS is already set to 0x0000) and avoid an extra "segment override prefix" on some instructions. It would also be more efficient to do direct writes, so the entire thing becomes something like:

Code: Select all

    cli
    movw $timer_handler,(32)
    movw $0,(34)
    movw $keyboard_handler,(36)
    movw $0,(38)
    sti
Your code to get a random number seems strange - after being called 8 times you can guarantee it will always return 0x5555, and after being called 4 times you can guarantee the value 0x55 will be in AL. I'm not sure if you wanted the last instruction to be "xor %ax,random".

Finally; I'm not sure why you're doing this in the first place. The BIOS already has IRQ handlers that aren't broken (e.g. that convert scan codes to ASCII for you and may work with USB keyboards when the nasty and often buggy "PS/2 emulation" isn't enabled); and I'm worried that you're planning to fall into the "real mode OS trap".


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
MichaelPetch
Member
Member
Posts: 799
Joined: Fri Aug 26, 2016 1:41 pm
Libera.chat IRC: mpetch

Re: Can't Handle IRQ's in Real Mode

Post by MichaelPetch »

Brendan wrote:If you're not using a linker (which doesn't make too much sense given that most tools don't support real mode); then you're missing an "ORG 0x7C00" at the top or something to define sections.
The ORG directive (.org) doesn't work the same in GNU assembler as it does in NASM as far as I know. It is possible to do without an ORG directive using the linker with the default linker script. By linking with -Ttext=0x7c00 .However this would pose a different problem since the OP declares a .data section which would likely default to 4kb alignment. I felt the OP might be using a linker script since the boot signature was notably absent. Was the main reason I inquired about how this was being built.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Can't Handle IRQ's in Real Mode

Post by Brendan »

Hi,
MichaelPetch wrote:
Brendan wrote:If you're not using a linker (which doesn't make too much sense given that most tools don't support real mode); then you're missing an "ORG 0x7C00" at the top or something to define sections.
The ORG directive (.org) doesn't work the same in GNU assembler as it does in NASM as far as I know. It is possible to do without an ORG directive using the linker with the default linker script. By linking with -Ttext=0x7c00 .However this would pose a different problem since the OP declares a .data section which would likely default to 4kb alignment. I felt the OP might be using a linker script since the boot signature was notably absent. Was the main reason I inquired about how this was being built.
Ah - you're right (I forgot ORG works very different for GAS).

I hope they're not using the GNU linker - it doesn't support real mode properly. More specifically, it doesn't support segmentation and only has partial support for "16-bit code pretending not to be 32-bit code". I'm not sure what other options there are (YASM supports AT&T and flat binary but I'm not sure about the directives).


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
yasar11732
Member
Member
Posts: 28
Joined: Thu Sep 27, 2018 5:10 pm
Libera.chat IRC: yasar
Location: Turkey
Contact:

Re: Can't Handle IRQ's in Real Mode

Post by yasar11732 »

MichaelPetch wrote:You could be having issues because of how you build this or how it is run .I don't know if this was in a bootloader or not. Are you using a linker script, if not what linker command do you use? Showing us exactly how you generate the code, and tell us how you run it.
This is my Makefile

Code: Select all

boot.iso: deploy/boot.bin
	mkisofs -b boot.bin -hide boot.bin -iso-level 3 -no-emul-boot -o boot.iso deploy/

deploy/boot.bin: build/snake.o
	ld -Ttext 7c00 --oformat=binary build/snake.o -nostartfiles -nostdlib -o deploy/boot.bin

build/snake.o: snake.s
	as snake.s -o build/snake.o
MichaelPetch wrote: With that being said the most obvious thing I see wrong is how you send EOI to the PIC. You do:

Code: Select all

mov $20,%al
out %al,$20
(youdo this in two places). That should be 0x20 hex not decimal. Try

Code: Select all

mov $0x20,%al
out %al,$0x20
Thanks, that fixed the problem of IRQ's not firing.
Brendan wrote:Hi,

The BIOS will probably need a few KiB of stack space, but you set SS:SP to 0x0000:0x07BF so that there's only about half a KiB of space before the BIOS overwrites its own data in the BDA. It's also strange to misalign the stack. I'm thinking that this might have been a typo (and that you actually wanted SS:SP to 0x0000:0x7C00 so that the first word pushed on the stack ends up just below the code at 0x00007BFE).
My intention was to put stack 2 byte below the 0x7C00. It was supposed to be 0x7BFD. I was in the impression that putting the stack at 0x7C00 would overwrite my code.
Brendan wrote: If you're not using a linker (which doesn't make too much sense given that most tools don't support real mode); then you're missing an "ORG 0x7C00" at the top or something to define sections.
I am passing -Ttext 7c00 to my ld. Since I am booting with El Torito, I am not using bios magic value, since it works without it too.
Brendan wrote:Hi,

When registering your interrupt handlers, you're saving and restoring ES for no reason (because it wasn't set to anything that matters in the first place) and could use DS instead of ES (because DS is already set to 0x0000) and avoid an extra "segment override prefix" on some instructions. It would also be more efficient to do direct writes, so the entire thing becomes something like:

Code: Select all

    cli
    movw $timer_handler,(32)
    movw $0,(34)
    movw $keyboard_handler,(36)
    movw $0,(38)
    sti
That was the first thing I tried. After seeing that it didn't work, I tried random things until I gave up and started this thread.
Brendan wrote: Your code to get a random number seems strange - after being called 8 times you can guarantee it will always return 0x5555, and after being called 4 times you can guarantee the value 0x55 will be in AL. I'm not sure if you wanted the last instruction to be "xor %ax,random".
My random sequence was supposed to be next = 5 * prev + 1 (mod 2^16). Maybe I should sleep more :/ Fixed it now.
Brendan wrote: Finally; I'm not sure why you're doing this in the first place. The BIOS already has IRQ handlers that aren't broken (e.g. that convert scan codes to ASCII for you and may work with USB keyboards when the nasty and often buggy "PS/2 emulation" isn't enabled); and I'm worried that you're planning to fall into the "real mode OS trap".
I am trying to do Snake game that works in real mode. I will read direction keys with keyboard interrupts and run main loop with timer interrupts.
yasar11732
Member
Member
Posts: 28
Joined: Thu Sep 27, 2018 5:10 pm
Libera.chat IRC: yasar
Location: Turkey
Contact:

Re: Can't Handle IRQ's in Real Mode

Post by yasar11732 »

MichaelPetch wrote:
Brendan wrote:If you're not using a linker (which doesn't make too much sense given that most tools don't support real mode); then you're missing an "ORG 0x7C00" at the top or something to define sections.
The ORG directive (.org) doesn't work the same in GNU assembler as it does in NASM as far as I know. It is possible to do without an ORG directive using the linker with the default linker script. By linking with -Ttext=0x7c00 .However this would pose a different problem since the OP declares a .data section which would likely default to 4kb alignment. I felt the OP might be using a linker script since the boot signature was notably absent. Was the main reason I inquired about how this was being built.
That explains why I am getting huge binary for no reason :) I thought I would get away with not using a linker script.
MichaelPetch
Member
Member
Posts: 799
Joined: Fri Aug 26, 2016 1:41 pm
Libera.chat IRC: mpetch

Re: Can't Handle IRQ's in Real Mode

Post by MichaelPetch »

Just combine your .data into your .text section. This can easily be done by getting rid of the .data line.
Post Reply