Interrupt Vector Table Question
Interrupt Vector Table Question
Hi everyone:
There is no problem for me to use interrupt in real mode via IVT. But in pmode when i finish setting IDT, I do not know how to re-use the interrupt like in real mode. Maybe it has some relations with interrupt handle set in interrupt descriptor.
Could anyone give me some advise?
There is no problem for me to use interrupt in real mode via IVT. But in pmode when i finish setting IDT, I do not know how to re-use the interrupt like in real mode. Maybe it has some relations with interrupt handle set in interrupt descriptor.
Could anyone give me some advise?
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Interrupt Vector Table Question
you will *not* be able to use interrupts "like in real mode". Especially, you'll have to forget the whole idea of calling INT 10h for video setting or INT 13h for disk operations.
All you can do is define your own new INTs *and* define handlers for processor exceptions and hardware interrupts.
All you can do is define your own new INTs *and* define handlers for processor exceptions and hardware interrupts.
Re:Interrupt Vector Table Question
Thank you for your help, Pype.Clicker
Sure, I know that in pmode i cannot use INT in realmode, and i should define ints, but i do not know how to define the new ints which could have the same function like ints in realmode.
And i still want to know that in pmode where the interrupt vector table is?
Could anyone help me? Thanks in advance.
Sure, I know that in pmode i cannot use INT in realmode, and i should define ints, but i do not know how to define the new ints which could have the same function like ints in realmode.
And i still want to know that in pmode where the interrupt vector table is?
Could anyone help me? Thanks in advance.
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Interrupt Vector Table Question
It is where you tell it to be. The role of the IDTR register is to keep track for the CPU of where in linear address space *you* decided to store your IDTAnd i still want to know that in pmode where the interrupt vector table is?
Code: Select all
myIdt: resd 512 ; 256 ints * 8 bytes/descriptor
IDTR: dw 256*8-1
dd myIdt
setup:
mov eax, base_address_of_your_code
add [IDTR+2],eax
lidt [IDTR]
I need you to be more precise on what you want to achieve. There's no general answer except "use V8086 mode" ...how to define the new ints which could have the same function
For instance, if all you want to do is receive IRQ1 when a key is pressed, you need to
- remap the PIC to avoid conflict with exceptions (http://www.osdev.org/osfaq2/index.php/C ... e%20PIC%3F)
- write a InterruptHandler for IRQ1 (for instance int 0x21 if you remapped IRQs starting at 0x20 like everybody around) -- see http://www.osdev.org/osfaq2/index.php/I ... ceRoutines
- read port 0x60 and send 0x20 on port 0x20 in that handler.
If you wish to have something more like RealMode INT16h (e.g. wait until a character is pressed and then return its ASCII code), sorry but you'll have to do everything yourself from the value you read out of port 0x60.
Same kind of situation occurs for reading from floppy, hard disk, setting video mode, etc.
There should be more infos about how to set up an int handler in BonaFide tutorials...
HTH
Re:Interrupt Vector Table Question
Hi Pype.Clicker, please forgive me my stupid mind, I think my expression is unclear.
Everyone knows that In real mode, the first 1,024 bytes of memory of the computer are used as the interrupt handler table. This table has a 4 byte far address to the interrupt handler (Interrupt Service Routine - ISR) for each of the 256 interrupts.
So my question is that when I enter to PMode, if I store this interrupt handler table in my IDT, could i use these ints like in realmode, for example if I want to read a sector from a floppy,
what should I do in Pmode, I think it is very easy in realmode with using int 0x13.
Thank you in advance.
Everyone knows that In real mode, the first 1,024 bytes of memory of the computer are used as the interrupt handler table. This table has a 4 byte far address to the interrupt handler (Interrupt Service Routine - ISR) for each of the 256 interrupts.
So my question is that when I enter to PMode, if I store this interrupt handler table in my IDT, could i use these ints like in realmode, for example if I want to read a sector from a floppy,
what should I do in Pmode, I think it is very easy in realmode with using int 0x13.
Thank you in advance.
Re:Interrupt Vector Table Question
No, unfortunately you can't do this. All of those interrupt handlers were designed for real mode, so you would have to run it inside v8086 which is a lot of work to write (apparently, i haven't even tried yet).
If you want to read a sector from a floppy, you have to go through and write all the code to do it yourself, reading and writing bytes to the floppy controller ports. There should be some tutorials around here on how to interface with the floppy controller, and then there is always the intel floppy controller datasheet.
And you will have to do the same thing for dealing with the keyboard, mouse, and anything else that you would want to interface with.
If you want to read a sector from a floppy, you have to go through and write all the code to do it yourself, reading and writing bytes to the floppy controller ports. There should be some tutorials around here on how to interface with the floppy controller, and then there is always the intel floppy controller datasheet.
And you will have to do the same thing for dealing with the keyboard, mouse, and anything else that you would want to interface with.
Re:Interrupt Vector Table Question
Its hard when your a beginner, so here go's
That leads to this
And these lead to this
if you want more help ask
Code: Select all
idtr: dw idt_end - idt - 1 ; IDT limit
dd idt
include 'idt.asm'
Code: Select all
idt:
;0 interrupt 0h
dw div_error ; div error
dw sys_code
db 0
db sys_interrupt
dw 0
;1 interrupt 1h
dw debug_exception ; debug exception
dw sys_code
db 0
db sys_interrupt
dw 0
;2 interrupt 2h
dw nmi_interrupt ; non maskable interrupt
dw sys_code
db 0
db sys_interrupt
dw 0
;3 interrupt 3h
dw int3_trap ; int3 trap
dw sys_code
db 0
db sys_interrupt
dw 0
;fill this with all the numbers
;253 interrupt FDh
dw unhandled_int ; reserved
dw sys_code
db 0
db sys_interrupt
dw 0
;254 interrupt FEh
dw unhandled_int ; reserved
dw sys_code
db 0
db sys_interrupt
dw 0
;255 interrupt FFh
dw unhandled_int ; reserved
dw sys_code
db 0
db sys_interrupt
dw 0
idt_end:
Code: Select all
unhandled_int:
pushad
mov ax,8h
mov es,ax
mov byte [es:0xB809E], "U"
popad
iret
nmi_interrupt:
pushad
mov ax,8h
mov es,ax
mov byte [es:0xB809E], "N"
reboot1:
jmp reboot1
popad
iret
clock_tick:
pushad
mov ax,8h
mov es,ax
;mov esi, stringZ
;call print_string
mov byte [es:0xB809E], "C"
call irq_clear
popad
iret
keyboard_irq:
pushad
;mov ax,8h
;mov es,ax
;mov byte [es:0xB809C], "K"
call key_board
popad
iret
page_fault:
pushad
mov ax,8h
mov es,ax
mov byte [es:0xB809C], "P"
popad
iret
div_error:
pushad
mov ax,8h
mov es,ax
mov byte [es:0xB809C], "D"
popad
iret
put as many as you want here
irq_clear:
push eax
mov al, 0x20
out 0x20, al ; quiet screaming irq chip.
pop eax
ret
Re:Interrupt Vector Table Question
Actually, I found it was a lot easier to write than I was expecting. I'm tempted to just cut and paste mine here. In fact...bkilgore wrote:No, unfortunately you can't do this. All of those interrupt handlers were designed for real mode, so you would have to run it inside v8086 which is a lot of work to write (apparently, i haven't even tried yet).
Code: Select all
static inline void v86push16(UInt16 x)
{
v86.tss.esp = (UInt16)(v86.tss.esp - 2);
*(UInt16*)(v86.tss.ss * 16 + v86.tss.esp) = x;
}
static inline void v86push32(UInt32 x)
{
v86.tss.esp = (UInt16)(v86.tss.esp - 4);
*(UInt32*)(v86.tss.ss * 16 + v86.tss.esp) = x;
}
static inline UInt16 v86pop16(void)
{
UInt16 result = *(UInt16*)(v86.tss.ss * 16 + v86.tss.esp);
v86.tss.esp = (UInt16)(v86.tss.esp + 2);
return result;
}
static inline UInt32 v86pop32(void)
{
UInt32 result = *(UInt32*)(v86.tss.ss * 16 + v86.tss.esp);
v86.tss.esp = (UInt16)(v86.tss.esp + 4);
return result;
}
void callV86(UInt16 segment, UInt16 offset)
{
int o32 = 0, a32 = 0;
UInt32 err;
v86.tss.cs = segment;
v86.tss.eip = offset;
v86.tss.eflags = (v86.tss.eflags & EFLAGS_REAL) | EFLAGS_VM;
disablePreemption(currentTask); // disallow multitasking for the moment
setTaskHandler(0x0D, currentTask->selector, 0); // this task is GPF handler
ljmp(v86selector); // switch to V86 task
err = pop(); // pop GPF error code
for (;;)
{
UInt8 *ip = (UInt8*)(v86.tss.cs * 16 + v86.tss.eip);
switch ( *ip )
{
case 0x66: // O32
o32 = 1;
v86.tss.eip = (UInt16)(v86.tss.eip + 1);
continue;
case 0x67: // A32
a32 = 1;
v86.tss.eip = (UInt16)(v86.tss.eip + 1);
continue;
case 0x9C: // PUSHF
if ( o32 )
v86push32(v86.tss.eflags);
else
v86push16(v86.tss.eflags);
v86.tss.eip = (UInt16)(v86.tss.eip + 1);
break;
case 0x9D: // POPF
if ( o32 )
v86.tss.eflags = (v86pop32() & EFLAGS_REAL) | EFLAGS_VM;
else
v86.tss.eflags = (v86pop16() & EFLAGS_REAL) | EFLAGS_VM;
v86.tss.eip = (UInt16)(v86.tss.eip + 1);
break;
case 0xCC: // INT 3
case 0xCD: // INT x
v86push16(v86.tss.eflags);
v86push16(v86.tss.cs);
v86push16(v86.tss.eip + (ip[0] - 0xCB));
v86.tss.eip = *(UInt16*)(ip[0] == 0xCC ? 12 : ip[1] * 4);
v86.tss.cs = *(UInt16*)(ip[0] == 0xCC ? 14 : ip[1] * 4 + 2);
v86.tss.eflags &= ~(EFLAGS_IF | EFLAGS_TF);
break;
case 0xCF: // IRET
v86.tss.eip = v86pop16();
v86.tss.cs = v86pop16();
v86.tss.eflags = (v86pop16() & EFLAGS_REAL) | EFLAGS_VM;
break;
default:
kprintf("V86 unknown opcode: %02X (err=%04X)\n", *ip, (UInt16)err);
dumpTSS(&v86.tss);
// The ability in C to fall through into the next case is an
// outstanding feature of the language, not a design flaw.
case 0xF4: // HLT
setEFLAGS(getEFLAGS() & ~EFLAGS_NT); // clear Nested Task flag
resetTaskSelector(v86selector); // clear busy bit on V86 task
setIntHandler(0x0D, handler0D); // reset standard GPF handler
enablePreemption(currentTask); // reenable multitasking
return; // ...and I am outta here...
case 0xFA: // CLI
v86.tss.eflags &= ~EFLAGS_IF;
v86.tss.eip = (UInt16)(v86.tss.eip + 1);
break;
case 0xFB: // STI
v86.tss.eflags |= EFLAGS_IF;
v86.tss.eip = (UInt16)(v86.tss.eip + 1);
break;
}
iret(); // return to V86 task
err = pop(); // pop GPF error code off stack
o32 = a32 = 0;
}
}
Re:Interrupt Vector Table Question
Finally, I still have a question why it is nesscary for us to define a IDT, why we couldn't continue use the IVT in Pmode.
Re:Interrupt Vector Table Question
Because the addresses aren't correct then anymore.....chen17981 wrote: Finally, I still have a question why it is nesscary for us to define a IDT, why we couldn't continue use the IVT in Pmode.
An IVT is meant for the real mode, not for the protected mode.......
Re:Interrupt Vector Table Question
Indeed, even if the routines in question were smart enough to handle being called from either mode, the IVT itself is too small to hold the information necessary to tell the processor what to do in order to call them. Because of its segmented architecture, 32-bit were required to specify the location of interrupt handling routines on the 16-bit 8086. On the 32-bit 80386 and later, when operating in 32-bit mode, a bare minimum of 48-bits are required (16 bit segment, but now 32 bits for the offset). Plus, to support protected mode, more information (such as privilige level) and thus even more bits are required. The IVT is simply too small to handle interrupts in protected mode, even in principle. An IDT must be created, and looking at it's structure, it's hard to imagine how a structure any smaller than that could contain the information necessary to tell the processor what to do when an interrupt occurs. There was simply no way to cram that kind of information into the IVT in a backwards compatible way -- a new structure had to be defined.