Problems with overwriting the keyboard ivt

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
SCHiM
Posts: 5
Joined: Tue Nov 23, 2010 10:52 am

Problems with overwriting the keyboard ivt

Post by SCHiM »

I run into trouble every time I try to overwrite the default interrupt vector for the keyboard in unreal mode.

Each time I press a key after I changed the ivt bochs throws an error my way and halts (note no triple fault)

Here's what I do:

I switch to protected mode, change all my segments to 32 bit(cs and ss not included) and then switch back to real mode. After outputting a message to inform the user of success, I do this:

Code: Select all


   cli      ;no interruptions
   mov bx, 0x09   ;hardware interrupt #
   shl bx, 2   ;multiply by 4
   xor ax, ax
   mov gs, ax   ;start of memory
   mov [gs:bx], word getc
   mov [gs:bx+2], ds ; segment = 0 (while debugging)
   sti
 
getc code:
I took this code from one of the babysteps tutorials.

Code: Select all

   pusha
 
   ;Apparently spinning until the byte is ready is necessary on some older machines.
 .spin:
   in  al, 0x64
   and al, 0x01
   jz  .spin
	
	xor eax, eax
   ;read scancode
   in  al, 0x60
 
	and al, 0x80
	jz Done
   ;Here you can do with the scancode whatever you like.
   ;For example converting it to another keyboard layout or test for special keys and trigger a reboot
   
    lea ax, [KeyMap]
	add bx, ax
	mov cl, byte [bx]
	mov ch, 0x7
	
		push cx
		push 0xb8000
		call putc
	
   ;Now we tell the first PIC that the IRQ is handled
Done:
   
   mov al, 0x20
   out 0x20, al
 
   popa
 iret
I've checked in my debugger to see if the ivt is correctly changed, and it is, I'm correctly overwriting the ninth entry in the table. So it looks like this:

Code: Select all

8. 0xbar:0xfoo
9. 0x0000:0xcorrect address to getc function(I checked)
10. 0xbar:0xfoo
 
In the bochs output window I get these error messages respectively:

This recursive error I get when I replace the segment of the handler with 0(my ds):

int13_cdrom: function 00, ELDL out of range fe (this goes on indefinitely)

If I don't replace the segment of the handler, I get this error after a considerable timeout (after pressing a key) and no triple fault:

int13_cdrom: function 00, status 04 !

I think I'm overwriting the wrong address (obviously)
Does anyone know how to fix this?

ps, before you ask, I'm not switching to pmode because I tried that and found that it was too hard to start with. And I'm not staying in realmode since I want more memory to play with, even if I don't need it and programs can't run outside the first 64KBs of memory.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Problems with overwriting the keyboard ivt

Post by Brendan »

Hi,
SCHiM wrote:This recursive error I get when I replace the segment of the handler with 0(my ds):

int13_cdrom: function 00, ELDL out of range fe (this goes on indefinitely)

If I don't replace the segment of the handler, I get this error after a considerable timeout (after pressing a key) and no triple fault:

int13_cdrom: function 00, status 04 !
Unfortunately, the BIOS uses interrupts 0x08 to 0x0F for IRQs while the CPU uses them for exceptions. This means that if anything in your code causes an exception, you end up executing an IRQ handler for no reason and ignoring the problem; then the IRQ handler returns and the same instruction that caused the exception is executed again (leading to an infinite loop of stupidity, where strange things happen for no sane reason).

There are a few ways to protect against that. The easiest way is to add code for IRQs 0 to 7 that checks the PIC to see if the corresponding IRQ was sent (or if it wasn't and the handler was called because of an exception). This includes all of those interrupts (e.g. dummy stubs that check if it was an exception or an IRQ, that jump to the BIOS IRQ handler if it actually was an IRQ).

I don't know what is causing the initial exception; but the IRQ handling code from the babysteps tutorial looks like poo, probably because it was intended for protected mode and hasn't been modified for real mode properly. For example, it doesn't save/restore segment registers, uses PUSHA/POPA when it should use PUSHAD/POPAD (or only save/restore registers it changes), does "lea ax, [KeyMap]; add bx, ax; mov cl, byte [bx]" when it could just do "mov cl, byte [eax+keymap]", does "push 0xB8000" when 0xB8000 is too large to fit in 16-bits, etc.
SCHiM wrote:ps, before you ask, I'm not switching to pmode because I tried that and found that it was too hard to start with. And I'm not staying in realmode since I want more memory to play with, even if I don't need it and programs can't run outside the first 64KBs of memory.
That's probably a bad idea - for protected mode you need to learn how the CPU and various pieces of hardware work, but in the long run it's worthwhile. For real mode (which includes "unreal mode") you need to learn a lot of historical hackery and work-arounds instead, and in the long run most of it is a waste of time (and not just because the BIOS is obsolete/dead).

Imagine an "aircraft engineer" that spends all their time creating paper planes because real aircraft are too hard.


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.
User avatar
Chandra
Member
Member
Posts: 487
Joined: Sat Jul 17, 2010 12:45 am

Re: Problems with overwriting the keyboard ivt

Post by Chandra »

SCHiM wrote:I think I'm overwriting the wrong address (obviously)
I have a feeling that you did overwrite the right address but with the wrong handler.

Code: Select all

int13_cdrom:
That lets me to assume you overwrote the keyboard IVT handler with the Int 13h handler.

Code: Select all

cli                      ;no interruptions
mov bx, 0x09       ;hardware interrupt #
shl bx, 2              ;multiply by 4
xor ax, ax
mov gs, ax           ;start of memory
mov [gs:bx], word getc
mov [gs:bx+2], ds  ; segment = 0 (while debugging)
sti
As a part of debugging, I'd first examine that the correct offset of getc is moved to [gs:bx]. This explicitly depends upon the ORG directive you specify.
Programming is not about using a language to solve a problem, it's about using logic to find a solution !
Post Reply