第一步首先在setup中打开时钟中断,set_8259A修改如下
set_8259A:
movb $0x11,%al//0x11表示边沿触发,多片级联,需要ICW4
out %al,$0x20//主8259,ICW1
.word 0x00eb,0x00eb
out %al,$0xA0//从8259,IWC1
.word 0x00eb,0x00eb
//系统硬件终端号被设置成从0x20开始
movb $0x20,%al//IRQ0对应中断向量0x20
out %al,$0x21//主8259,ICW2
.word 0x00eb,0x00eb
mov $0x28,%al//IRQ8对应中断向量0x28
out %al,$0xA1//从8259,ICW2
.word 0x00eb,0x00eb
movb $0x04,%al//IR2对应从8259
out %al,$0x21//主8259,ICW3
.word 0x00eb,0x00eb
movb $0x02,%al//对应主8259的IR2
out %al,$0xA1//从8259,ICW3
.word 0x00eb,0x00eb
movb $0x01,%al
out %al,$0x21//主8259,ICW4
.word 0x00eb,0x00eb
out %al,$0xA1//从8259,ICW4
.word 0x00eb,0x00eb
//movb $0xff,%al//屏蔽主8259的全部中断
movb $0xfe,%al//仅仅开启主8259的定时器中断
out %al,$0x21//主8259,OCW1
.word 0x00eb,0x00eb
movb $0xff,%al
//屏蔽从8259的全部中断
out %al,$0xA1 //从8259,OCW1
.word 0x00eb,0x00eb
ret
head.S修改如下:
#define Descriptor(base,lim,attr)\
.word lim&0xffff;\
.word base&0xffff;\
.byte (base>>16)&0xff;\
.word ((lim>>8)&0xf00)|(attr&0x0f0ff);\
.byte ((base>>24)&0xff)
#define Gate(Selector,Offset,PCount,Attr)\
.2byte (Offset&0xffff);\
.2byte (Selector);\
.2byte (PCount&0x1f)|((Attr<<8)&0xff00);\
.2byte ((Offset>>16)&0xffff)
DA_32=0x4000 //32位模式
DA_LIMIT_4K=0x8000 //颗粒度为4096
DA_DRW=0x92 //数据段可读可写
DA_CR=0x9A //可读可执行
DA_C = 0x98
SETUPSEG = 0x9020
SETUPAddr = SETUPSEG<<4
DA_386CGate = 0x8c
DA_386IGate = 0x8E
DA_PL0 = 0x00
.text
.globl start/*程序从start处开始运行*/
.code32
start:
movl $0x20,%eax
mov %ax,%ds //因为ds是数据段寄存器,所以要加载一个数据段,否则会发生异常(可以试试0x08描述符)
mov %ax,%es
mov %ax,%ss
mov $0xffff,%esp
/*加载gdtr即将全局描述符表gdt的首地址和gdt的界限赋给gdtr寄存器*/
lgdt GdtPtr
lidt IdtPtr
movl $0x20,%eax
mov %ax,%ds
mov %ax,%es
mov %ax,%ss
mov $0xffff,%esp
ljmp $0x8,$LABEL_SEG_CODE32
.align 4
LABEL_SEG_CODE32:
.code32
movw $0x10,%ax
movw %ax,%gs
movl $((80*12+79)*2),%edi/*第12行,79列*/
movb $0x0c,%ah/*高四位表示黑底,低四位表示红字*/
movb $'S',%al/*显示的字符*/
movw %ax,%gs:(%edi)
int $0x80
sti
loop1:/*无限循环*/
jmp loop1
.align 4
INT_TEST:
.code32
movl $((80*13+79)*2),%edi/*第11行,79列*/
movb $0x0c,%ah/*高四位表示黑底,低四位表示红字*/
movb $'I',%al/*显示的字符*/
movw %ax,%gs:(%edi)
iret
loop2:/*无限循环*/
jmp loop2
.align 4
ClockHandler:
movl $((80*14+79)*2),%edi
movw %gs:(%edi),%ax
add $1,%ax
movw %ax,%gs:(%edi)
movb $0x20,%al
out %al,$0x20
iret
loop3:/*无限循环*/
jmp loop3
ret
.align 4
GDT_START:
Descriptor_DUMMY:Descriptor(0x0,0x0,0x0)
Descriptor_CODE32 :Descriptor(0x0,0xffffffff,DA_C+DA_32)
Descriptor_VIDEO:Descriptor(0xb8000,0x0ffff,DA_DRW)
Descriptor_SYSTM :Descriptor(0x00000,0xffffffff,DA_C+DA_32)
Descriptor_SYSTM2 :Descriptor(0x00000,0xffffffff,DA_DRW)
GDT_END:
GdtPtr:
.word (GDT_END-GDT_START)-1 # so does gdt
.long GDT_START # This will be rewrite by code.
.align 4
LABEL_IDT:
.code32
.rep 32
Gate(0x08,(INT_TEST - start),0,(DA_386IGate+DA_PL0))
.endr
Gate(0x08,(ClockHandler - start),0,(DA_386IGate+DA_PL0))
.rep 222
Gate(0x08,(INT_TEST - start),0,(DA_386IGate+DA_PL0))
.endr
END_IDT:
.set Idtlen,(END_IDT - LABEL_IDT)
IdtPtr:
.word (END_IDT-LABEL_IDT)-1 # so does gdt
.long LABEL_IDT # This will be rewrite by code.