还是效果图了,程序的结构很糟糕了,大家还是凑合着看吧!这个程序至少有两处BUG,不过好在我要求不高,现在能运行就行了。说是C语言,其实一些关键的地方或者说是不会用C的地方,还是不得不使用了汇编语言。
百度网盘下载地址:
https://pan.baidu.com/s/1_-IznMWL3z1CROziiD6mCw
#Makefile
CC=gcc
AS=as
LD=ld
OBJ = boot.o kernel.o
all: kernel
.S.o:
$(AS) -o $@ $<
.c.o:
$(CC) -c -o $@ $<
kernel: $(OBJ)
$(LD) -Ttext 0x100000 -o $@ $^
default:
make all
objcopy -I pe-i386 -O elf32-i386 kernel
winimage ..\mybochs\andows.img kernel /i /h /y
run:
make default
bochs -q -f ..\mybochs\bochsrc.bxrc
clean:
del boot.o
del kernel.o
del kernel
del ..\mybochs\*.lock
del bochsout.txt
#boot.S
MULTIBOOT2_HEADER_MAGIC = 0xe85250d6
GRUB_MULTIBOOT_ARCHITECTURE_I386 = 0x0
MULTIBOOT_HEADER_TAG_ADDRESS = 0x2
MULTIBOOT_HEADER_TAG_OPTIONAL = 0x1
MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS = 0x3
MULTIBOOT_HEADER_TAG_END = 0x0
MULTIBOOT_HEADER_TAG_FRAMEBUFFER = 0x5
.globl _start
_start:
#跳转到程序的入口
jmp multiboot_entry
#8字节对齐
.align 8
multiboot_header:
#引导头的魔数0xe85250d6
.int MULTIBOOT2_HEADER_MAGIC
#0是32保护模式i386
.int GRUB_MULTIBOOT_ARCHITECTURE_I386
#引导头的字节长度
.int multiboot_header_end - multiboot_header
#校验码
.int -(MULTIBOOT2_HEADER_MAGIC + GRUB_MULTIBOOT_ARCHITECTURE_I386 + (multiboot_header_end - multiboot_header))
.align 8
#应该叫做引导头的地址域(这或许不是必须存在的域)
address_tag_start:
.short MULTIBOOT_HEADER_TAG_ADDRESS
.short MULTIBOOT_HEADER_TAG_OPTIONAL
.int address_tag_end - address_tag_start
.int multiboot_header
.int _start
.int 0x0
.int 0x0
address_tag_end:
.align 8
#应该叫做引导头入口的地址域(这或许不是必须存在的域)
entry_address_tag_start:
.short MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS
.short MULTIBOOT_HEADER_TAG_OPTIONAL
.int entry_address_tag_end - entry_address_tag_start
.int multiboot_entry
entry_address_tag_end:
.align 8
#帧缓冲的域(这或许不是必须存在的域,由这里可以进入预制的图形模式)
//framebuffer_tag_start:
// .short MULTIBOOT_HEADER_TAG_FRAMEBUFFER
// .short MULTIBOOT_HEADER_TAG_OPTIONAL
// .int framebuffer_tag_end - framebuffer_tag_start
// .int 800
// .int 600
// .int 16
//framebuffer_tag_end:
.align 8
#这个域在示例程序中未注明,所以我定义成了未定义的域。
undefined_tag:
.short MULTIBOOT_HEADER_TAG_END
.short 0
.int 8
multiboot_header_end:
.align 8
#上面是能被grub2引导的符合multiboot标准的ELF格式文件。
#接下来即是我们的汇编代码,从这里我们可以调用C语言程序,
#从而摆脱汇编的束缚,当然也可以在这段代码之后定义无数的有用的汇编例程,
#供我们今后在C语言中调用,当然我们的原则是无法用C语言完成的,
#才会定义在这段代码之后。
multiboot_entry:
#关闭中断、初始化堆栈指针、清标志寄存器。
cli
movl $stack, %esp
pushl $0
popf
#为调用的C语言函数准备两个参数。
pushl %ebx
pushl %eax
call _cmain
addl $8, %esp
1:
hlt
jmp 1b
SYS_CS = 1 * 8
SYS_DS = 2 * 8
VIDEO = 4 * 8
.global _myjmp
_myjmp: #void myjmp(void);
ljmp $SYS_CS, $_newstart
_newstart:
movw $SYS_DS, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %ss
movw $VIDEO, %ax
movw %ax, %gs
ret
.globl _divide_error
.extern _do_divide_error
_divide_error: #void divide_error(void);
pushl $_do_divide_error
no_error_code:
xchgl %eax, (%esp)
pushl %ecx
pushl %edx
pushl %ebx
pushl %esi
pushl %edi
pushl %ebp
push %ds
push %es
push %fs
pushl $0
lea (11 * 4)(%esp), %edx
pushl %edx
movl $(2 * 8), %edx
movw %dx, %ds
movw %dx, %es
movw %dx, %fs
call *%eax
addl $(2 * 4), %esp
# addl $2, (10 * 4)(%esp) 仔细思考这里偏移量为什么是(10 * 4)
pop %fs
pop %es
pop %ds
popl %ebp
popl %edi
popl %esi
popl %ebx
popl %edx
popl %ecx
popl %eax
iret
.globl _general_protection
.extern _do_general_protection #void do_general_protection(long esp, long error_code);
_general_protection: #void general_protection(void);
pushl $_do_general_protection
error_code:
xchgl %eax, 4(%esp)
xchgl %ebx, (%esp)
pushl %ecx
pushl %edx
pushl %edi
pushl %esi
pushl %ebp
push %ds
push %es
push %fs
pushl %eax
lea 44(%esp), %eax
pushl %eax
movl $(2 * 8), %eax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
call *%ebx
addl $8, %esp
pop %fs
pop %es
pop %ds
popl %ebp
popl %esi
popl %edi
popl %edx
popl %ecx
popl %ebx
popl %eax
iret
tmp:
.int 0
tmp1:
.int 0
.globl _timer_interrupt
.extern _do_timer, _signal _current, _mycurrent, _sig, _tss_table, _myt
_timer_interrupt: #void timer_interrupt(void);
pushal
push %ds
push %es
push %fs
movw $(2 * 8), %ax
movw %ax, %ds
call _do_timer
movl (_mycurrent), %ebx
movl (_current), %eax
cmpl %ebx, %eax
je 1f
movl %eax, (tmp1)
ljmp *(tmp)
1:
movl $_tss_table + 4, %eax
cmpl $0, _sig
jne 2f
movl $0, (%eax)
2:
cmpl $1, _sig
jne 3f
movl _myt, %ecx
movl %ecx, (%eax)
3:
pop %fs
pop %es
pop %ds
popal
iret
.globl _key_interrupt
.extern _do_key
_key_interrupt: #void key_interrupt(void);
pushal
push %ds
push %es
push %fs
movw $(2 * 8), %ax
movw %ax, %ds
call _do_key
pop %fs
pop %es
pop %ds
popal
iret
.globl _sys_call
.extern _do_sys_call
_sys_call: #void sys_call(void);
pushal
push %ds
push %es
push %fs
movw $(2 * 8), %dx
movw %dx, %ds
pushl %eax
call _do_sys_call
addl $(1 * 4), %esp
pop %fs
pop %es
pop %ds
popal
iret
.globl _enable_timer_key
_enable_timer_key: #void enable_timer_key(void);
movw $0x21, %dx
inb %dx, %al
andb $0xfc, %al
outb %al, %dx
ret
.globl _go_ring3
.extern _func0, _f0_u_s
_go_ring3: #void go_ring3(void);
pushfl
andl $0xffffbfff, (%esp)
popfl
movw $(5 * 8), %ax
ltr %ax
movw $(6 * 8), %ax
lldt %ax
# movw $(2 * 8 + 7), %ax
# movw %ax, %ds
sti
pushl $(2 * 8 + 7)
pushl %esp
pushfl
pushl $(1 * 8 + 7)
pushl $(_func0)
iret
#对齐4k边界
.align 0x1000
#预留16k空间
.fill 0x4000, 1, 0
#栈顶
stack:
//kernel.c
#define switch_to(tss_sel) ({ \
struct {long a, b;} __tmp; \
__asm__("movw %%ax, %1\n\t" \
"movl $0, %0\n\t" \
"ljmp *%0" \
::"m"(*&__tmp.a),"m"(*&__tmp.b), \
"a"(tss_sel)); \
})
typedef struct descriptor {
short limit_low;
short base_low;
char base_mid;
char access_right;
char limit_high;
char base_high;
}descriptor, *Descriptor;
typedef struct gate {
short offset_low;
short selector;
char dw_count;
char access_right;
short offset_high;
}gate, *Gate;
void set_descriptor(Descriptor sd, unsigned int limit, int base, int attrib) {
if(limit > 0xfffff) {
attrib |= 0x8000;
limit /= 0x1000;
}
sd->limit_low = limit & 0xffff;
sd->base_low = base & 0xffff;
sd->base_mid = (base >> 16) & 0xff;
sd->access_right = attrib & 0xff;
sd->limit_high = ((limit >> 16) & 0x0f) | ((attrib >> 8) & 0xf0);
sd->base_high = (base >> 24) & 0xff;
return;
}
void set_gate(Gate gd, int offset, int selector, int attrib) {
gd->offset_low = offset & 0xffff;
gd->selector = selector;
gd->dw_count = (attrib >> 8) & 0xff;
gd->access_right = attrib & 0xff;
gd->offset_high = (offset >> 16) & 0xffff;
return;
}
typedef struct desc_struct {
unsigned char ch[8];
}desc, *Desc;
typedef struct tss {
int backlink;
int esp0;
int ss0;
int esp1;
int ss1;
int esp2;
int ss2;
int cr3;
int eip;
int eflags;
int eax;
int ecx;
int edx;
int ebx;
int esp;
int ebp;
int esi;
int edi;
int es;
int cs;
int ss;
int ds;
int fs;
int gs;
int ldt_sel;
int trace_bitmap;
}tss, *Tss;
typedef struct ldt_tss_struct {
desc myldt[6];
tss mytss;
}ldt_tss, *Ldt_tss;
typedef union task_struct {
ldt_tss myldt_tss;
unsigned char ch[512];
}task, *Task;
task mytask[3];
Tss tss_table[3] = {&(mytask[0].myldt_tss.mytss),
&(mytask[1].myldt_tss.mytss),
&(mytask[2].myldt_tss.mytss)};
Tss myt = &(mytask[1].myldt_tss.mytss);
unsigned int current = 5 * 8 + 7;
void enable_timer_key(void);
#define move_to_user_mode() \
__asm__ ("movl %%esp,%%eax\n\t" \
"pushl $0x17\n\t" \
"pushl %%eax\n\t" \
"pushfl\n\t" \
"pushl $0x0f\n\t" \
"pushl $1f\n\t" \
"iret\n" \
"1:\tmovl $0x17,%%eax\n\t" \
"mov %%ax,%%ds\n\t" \
"mov %%ax,%%es\n\t" \
"mov %%ax,%%fs\n\t" \
"mov %%ax,%%gs" \
::)
#define sti() __asm__ ("sti"::)
#define cli() __asm__ ("cli"::)
#define nop() __asm__ ("nop"::)
#define iret() __asm__ ("iret"::)
#define _set_gate(gate_addr,type,dpl,addr) \
__asm__ ("movw %%dx,%%ax\n\t" \
"movw %0,%%dx\n\t" \
"movl %%eax,%1\n\t" \
"movl %%edx,%2" \
: \
: "i" ((short) (0x8000+(dpl<<13)+(type<<8))), \
"o" (*((char *) (gate_addr))), \
"o" (*(4+(char *) (gate_addr))), \
"d" ((char *) (addr)),"a" (0x00080000))
struct desc_struct *idt = (struct desc_struct *) 0;
#define set_intr_gate(n,addr) \
_set_gate(&idt[n],14,0,addr)
#define set_trap_gate(n,addr) \
_set_gate(&idt[n],15,0,addr)
#define set_system_gate(n,addr) \
_set_gate(&idt[n],15,3,addr)
#define _set_seg_desc(gate_addr,type,dpl,base,limit) {\
*((gate_addr)+1) = ((base) & 0xff000000) | \
(((base) & 0x00ff0000)>>16) | \
((limit) & 0xf0000) | \
((dpl)<<13) | \
(0x00408000) | \
((type)<<8); \
*(gate_addr) = (((base) & 0x0000ffff)<<16) | \
((limit) & 0x0ffff); }
#define _set_tssldt_desc(n,addr,type) \
__asm__ ("movw $104,%1\n\t" \
"movw %%ax,%2\n\t" \
"rorl $16,%%eax\n\t" \
"movb %%al,%3\n\t" \
"movb $" type ",%4\n\t" \
"movb $0x00,%5\n\t" \
"movb %%ah,%6\n\t" \
"rorl $16,%%eax" \
::"a" (addr), "m" (*(n)), "m" (*(n+2)), "m" (*(n+4)), \
"m" (*(n+5)), "m" (*(n+6)), "m" (*(n+7)) \
)
#define set_tss_desc(n,addr) _set_tssldt_desc(((char *) (n)),addr,"0x89")
#define set_ldt_desc(n,addr) _set_tssldt_desc(((char *) (n)),addr,"0x82")
#define _lgdt(gdtr) \
__asm__( \
"movw %0, %%ax;" \
"movw %%ax, %1;" \
"lgdt (%2)" \
::"m"(*(gdtr)),"m"(*(gdtr + 2)),"b"(gdtr + 2) \
)
#define _lidt(idtr) \
__asm__( \
"movw %0, %%ax;" \
"movw %%ax, %1;" \
"lidt (%2)" \
::"m"(*(idtr)),"m"(*(idtr + 2)),"b"(idtr + 2) \
)
#define _sgdt(gdtr) \
__asm__( \
"sgdt (%2);" \
"movw %1, %%ax;" \
"movw %%ax, %0" \
::"m"(*(gdtr)),"m"(*(gdtr + 2)),"b"(gdtr + 2) \
)
#define _init_8259() ({ \
__asm__(" \
mov $0x11, %%al; \
out %%al, $0x20; \
out %%al, $0xa0; \
mov $0x20, %%al; \
out %%al, $0x21; \
mov $0x28, %%al; \
out %%al, $0xa1; \
mov $0x04, %%al; \
out %%al, $0x21; \
mov $0x02, %%al; \
out %%al, $0xa1; \
mov $0x01, %%al; \
out %%al, $0x21; \
out %%al, $0xa1; \
mov $0xff, %%al; \
out %%al, $0x21; \
out %%al, $0xa1" \
::); \
})
//定时器的初始化说起来就是一句话,它是告诉
//时钟的发生装置,多长时间发生一次中断,
//据说这个对系统的性能有着十分关键的作用,
//也就是说如果发生的频繁了,运行时间就全被
//时钟中断用去了,如果是频率比较低,那么你就
//进程特别的迟钝,不过我没有编代码尝试过,又是
//道听途说罢了。设置频率是100毫秒发生一次时钟
//中断,这些都是抄书了。
#define _init_8253() \
__asm__(" \
movb $0x36, %%al; \
movw $0x43, %%dx; \
outb %%al, %%dx; \
movw $11931, %%ax; \
movw $0x40, %%dx; \
outb %%al, %%dx; \
movb %%ah, %%al; \
outb %%al, %%dx" \
:: \
)
#define irq_disable(irq) ({ \
__asm__ __volatile__(" \
pushfl; \
cli; \
movb $1, %%ah; \
rolb %%cl, %%ah;\
cmpb $8, %%cl; \
jae 2f; \
1: \
inb $0x21, %%al; \
testb %%ah, %%al; \
jnz 3f; \
orb %%ah, %%al; \
outb %%al, $0x21; \
jmp 3f; \
2: \
inb $0xa1, %%al; \
testb %%ah, %%al; \
jnz 3f; \
orb %%ah, %%al; \
outb %%al, $0xa1; \
3: \
popfl" \
::"c"(irq)); \
})
#define irq_enable(irq) ({ \
__asm__ __volatile__(" \
pushfl; \
cli; \
movb $~1, %%ah; \
rolb %%cl, %%ah; \
cmpb $8, %%cl; \
jae 2f; \
1: \
inb $0x21, %%al; \
andb %%ah, %%al; \
outb %%al, $0x21; \
jmp 3f; \
2: \
inb $0xa1, %%al; \
andb %%ah, %%al; \
outb %%al, $0xa1; \
3: \
popfl" \
::"c"(irq)); \
})
#define out_b(port, data) \
__asm__("outb %%al, %%dx\n\t" \
"nop\n\t" \
"nop" \
::"d"(port),"a"(data) \
)
#define in_b(port) ({\
register unsigned int res; \
__asm__("inb %%dx, %%al\n\t" \
"nop\n\t" \
"nop" \
:"=a"(res):"d"(port)); \
res; \
})
//#include "multiboot2.h"
/* Macros. */
/* Some screen stuff. */
/* The number of columns. */
#define COLUMNS 80
/* The number of lines. */
#define LINES 25
/* The attribute of an character. */
//#define ATTRIBUTE 7
/* The video memory address. */
#define VIDEO 0xb8000
/* Variables. */
/* Save the X position. */
static int xpos;
/* Save the Y position. */
static int ypos;
/* Point to the video memory. */
static volatile unsigned char *video;
/* Forward declarations. */
void cmain (unsigned long magic, unsigned long addr);
static void cls (void);
static void itoa (char *buf, int base, int d);
static void myputchar (int c, int attrib);
void myprintf (int attrib, const char *format, ...);
#define IDT 0
#define IDT_LEN (256 * 8 - 1)
#define GDT (256 * 8)
#define GDT_LEN (512 * 8 - 1)
void myjmp(void);
#define ljmp() \
__asm__( \
"ljmp $(1 * 8), $new_start\n\t" \
"new_start:\n\t" \
"movw $(2 * 8), %%ax\n\t" \
"movw %%ax, %%ds\n\t" \
"movw %%ax, %%es\n\t" \
"movw %%ax, %%ss\n\t" \
"movw $(4 * 8), %%ax\n\t" \
"movw %%ax, %%gs\n\t" \
:: \
)
void divide_error(void);
void general_protection(void);
void timer_interrupt(void);
void key_interrupt(void);
void sys_call(void);
void init_tss(Task task);
void func0(void);
char f0_u_s[128];
void func1(void);
char f1_u_s[128];
void func2(void);
char f2_u_s[128];
void _init_desc(void);
#define goto_ring3(t, stack) ({ \
__asm__("pushfl\n\t" \
"andl $0xffffbfff, (%%esp)\n\t" \
"popfl\n\t" \
"movw $(5 * 8), %%ax\n\t" \
"ltr %%ax\n\t" \
"movw $(6 * 8), %%ax\n\t" \
"lldt %%ax\n\t" \
"movw $(2 * 8 + 7), %%ax\n\t" \
"movw %%ax, %%ds\n\t" \
"sti\n\t" \
"pushl $(2 * 8 + 7)\n\t" \
"pushl %0\n\t" \
"pushfl\n\t" \
"pushl $(1 * 8 + 7)\n\t" \
"pushl %1\n\t" \
"iret\n\t" \
::"S"(stack + 128 - 1),"D"(t)); \
})\
void go_ring3(void);
void cmain (unsigned long magic, unsigned long addr)
{
cls();
int i;
for(i = 0; i < 26; i++)
myprintf (0xf, "Hello, World!\n");
// myprintf(0xc, "How are you!\n");
_init_desc();
int test = 0 / 0;
myprintf(0xf, "How are you!\n");
myprintf(0xd, "SnailOS is startring......\n");
_init_8259();
_init_8253();
irq_enable(0);
irq_enable(1);
init_tss(mytask);
current = tss_table[0]->ldt_sel - 8;
// enable_timer_key();
// sti();
// goto_ring3(func0, f0_u_s);
go_ring3();
// func0();
// func1();
// func2();
while(1) {
//应该是运行不到这里的
}
}
void _init_desc(void) {
static unsigned int idtr[2] = {IDT_LEN, IDT};
static unsigned int gdtr[2] = {GDT_LEN, GDT};
_lidt((char *)idtr);
_lgdt((char *)gdtr);
//_set_seg_desc(gate_addr,type,dpl,base,limit);
// _set_seg_desc((unsigned int *)(GDT + 0 * 8), 0, 0, 0, 0); //空描述符
// _set_seg_desc((unsigned int *)(GDT + 1 * 8), 0xc09a, 0, 0, 0xffffffff);
// _set_seg_desc((unsigned int *)(GDT + 2 * 8), 0xc092, 0, 0, 0xffffffff);
// _set_seg_desc((unsigned int *)(GDT + 3 * 8), 0xc09a, 0, 0x100000, 0xffffffff);
// _set_seg_desc((unsigned int *)(GDT + 4 * 8), 0xc092, 0, 0xb8000, 0xffff);
set_descriptor((Descriptor) (GDT) + 0, 0, 0, 0);
set_descriptor((Descriptor) (GDT) + 1, 0xffffffff, 0, 0xc09a);
set_descriptor((Descriptor) (GDT) + 2, 0xffffffff, 0, 0xc092);
set_descriptor((Descriptor) (GDT) + 3, 0xffffffff, 0x100000, 0xc09a);
set_descriptor((Descriptor) (GDT) + 4, 0xffffffff, 0xb8000, 0xc092);
set_descriptor((Descriptor) (GDT) + 5, 0xffffffff, (int)&(mytask[0].myldt_tss.mytss), 0xc0e9);
set_descriptor((Descriptor) (GDT) + 6, 0xffffffff, (int)(mytask[0].myldt_tss.myldt), 0xc0e2);
set_descriptor((Descriptor) (GDT) + 7, 0xffffffff, (int)&(mytask[1].myldt_tss.mytss), 0xc0e9);
set_descriptor((Descriptor) (GDT) + 8, 0xffffffff, (int)(mytask[1].myldt_tss.myldt), 0xc0e2);
set_descriptor((Descriptor) (GDT) + 9, 0xffffffff, (int)&(mytask[2].myldt_tss.mytss), 0xc0e9);
set_descriptor((Descriptor) (GDT) + 10, 0xffffffff, (int)(mytask[2].myldt_tss.myldt), 0xc0e2);
// _set_seg_desc((unsigned int *)(GDT + 5 * 8), 0xc0e9, 0, (unsigned int)&(mytask[0].myldt_tss.mytss), 6 * 8 - 10);
// _set_seg_desc((unsigned int *)(GDT + 6 * 8), 0xc0e2, 0, (unsigned int)&(mytask[0].myldt_tss.myldt[0]), sizeof(tss) - 1);
set_descriptor((Descriptor) (&(mytask[0].myldt_tss.myldt[0])), 0, 0, 0); //0 * 8 + 7
set_descriptor((Descriptor) (&(mytask[0].myldt_tss.myldt[1])), 0xffffffff, 0x0, 0xc0fa); //1 * 8 + 7
set_descriptor((Descriptor) (&(mytask[0].myldt_tss.myldt[2])), 0xffffffff, 0x0, 0xc0f2); //2 * 8 + 7
set_descriptor((Descriptor) (&(mytask[1].myldt_tss.myldt[0])), 0, 0, 0); //0 * 8 + 7
set_descriptor((Descriptor) (&(mytask[1].myldt_tss.myldt[1])), 0xffffffff, 0x0, 0xc0fa); //1 * 8 + 7
set_descriptor((Descriptor) (&(mytask[1].myldt_tss.myldt[2])), 0xffffffff, 0x0, 0xc0f2); //2 * 8 + 7
set_descriptor((Descriptor) (&(mytask[2].myldt_tss.myldt[0])), 0, 0, 0); //0 * 8 + 7
set_descriptor((Descriptor) (&(mytask[2].myldt_tss.myldt[1])), 0xffffffff, 0x0, 0xc0fa); //1 * 8 + 7
set_descriptor((Descriptor) (&(mytask[2].myldt_tss.myldt[2])), 0xffffffff, 0x0, 0xc0f2); //2 * 8 + 7
// _set_seg_desc((unsigned int *)&(mytask[0].myldt_tss.myldt[0]), 0, 0, 0, 0);
// _set_seg_desc((unsigned int *)&(mytask[0].myldt_tss.myldt[1]), 0xc0fa, 0, 0, 0xffffffff);
// _set_seg_desc((unsigned int *)&(mytask[0].myldt_tss.myldt[2]), 0xc0f2, 0, 0, 0xffffffff);
ljmp();
// myprintf(0xf , "\n");
// myprintf(0xf , "\n");
// myprintf(0xf , "\n");
// char *t = (char *) &(mytask[0].myldt_tss.myldt[0]);
// myprintf(0xd , "0x%x--0x%x\n", *((int *)((char *)(GDT) + 0 * 8 + 4)), *((int *)((char *)(GDT) + 0 * 8 + 0)));
// myprintf(0xd , "0x%x--0x%x\n", *((int *)((char *)(GDT) + 1 * 8 + 4)), *((int *)((char *)(GDT) + 1 * 8 + 0)));
// myprintf(0xd , "0x%x--0x%x\n", *((int *)((char *)(GDT) + 2 * 8 + 4)), *((int *)((char *)(GDT) + 1 * 8 + 0)));
// myprintf(0xd , "0x%x--0x%x\n", *((int *)((char *)(GDT) + 3 * 8 + 4)), *((int *)((char *)(GDT) + 3 * 8 + 0)));
// myprintf(0xd , "0x%x--0x%x\n", *((int *)((char *)(GDT) + 4 * 8 + 4)), *((int *)((char *)(GDT) + 4 * 8 + 0)));
// myprintf(0xd , "0x%x--0x%x\n", *((int *)((char *)(GDT) + 5 * 8 + 4)), *((int *)((char *)(GDT) + 5 * 8 + 0)));
// myprintf(0xd , "0x%x--0x%x\n", *((int *)((char *)(GDT) + 6 * 8 + 4)), *((int *)((char *)(GDT) + 6 * 8 + 0)));
// myprintf(0xe , "0x%x--0x%x\n", *((int *)((char *)(t) + 0 * 8 + 4)), *((int *)((char *)(t) + 0 * 8 + 0)));
// myprintf(0xe , "0x%x--0x%x\n", *((int *)((char *)(t) + 1 * 8 + 4)), *((int *)((char *)(t) + 1 * 8 + 0)));
// myprintf(0xe , "0x%x--0x%x\n", *((int *)((char *)(t) + 2 * 8 + 4)), *((int *)((char *)(t) + 1 * 8 + 0)));
// set_intr_gate(n,addr);
set_trap_gate(0 , ÷_error);
set_trap_gate(0xd , &general_protection);
set_intr_gate(0x20, &timer_interrupt);
set_intr_gate(0x21, &key_interrupt);
set_system_gate(0x80, sys_call);
return;
}
void do_divide_error(int ret_addr, int err_code) {
myprintf(0xc, "DIVIDE_ERROR!...retaddr = 0x%x, err_code = 0x%x", ret_addr, err_code);
__asm__("addl $2, (14 * 4)(%%ebp)"::); //仔细思考这里的偏移量为什么是(14 * 4),而且是相对于ebp的。
// while(1) {
//
// }
}
void do_general_protection(long esp, long error_code) {
myprintf(0xc, "General protection!...esp = 0x%x, error_code = 0x%x", esp, error_code);
while(1) {
}
}
Tss * temp = tss_table;
unsigned int mycurrent = 5 * 8 + 7;
void sche(void) {
while(1) {
temp++;
if(!(*temp)) {
continue;
}
if(temp >= tss_table + 3) {
temp = tss_table;
break;
}
break;
}
if(current == (*temp)->ldt_sel - 8) {
mycurrent = current;
} else {
current = (*temp)->ldt_sel - 8;
}
}
unsigned int sig = 2;
//这里想用C来发送终止进程,但不知道何种原因,不能改变进程表,因此改用汇编语言。
void signal(void) {
if(sig = 0) {
tss_table[1] = 0;
}
if(sig = 1) {
tss_table[1] = &(mytask[1].myldt_tss.mytss);
}
}
unsigned int jiffies = 0;
unsigned int count = 0;
unsigned int count1 = 0;
void do_timer(void) {
jiffies++;
if(!(jiffies % 30)) {
count++;
}
if(!(jiffies % 120)) {
count1++;
}
out_b(0x20, 0x20);
// myprintf(0xf ,"TIMER!...");
sche();
}
void do_sys_call(int eax) {
int mycount = count;
int mycount1 = count1;
if(eax == 0) {
myprintf(0x9, " BLUE! ");
} else if(eax == 1) {
myprintf(0xc, " RED! ");
} else if(eax == 2) {
myprintf(0xa, " GREEN! ");
} else if(eax == 3) {
while(count == mycount) {
}
} else if(eax == 4) {
while(count1 == mycount1) {
}
}
return;
}
unsigned char mykey;
void do_key(void) {
mykey = in_b(0x60);
out_b(0x20, 0x20);
if(mykey == 0x1)
sig = 0;
if(mykey == 0x3b)
sig = 1;
if(mykey == 0xe0) {
} else if(mykey == 0xe1) {
} else if((mykey & 0x80) != 0){
} else {
myprintf(0xe, " 0x%x ", mykey);
}
}
void func0(void) {
__asm__("movw $(2 * 8 + 7), %%ax\n\tmovw %%ax, %%ds\n\t"::);
while(1) {
__asm__("int $0x80\n\t"::"a"(3));
__asm__("int $0x80\n\t"::"a"(0));
}
__asm__("1:\n\tjmp 1b"::);
}
void func1(void) {
__asm__("movw $(2 * 8 + 7), %%ax\n\tmovw %%ax, %%ds\n\t"::);
while(1) {
__asm__("int $0x80\n\t"::"a"(3));
__asm__("int $0x80\n\t"::"a"(1));
}
__asm__("1:\n\tjmp 1b"::);
}
void func2(void) {
__asm__("movw $(2 * 8 + 7), %%ax\n\tmovw %%ax, %%ds\n\t"::);
while(1) {
__asm__("int $0x80\n\t"::"a"(4));
__asm__("int $0x80\n\t"::"a"(2));
}
__asm__("1:\n\tjmp 1b"::);
}
void init_tss(Task task) {
Tss mytss;
mytss = &(task[0].myldt_tss.mytss);
mytss->backlink = 0;
mytss->esp0 = (int)((char *)(&(task[0])) + 512 - 1);
mytss->ss0 = 2 * 8;
mytss->esp1= 0;
mytss->ss1 = 0;
mytss->esp2 = 0;
mytss->ss2 = 0;
mytss->cr3 = 0;
mytss->eip = (int) func0;
mytss->eflags = 0x200;
mytss->eax = 0;
mytss->ecx = 0;
mytss->edx = 0;
mytss->ebx = 0;
mytss->esp = (int)(f0_u_s + 128 - 1);
mytss->ebp = 0;
mytss->esi = 0;
mytss->edi = 0;
mytss->es = 2 * 8 + 7;
mytss->cs = 1 * 8 + 7;
mytss->ss = 2 * 8 + 7;
mytss->ds = 2 * 8 + 7;
mytss->fs = 2 * 8 + 7;
mytss->gs = 2 * 8 + 7;
mytss->ldt_sel = 6 * 8;
mytss->trace_bitmap = 0x8000000;
mytss = &(task[1].myldt_tss.mytss);
mytss->backlink = 0;
mytss->esp0 = (int)((char *)(&(task[1])) + 512 - 1);
mytss->ss0 = 2 * 8;
mytss->esp1= 0;
mytss->ss1 = 0;
mytss->esp2 = 0;
mytss->ss2 = 0;
mytss->cr3 = 0;
mytss->eip = (int) func1;
mytss->eflags = 0x200;
mytss->eax = 0;
mytss->ecx = 0;
mytss->edx = 0;
mytss->ebx = 0;
mytss->esp = (int)(f1_u_s + 128 - 1);
mytss->ebp = 0;
mytss->esi = 0;
mytss->edi = 0;
mytss->es = 2 * 8 + 7;
mytss->cs = 1 * 8 + 7;
mytss->ss = 2 * 8 + 7;
mytss->ds = 2 * 8 + 7;
mytss->fs = 2 * 8 + 7;
mytss->gs = 2 * 8 + 7;
mytss->ldt_sel = 8 * 8;
mytss->trace_bitmap = 0x8000000;
mytss = &(task[2].myldt_tss.mytss);
mytss->backlink = 0;
mytss->esp0 = (int)((char *)(&(task[2])) + 512 - 1);
mytss->ss0 = 2 * 8;
mytss->esp1= 0;
mytss->ss1 = 0;
mytss->esp2 = 0;
mytss->ss2 = 0;
mytss->cr3 = 0;
mytss->eip = (int) func2;
mytss->eflags = 0x200;
mytss->eax = 0;
mytss->ecx = 0;
mytss->edx = 0;
mytss->ebx = 0;
mytss->esp = (int)(f2_u_s + 128 - 1);
mytss->ebp = 0;
mytss->esi = 0;
mytss->edi = 0;
mytss->es = 2 * 8 + 7;
mytss->cs = 1 * 8 + 7;
mytss->ss = 2 * 8 + 7;
mytss->ds = 2 * 8 + 7;
mytss->fs = 2 * 8 + 7;
mytss->gs = 2 * 8 + 7;
mytss->ldt_sel = 10 * 8;
mytss->trace_bitmap = 0x8000000;
return;
}
/* Clear the screen and initialize VIDEO, XPOS and YPOS. */
static void cls (void)
{
int i;
video = (unsigned char *) VIDEO;
for (i = 0; i < COLUMNS * LINES * 2; i++)
*(video + i) = 0;
xpos = 0;
ypos = 0;
}
/* Convert the integer D to a string and save the string in BUF. If
BASE is equal to 'd', interpret that D is decimal, and if BASE is
equal to 'x', interpret that D is hexadecimal. */
static void itoa (char *buf, int base, int d)
{
char *p = buf;
char *p1, *p2;
unsigned long ud = d;
int divisor = 10;
/* If %d is specified and D is minus, put `-' in the head. */
if (base == 'd' && d < 0)
{
*p++ = '-';
buf++;
ud = -d;
}
else if (base == 'x')
divisor = 16;
/* Divide UD by DIVISOR until UD == 0. */
do
{
int remainder = ud % divisor;
*p++ = (remainder < 10) ? remainder + '0' : remainder + 'a' - 10;
}
while (ud /= divisor);
/* Terminate BUF. */
*p = 0;
/* Reverse BUF. */
p1 = buf;
p2 = p - 1;
while (p1 < p2)
{
char tmp = *p1;
*p1 = *p2;
*p2 = tmp;
p1++;
p2--;
}
}
/* Put the character C on the screen. */
static void myputchar (int c, int attrib)
{
if (c == '\n' || c == '\r')
{
newline:
xpos = 0;
ypos++;
if (ypos >= LINES) {
cls();
}
return;
}
*(video + (xpos + ypos * COLUMNS) * 2) = c & 0xFF;
*(video + (xpos + ypos * COLUMNS) * 2 + 1) = attrib;
xpos++;
if (xpos >= COLUMNS)
goto newline;
}
/* Format a string and print it on the screen, just like the libc
function printf. */
void myprintf (int attrib, const char *format, ...)
{
char **arg = (char **) &format;
int c;
char buf[20];
arg++;
while ((c = *format++) != 0)
{
if (c != '%')
myputchar (c, attrib);
else
{
char *p, *p2;
int pad0 = 0, pad = 0;
c = *format++;
if (c == '0')
{
pad0 = 1;
c = *format++;
}
if (c >= '0' && c <= '9')
{
pad = c - '0';
c = *format++;
}
switch (c)
{
case 'd':
case 'u':
case 'x':
itoa (buf, c, *((int *) arg++));
p = buf;
goto string;
break;
case 's':
p = *arg++;
if (! p)
p = "(null)";
string:
for (p2 = p; *p2; p2++);
for (; p2 < p + pad; p2++)
myputchar (pad0 ? '0' : ' ', attrib);
while (*p)
myputchar (*p++, attrib);
break;
default:
myputchar (*((int *) arg++), attrib);
break;
}
}
}
}