General Questions about basic kernel code
Posted: Thu Apr 28, 2011 10:09 am
So I made a basic OS with a GDT and an IDT and I understand almost everything but I have a few questions.
First of all, this assembly function is called whenever there is an IRQ,
First of all, the function irq_handler has an argument struct regs *r which is
How does the function get the argument data from the stack? Does it do it automatically when its called, taking all all the data that it requires?
Also, in this code irq_handler is moved to eax before being called. What's the difference between this and just calling irq_handler directly?
To setup each IRQ in the table, the following function is called idt_set_gate(32, (unsigned)irq0, 0x08, 0x8E); The function is defined as,
So the selector points to the IRQ, right? So setting the selector to 0x08 just points it to the code segment. How does this point t to the interrupt function?
Finally, in the following code,
I'm confused on the purpose of the jmp 0x08:flush2 line. The purpose of this function is to point the correct registers to the GDT entries right? So I see how jumping to 0x08 points to the code segment but how does calling flush right after that set the CS to that value?
First of all, this assembly function is called whenever there is an IRQ,
Code: Select all
irq_common_stub:
pusha
push ds
push es
push fs
push gs
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov eax, esp
push eax
mov eax, irq_handler
call eax
pop eax
pop gs
pop fs
pop es
pop ds
popa
add esp, 8
iret
Code: Select all
struct regs
{
unsigned int gs, fs, es, ds; /* pushed the segs last */
unsigned int edi, esi, ebp, esp, ebx, edx, ecx, eax; /* pushed by 'pusha' */
unsigned int int_no, err_code; /* our 'push byte #' and ecodes do this */
unsigned int eip, cs, eflags, useresp, ss; /* pushed by the processor automatically */
};
Also, in this code irq_handler is moved to eax before being called. What's the difference between this and just calling irq_handler directly?
To setup each IRQ in the table, the following function is called idt_set_gate(32, (unsigned)irq0, 0x08, 0x8E); The function is defined as,
Code: Select all
void idt_set_gate(unsigned char num, unsigned long base, unsigned short sel, unsigned char flags) // Sets an IDT entry
{
idt[num].base_lo = (base & 0xFFFF); // Sets first 16 bits of base address
idt[num].base_hi = (base >> 16) & 0xFFFF; // Sets last 16 bits of base address
idt[num].sel = sel; // Sets selector
idt[num].always0 = 0; // This value is always 0
idt[num].flags = flags; // Sets flags
}
Finally, in the following code,
Code: Select all
global gdt_flush ; Allows the C code to link to this
extern gp ; Says that 'gp' is in another file
gdt_flush:
lgdt [gp] ; Load the GDT with our '_gp' which is a special pointer
mov ax, 0x10 ; 0x10 is the offset in the GDT to our data segment
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
jmp 0x08:flush2 ; 0x08 is the offset to our code segment (because he GDT starts with a NULL descriptor): Far jump!
flush2:
ret ; Returns back to the C code!