我试图从头开始编写一个没有任何库和东西的操作系统。因此,我设置了IDT和其他东西,最后完成了它。因此,当我尝试它时,它一直在重新启动。我只写了int 0x0,所以我写了前16个以处理我至少会看到的异常。所以我要做的就是设置一个set_background函数,并给每个异常一个从0到15的异常颜色,我给了20到2f的颜色(我在13h模式下:320x200p 256色)当我运行OS时,我发现我的异常是带有2d颜色代码的代码。这是位于13的通用保护错误。我知道抛出通用保护错误时,它指向通过eip的指令。因此,我使用了仿真器控制台(qemu监视器)来获取引发异常的指令的值。我猜它与我的fill_rect函数的地址相对应,但是我不确定我什至找不到。
内核如下
#include "OS.h"
int kmain()
{
init_idt();
//asm("int $0x0");
while(1);
}
我没有写太多内核代码,因为我不需要
OS.h文件如下
#include "IO.h"
#include "screen.h"
#ifndef __TARAOS_H
#define __TARAOS_H
#define NULL 0
//TODO: Add more keys
unsigned char MapScancodeToAscii(unsigned Scancode)
{
unsigned char ScancodeTabel[] = {
'\0',
'\0', //
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'0',
'-',
'=',
' ',
'q',
'w',
'e',
'r',
't',
'y',
'u',
'i',
'o',
'p',
'[',
']',
'\n',
'a',
's',
'd',
'f',
'g',
'h',
'j',
'k',
'l',
',',
'\\',
'`',
'z',
'x',
'c',
'v',
'b',
'n',
'm',
',',
'.',
'/',
' '
};
unsigned char ret = ScancodeTabel[Scancode];
if(ret == 0) {/* TODO: ADD ERROR - HANDLE CODE */}
return ret;
}
//Video
//Definitions of Video constants
#define __VIDMEM__ 0xA000
#define __DEFAULT_WOB__ 0x0f
//Keyboard
//Definition of Keyboard Driver constants
#define __STATUS_PORT__ 0x64
#define __DATA_PORT__ 0x60
void* memset(void* ptr, int value, int num)
{
unsigned char* ptr_byte = (unsigned char*)ptr;
for (int i = 0; i < num; ptr_byte[i] = (unsigned char)value, i++);
return ptr;
}
int strlen(char *s)
{
char *p = s;
while (*p != '\0')
++p;
return p - s;
}
int strcmp(char string1[], char string2[] )
{
for (int i = 0; ; i++)
{
if (string1[i] != string2[i])
{
return string1[i] < string2[i] ? -1 : 1;
}
if (string1[i] == '\0')
{
return 0;
}
}
}
void set_background(unsigned char* screen,int color)
{
unsigned char* vm = screen;
fill_rect((int)vm,0,320,0,200,color);
}
//IDT///////////////////////////////////////////
struct idt
{
short limit;
unsigned int base;
}__attribute__ ((packed));
struct idt_entry
{
short base_low;
short select;
char always0;
char flags;
short base_high;
}__attribute__ ((packed));
struct idt Tidt;
struct idt_entry _idt_entries[256];
#define IDTBASE 0x00000000
#define IDTSIZE 0xFF
void init_idt_entry(int num, unsigned int offset, unsigned short select,
unsigned short flags)
{
_idt_entries[num].base_low = (offset & 0xffff);
_idt_entries[num].base_high = (offset & 0xffff0000) >> 16;
_idt_entries[num].always0 = 0;
_idt_entries[num].flags = flags;
_idt_entries[num].select = select;
return;
}
void isr_common_handler()
{
asm(".intel_syntax noprefix;"
"sti;"
"iret;"
".att_syntax prefix;"
);
}
void isr0()
{
asm(".intel_syntax noprefix;"
""
"cli;"
".att_syntax prefix;"
);
set_background((unsigned char*)0xA0000, 0x20);
isr_common_handler();
}
void isr1()
{
asm(".intel_syntax noprefix;"
"cli;"
".att_syntax prefix;"
);
set_background((unsigned char*)0xA0000, 0x21);
isr_common_handler();
}
void isr2()
{
asm(".intel_syntax noprefix;"
"cli;"
".att_syntax prefix;"
);
set_background((unsigned char*)0xA0000, 0x22);
isr_common_handler();
}
void isr3()
{
asm(".intel_syntax noprefix;"
"cli;"
".att_syntax prefix;"
);
set_background((unsigned char*)0xA0000, 0x23);
isr_common_handler();
}
void isr4()
{
asm(".intel_syntax noprefix;"
"cli;"
".att_syntax prefix;"
);
set_background((unsigned char*)0xA0000, 0x24);
isr_common_handler();
}
void isr5()
{
asm(".intel_syntax noprefix;"
"cli;"
".att_syntax prefix;"
);
set_background((unsigned char*)0xA0000, 0x25);
isr_common_handler();
}
void isr6()
{
asm(".intel_syntax noprefix;"
"cli;"
".att_syntax prefix;"
);
set_background((unsigned char*)0xA0000, 0x26);
isr_common_handler();
}
void isr7()
{
asm(".intel_syntax noprefix;"
"cli;"
".att_syntax prefix;"
);
set_background((unsigned char*)0xA0000, 0x27);
isr_common_handler();
}
void isr8()
{
asm(".intel_syntax noprefix;"
"cli;"
".att_syntax prefix;"
);
set_background((unsigned char*)0xA0000, 0x28);
isr_common_handler();
}
void isr9()
{
asm(".intel_syntax noprefix;"
"cli;"
".att_syntax prefix;"
);
set_background((unsigned char*)0xA0000, 0x29);
isr_common_handler();
}
void isr10()
{
asm(".intel_syntax noprefix;"
"cli;"
".att_syntax prefix;"
);
set_background((unsigned char*)0xA0000, 0x2a);
isr_common_handler();
}
void isr11()
{
asm(".intel_syntax noprefix;"
"cli;"
".att_syntax prefix;"
);
set_background((unsigned char*)0xA0000, 0x2b);
isr_common_handler();
}
void isr12()
{
asm(".intel_syntax noprefix;"
"cli;"
".att_syntax prefix;"
);
set_background((unsigned char*)0xA0000, 0x2c);
isr_common_handler();
}
void isr13()
{
asm(".intel_syntax noprefix;"
"cli;"
".att_syntax prefix;"
);
set_background((unsigned char*)0xA0000, 0x2d);
isr_common_handler();
}
void isr14()
{
asm(".intel_syntax noprefix;"
"cli;"
".att_syntax prefix;"
);
set_background((unsigned char*)0xA0000, 0x2e);
isr_common_handler();
}
void isr15()
{
asm(".intel_syntax noprefix;"
"cli;"
".att_syntax prefix;"
);
set_background((unsigned char*)0xA0000, 0x2f);
isr_common_handler();
}
void idt_flush(int offset)
{
asm volatile(
".intel_syntax noprefix;"
"mov eax, [esp+4] ;"
"lidt [eax] ;"
"ret;"
".att_syntax prefix;"
);
}
void init_pic()
{
outb(0x20,0x11);
outb(0xA0,0x11);
outb(0x21, 0x20);
outb(0xA1, 40);
outb(0x21, 0x04);
outb(0xA1, 0x02);
outb(0x21, 0x01);
outb(0xA1, 0x01);
outb(0x21, 0x0);
outb(0xA1, 0x0);
}
void init_idt()
{
init_pic();
Tidt.limit = 8 * 256;
Tidt.base = (int)&_idt_entries;
memset(&_idt_entries, 0, 8*256);
for(int i = 0; i < 256 ; i++){
init_idt_entry(i,(int)&isr0,0x08, 0x8E);
}
init_idt_entry(0,(int)&isr0,0x08, 0x8E);
init_idt_entry(1,(int)&isr1,0x08, 0x8E);
init_idt_entry(2,(int)&isr2,0x08, 0x8E);
init_idt_entry(3,(int)&isr3,0x08, 0x8E);
init_idt_entry(4,(int)&isr4,0x08, 0x8E);
init_idt_entry(5,(int)&isr5,0x08, 0x8E);
init_idt_entry(6,(int)&isr6,0x08, 0x8E);
init_idt_entry(7,(int)&isr7,0x08, 0x8E);
init_idt_entry(8,(int)&isr8,0x08, 0x8E);
init_idt_entry(9,(int)&isr9,0x08, 0x8E);
init_idt_entry(10,(int)&isr10,0x08, 0x8E);
init_idt_entry(11,(int)&isr11,0x08, 0x8E);
init_idt_entry(12,(int)&isr12,0x08, 0x8E);
init_idt_entry(13,(int)&isr13,0x08, 0x8E);
init_idt_entry(14,(int)&isr14,0x08, 0x8E);
init_idt_entry(15,(int)&isr15,0x08, 0x8E);
idt_flush((int)&Tidt);
asm volatile(".intel_syntax noprefix;"
"sti;"
".att_syntax prefix;"
);
}
#endif
我认为会导致故障的fill rect函数包含在screen.h中
#ifndef __SCREEN_H__
#define __SCREEN_H__
void putpixel(unsigned char* screen, int x,int y, int color) {
unsigned char* fb = screen;
unsigned int offset = y * 320 + x;
fb[offset] = color;
}
void draw_line(unsigned char* screen, int fromx, int tox, int y,int color)
{
unsigned char* fb = screen;
unsigned int offset = y * 320 + fromx;
for(int i = 0;i < tox; i++)
{
fb[offset+i] = color;
}
}
void fill_rect(unsigned char* screen, int fromx, int tox, int fromy,int toy,int color)
{
unsigned char* fb = screen;
unsigned int start_offset = fromy * 320 + fromx;
unsigned int end_offset = toy * 320 + tox;
for(int i = fromy; i < toy ; i++ )
{
for(int j = fromx; j < tox ; j++)
{
putpixel(fb,j,i,color);
}
}
}
#endif
我认为fill_Rect函数是导致故障的函数
在地址1170中显示了导致异常的函数83 45 f8 01(我将内核加载到0x1000)
编辑:
其他文件
引导程序:
[ORG 0x7c00]
BITS 16
global _boot_start
_boot_start:
; Yükleyici
cli
mov bx,0x9000
mov bp,bx
mov sp,bx
mov ss,bx
sti
xor ax, ax
mov ds, ax
mov es, ax
mov [bootdev], dl
mov bx, MSG_START ;
call print_string
mov dl, [bootdev]
mov dh, 5
mov cl, 0x02
mov bx, 0x1000
call disk_load
mov bx, MSG_YESNO
call print_string
call get_yes_no
mov bx, MSG_BOOT_KERNEL
call print_string
xor ah,ah
mov al,13h
int 0x10
lgdt [gdt_descriptor]
cli
mov eax , cr0 ; To make the switch to protected mode , we set
or eax , 0x1 ; the first bit of CR0 , a control register
mov cr0 , eax ; Update the control register
jmp CODE_SEG:pm
; Alt fonksiyonlar
;******************************************************************
print_string:
.loop:
mov al,[bx]
cmp al,0
je return
push bx
mov ah,0Eh
int 10h
pop bx
inc bx
jmp .loop
return:
ret
;******************************************************************
get_yes_no:
pusha
.loop:
mov ah, 00h
int 16h
cmp ah, 15h
je .yes
cmp ah, 31h
je .no
jmp .loop
ret
.no:
mov bx, No
call print_string
mov ah, 00h
int 13h
jmp $
.yes:
mov bx, Yes
call print_string
jmp .done
.done:
popa
ret
;******************************************************************
disk_load:
push dx
mov ah, 02h
mov al, dh
mov ch, 0x00
mov dh, 0x00
;mov cl, 0x02
int 0x13
pop dx
jc disk_error
cmp dh, al
jne disk_error_double
mov bx,MSG_LOAD_SUCC
call print_string
ret
disk_error:
mov bx,MSG_LOAD_FAIL
call print_string
jmp $
disk_error_double:
mov bx,MSG_LOAD_FAIL_C
call print_string
jmp $
BITS 32
pm:
mov ax , DATA_SEG ; Now in PM , our old segments are meaningless ,
mov ds , ax
mov ss , ax
mov es , ax
mov fs , ax
mov gs , ax
mov ebp , 0x90000
mov esp , ebp
call KERNEL_OFFSET
jmp $
;******************************************************************
print_string_pm :
pusha
mov edx , VIDEO_MEMORY ; Set edx to the start of vid mem.
.print_string_pm_loop :
mov al , [ ebx ] ; Store the char at EBX in AL
mov ah , WHITE_ON_BLACK ; Store the attributes in AH
cmp al , 0 ; if (al == 0), at end of string , so
je .print_string_pm_done ; jump to done
mov [edx], ax ; Store char and attributes at current
; character cell.
add ebx , 1 ; Increment EBX to the next char in string.
add edx , 2 ; Move to next character cell in vid mem.
jmp .print_string_pm_loop ; loop around to print the next char.
.print_string_pm_done :
popa
ret
; Global Descriptor table
; GDT
gdt_start :
gdt_null : ; the mandatory null descriptor
dd 0x0 ; 'dd ' means define double word ( i.e. 4 bytes )
dd 0x0
gdt_code :
dw 0xffff ; Limit ( bits 0 -15)
dw 0x0 ; Base ( bits 0 -15)
db 0x0 ; Base ( bits 16 -23)
db 10011010b ; 1st flags , type flags
db 11001111b ; 2nd flags , Limit ( bits 16 -19)
db 0x0 ; Base ( bits 24 -31)
gdt_data :
dw 0xffff ; Limit ( bits 0 -15)
dw 0x0 ; Base ( bits 0 -15)
db 0x0 ; Base ( bits 16 -23)
db 10010010b ; 1st flags , type flags
db 11001111b ; 2nd flags , Limit ( bits 16 -19)
db 0x0 ; Base ( bits 24 -31)
gdt_end :
gdt_descriptor :
dw gdt_end - gdt_start - 1
dd gdt_start
CODE_SEG equ gdt_code - gdt_start
DATA_SEG equ gdt_data - gdt_start
; Değişkenler
MSG_START DB ">",13,10,0
MSG_LOAD_SUCC DB "> Succesfully loaded",13,10,0
MSG_LOAD_FAIL DB "> Failed to load Please try to restart the system",13,10,0
MSG_LOAD_FAIL_C DB "> Error while loading",13,10,0
MSG_YESNO DB "> Do you want to boot up in kernel mode Y/N :",0
MSG_BOOT_KERNEL DB 13,10,"> Booting in kernel mode",0
MSG_BOOT_32 DB "32 bit pm",13,10,0
Yes db "Y",0
No db "N",0
bootdev: db 0
KERNEL_OFFSET equ 0x1000
VIDEO_MEMORY equ 0xb8000
WHITE_ON_BLACK equ 0x0f
times 510-($-$$) db 0
dw 0xaa55
IO.h:
#ifndef __IO_H
#define __IO_H
unsigned char inb ( unsigned short port ) {
unsigned char result ;
__asm__ (" in %%dx , %%al " : "=a" ( result ) : "d" ( port ));
return result ;
}
void outb ( unsigned short port , unsigned char data ) {
__asm__ (" out %%al , %%dx " : :"a" ( data ), "d" ( port ));
}
unsigned short inw ( unsigned short port ) {
unsigned short result ;
__asm__ (" in %%dx , %%ax " : "=a" ( result ) : "d" ( port ));
return result ;
}
void outw ( unsigned short port , unsigned short data ) {
__asm__ (" out %%ax , %%dx " : :"a" ( data ), "d" ( port ));
}
#endif
这是我的makefile
OS:
nasm -fbin bootload.asm -o bootload.bin
gcc -ffreestanding -c kernel.c -o kernel.o
nasm kernel_entry.asm -f elf -o k_entry.o
ld -T NUL -o kernel.tmp -Ttext 0x1000 k_entry.o kernel.o
objcopy -O binary -j .text kernel.tmp kernel.bin
copy /b bootload.bin+kernel.bin os-image.bin
qemu-system-i386 -monitor stdio os-image.bin
clean:
del *.o
del *.temp
del *.bin
当我用-v运行它时,它给出了
Using built-in specs.
COLLECT_GCC=gcc
Target: i686-w64-mingw32
Configured with: ../../../src/gcc-8.1.0/configure --host=i686-w64-mingw32 --build=i686-w64-mingw32 --target=i686-w64-mingw32 --prefix=/mingw32 --with-sysroot=/c/mingw810/i686-810-win32-dwarf-rt_v6-rev0/mingw32 --enable-shared --enable-static --disable-multilib --enable-languages=c,c++,fortran,lto --enable-libstdcxx-time=yes --enable-threads=win32 --enable-libgomp --enable-libatomic --enable-lto --enable-graphite --enable-checking=release --enable-fully-dynamic-string --enable-version-specific-runtime-libs --disable-sjlj-exceptions --with-dwarf2 --disable-libstdcxx-pch --disable-libstdcxx-debug --enable-bootstrap --disable-rpath --disable-win32-registry --disable-nls --disable-werror --disable-symvers --with-gnu-as --with-gnu-ld --with-arch=i686 --with-tune=generic --with-libiconv --with-system-zlib --with-gmp=/c/mingw810/prerequisites/i686-w64-mingw32-static --with-mpfr=/c/mingw810/prerequisites/i686-w64-mingw32-static --with-mpc=/c/mingw810/prerequisites/i686-w64-mingw32-static --with-isl=/c/mingw810/prerequisites/i686-w64-mingw32-static --with-pkgversion='i686-win32-dwarf-rev0, Built by MinGW-W64 project' --with-bugurl=https://sourceforge.net/projects/mingw-w64 CFLAGS='-O2 -pipe -fno-ident -I/c/mingw810/i686-810-win32-dwarf-rt_v6-rev0/mingw32/opt/include -I/c/mingw810/prerequisites/i686-zlib-static/include -I/c/mingw810/prerequisites/i686-w64-mingw32-static/include' CXXFLAGS='-O2 -pipe -fno-ident -I/c/mingw810/i686-810-win32-dwarf-rt_v6-rev0/mingw32/opt/include -I/c/mingw810/prerequisites/i686-zlib-static/include -I/c/mingw810/prerequisites/i686-w64-mingw32-static/include' CPPFLAGS=' -I/c/mingw810/i686-810-win32-dwarf-rt_v6-rev0/mingw32/opt/include -I/c/mingw810/prerequisites/i686-zlib-static/include -I/c/mingw810/prerequisites/i686-w64-mingw32-static/include' LDFLAGS='-pipe -fno-ident -L/c/mingw810/i686-810-win32-dwarf-rt_v6-rev0/mingw32/opt/lib -L/c/mingw810/prerequisites/i686-zlib-static/lib -L/c/mingw810/prerequisites/i686-w64-mingw32-static/lib -Wl,--large-address-aware'
Thread model: win32
gcc version 8.1.0 (i686-win32-dwarf-rev0, Built by MinGW-W64 project)
COLLECT_GCC_OPTIONS='-v' '-Os' '-fno-PIC' '-m32' '-ffreestanding' '-c' '-o' 'kernel.o' '-mtune=generic' '-march=i686'
D:/MinGw1/mingw32/bin/../libexec/gcc/i686-w64-mingw32/8.1.0/cc1.exe -quiet -v -iprefix D:/MinGw1/mingw32/bin/../lib/gcc/i686-w64-mingw32/8.1.0/ -U_REENTRANT kernel.c -quiet -dumpbase kernel.c -m32 -mtune=generic -march=i686 -auxbase-strip kernel.o -Os -version -fno-PIC -ffreestanding -o C:\Users\Z2123~1\AppData\Local\Temp\cc2jKvGE.s
GNU C17 (i686-win32-dwarf-rev0, Built by MinGW-W64 project) version 8.1.0 (i686-w64-mingw32)
compiled by GNU C version 8.1.0, GMP version 6.1.2, MPFR version 4.0.1, MPC version 1.1.0, isl version isl-0.18-GMP
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
ignoring duplicate directory "D:/MinGw1/mingw32/lib/gcc/../../lib/gcc/i686-w64-mingw32/8.1.0/include"
ignoring nonexistent directory "C:/mingw810/i686-810-win32-dwarf-rt_v6-rev0/mingw32C:/msys64/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/../../../../include"
ignoring duplicate directory "D:/MinGw1/mingw32/lib/gcc/../../lib/gcc/i686-w64-mingw32/8.1.0/include-fixed"
ignoring duplicate directory "D:/MinGw1/mingw32/lib/gcc/../../lib/gcc/i686-w64-mingw32/8.1.0/../../../../i686-w64-mingw32/include"
ignoring nonexistent directory "C:/mingw810/i686-810-win32-dwarf-rt_v6-rev0/mingw32/mingw/include"
#include "..." search starts here:
#include <...> search starts here:
D:/MinGw1/mingw32/bin/../lib/gcc/i686-w64-mingw32/8.1.0/include
D:/MinGw1/mingw32/bin/../lib/gcc/i686-w64-mingw32/8.1.0/include-fixed
D:/MinGw1/mingw32/bin/../lib/gcc/i686-w64-mingw32/8.1.0/../../../../i686-w64-mingw32/include
End of search list.
GNU C17 (i686-win32-dwarf-rev0, Built by MinGW-W64 project) version 8.1.0 (i686-w64-mingw32)
compiled by GNU C version 8.1.0, GMP version 6.1.2, MPFR version 4.0.1, MPC version 1.1.0, isl version isl-0.18-GMP
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: 283040c7d21de7e7c3c642876453fb1b
In file included from kernel.c:1:
TaraOS.h: In function 'MapScancodeToAscii':
TaraOS.h:28:13: warning: multi-character character constant [-Wmultichar]
' ',
^~~~~
TaraOS.h:28:13: warning: unsigned conversion from 'int' to 'unsigned char' changes value from '2105376' to '32' [-Woverflow]
TaraOS.h: In function 'set_background':
TaraOS.h:121:19: warning: passing argument 1 of 'fill_rect' makes pointer from integer without a cast [-Wint-conversion]
fill_rect((int)vm,0,320,0,200,color);
^~~~~~~
In file included from TaraOS.h:5,
from kernel.c:1:
screen.h:22:35: note: expected 'unsigned char *' but argument is of type 'int'
void fill_rect(unsigned char* screen, int fromx, int tox, int fromy,int toy,int color)
~~~~~~~~~~~~~~~^~~~~~
COLLECT_GCC_OPTIONS='-v' '-Os' '-fno-PIC' '-m32' '-ffreestanding' '-c' '-o' 'kernel.o' '-mtune=generic' '-march=i686'
D:/MinGw1/mingw32/bin/../lib/gcc/i686-w64-mingw32/8.1.0/../../../../i686-w64-mingw32/bin/as.exe -v --32 -o kernel.o C:\Users\Z2123~1\AppData\Local\Temp\cc2jKvGE.s
GNU assembler version 2.30 (i686-w64-mingw32) using BFD version (GNU Binutils) 2.30
,然后再次输入相同的错误代码