as the title says as soon as there is an interrupt my function is called and works fine, but then qemu crashes:
Code: Select all
qemu: fatal: Trying to execute code outside RAM or ROM at 0x000a0000
EAX=00000f02 EBX=00002a00 ECX=00100482 EDX=00000000
ESI=00000000 EDI=00103fff EBP=00000000 ESP=001025e0
EIP=0009fff0 EFL=00000202 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT= 000caa68 00000027
IDT= 001025e0 00000800
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
DR6=ffff0ff0 DR7=00000400
CCS=00000f02 CCD=00000f0b CCO=ADDB
EFER=0000000000000000
FCW=037f FSW=0000 [ST=0] FTW=00 MXCSR=00001f80
FPR0=0000000000000000 0000 FPR1=0000000000000000 0000
FPR2=0000000000000000 0000 FPR3=0000000000000000 0000
FPR4=0000000000000000 0000 FPR5=0000000000000000 0000
FPR6=0000000000000000 0000 FPR7=0000000000000000 0000
XMM00=00000000000000000000000000000000 XMM01=00000000000000000000000000000000
XMM02=00000000000000000000000000000000 XMM03=00000000000000000000000000000000
XMM04=00000000000000000000000000000000 XMM05=00000000000000000000000000000000
XMM06=00000000000000000000000000000000 XMM07=00000000000000000000000000000000
Assembler code:
Code: Select all
bits 32
section .text
;multiboot spec
align 4
dd 0x1BADB002
dd 0x00
dd - (0x1BADB002 + 0x00)
global start
global inb
global outb
global load_idt
global interrupt_handle
extern kmain
extern cihandle
start:
cli
mov esp, stack_space
call kmain
hlt
inb:
mov edx, [esp + 4]
in al, dx
ret
outb:
mov edx, [esp + 4]
mov al, [esp + 4 + 4]
out dx, al
ret
load_idt:
mov edx, [esp + 4]
lidt [edx]
sti
ret
interrupt_handle:
call cihandle
iretd ;if I change this to ret the kernel continues to run, but doesn't catch any more interrupts
section .bss
resb 8192
stack_space:
Code: Select all
#define COM1 0x3f8
#define PITM 0x43
#define PIT0 0x40
#define IDT_SIZE 256
extern char inb(unsigned short port);
extern void outb(unsigned short port, unsigned char data);
extern void load_idt(unsigned long *idt_ptr);
extern void interrupt_handle(void);
struct IDT_entry {
unsigned short int offset_lowerbits;
unsigned short int selector;
unsigned char zero;
unsigned char type_attr;
unsigned short int offset_higherbits;
};
struct IDT_entry IDT[IDT_SIZE];
char* itoa(int i, int base){
char const digit[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char* p;
if(i<0){
*p++ = '-';
i *= -1;
}
int shifter = i;
do{ //Move to where representation ends
++p;
shifter = shifter/base;
}while(shifter);
*p = '\0';
do{ //Move back, inserting digits as u go
*--p = digit[i%base];
i = i/base;
}while(i);
return p;
}
int is_transmit_empty(unsigned short port) {
return inb(port + 5) & 0x20;
}
void write_serial(char a, unsigned short port) {
while (is_transmit_empty(port) == 0);
outb(port,a);
}
void write_mul(char *a, unsigned short port) {
unsigned int j = 0;
while(a[j] != '\0') {
write_serial(a[j], port);
++j;
}
}
void init_serial(unsigned short port) {
outb(port + 1, 0x00); // Disable all interrupts
outb(port + 3, 0x80); // Enable DLAB (set baud rate divisor)
outb(port + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud
outb(port + 1, 0x00); // (hi byte)
outb(port + 3, 0x03); // 8 bits, no parity, one stop bit
outb(port + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
outb(port + 4, 0x0B); // IRQs enabled, RTS/DSR set
}
void print(char *str) {
int i = 0;
int j = 0;
char *vidptr = (char*)0xb8000;
while (str[i] != '\0') {
vidptr[j] = str[i];
j = j + 2;
++i;
}
}
int initirq() {
unsigned long interrupt_address = (unsigned long) interrupt_handle;
unsigned long idt_address;
unsigned long idt_ptr[2];
IDT[0x21].offset_lowerbits = interrupt_address & 0xFFFF;
IDT[0x21].selector = 0x08;
IDT[0x21].zero = 0;
IDT[0x21].type_attr = 0x8e;
IDT[0x21].offset_higherbits = (interrupt_address & 0xFFFF0000) >> 16;
/* ICW1 - begin initialization */
outb(0x20 , 0x11);
outb(0xA0 , 0x11);
/* ICW2 - remap offset address of IDT */
/*
* In x86 protected mode, we have to remap the PICs beyond 0x20 because
* Intel have designated the first 32 interrupts as "reserved" for cpu exceptions
*/
outb(0x21 , 0x20);
outb(0xA1 , 0x28);
/* ICW3 - setup cascading */
outb(0x21 , 0x00);
outb(0xA1 , 0x00);
/* ICW4 - environment info */
outb(0x21 , 0x01);
outb(0xA1 , 0x01);
/* Initialization finished */
outb(0x21, 0xFD);
outb(0xA1, 0xFF);
idt_address = (unsigned long)IDT;
idt_ptr[0] = sizeof (struct IDT_entry) * IDT_SIZE + ((idt_address & 0xFFFFF) << 16);
idt_ptr[1] = idt_address >> 16;
load_idt(idt_ptr);
}
void cihandle(void) {
outb(0x20, 0x20);
outb(COM1, 'A');
return;
}
void kmain(void)
{
init_serial(COM1);
init_serial(PITM);
init_serial(PIT0);
write_serial(0x00, PITM);
initirq();
write_mul("Hello World!", COM1);
char *str = "hello kernel!";
/* video memory begins at address 0xb8000 */
char *vidptr = (char*)0xb8000;
unsigned int i = 0;
unsigned int j = 0;
unsigned int screensize;
/* this loops clears the screen
* there are 25 lines each of 80 columns; each element takes 2 bytes */
screensize = 80 * 25 * 2;
while (j < screensize) {
vidptr[j] = ' ';
vidptr[j+1] = 0x0F;
j = j + 2;
}
/*
j = 0;
str = itoa(0xAA, 16);
while (str[i] != '\0') {
vidptr[j] = str[i];
j = j + 2;
++i;
}*/
}
Luca