读书笔记《30天自制操作系统》day06

1. 鼠标及键盘的响应功能,因为用到中断所以必须自32位保护模式下设置GDT和IDT,以前在asmhead中设置时用汇编代码设置,现在用C操作。

2. GDT,IDT的补充知识,图片来自赵炯博士linux0.11内核分析书
(1)实模式下寻址方式是:物理地址=段值*16+偏移地址
(2)保护模式下也是用(段值:偏移量)形式表示地址,但是段与以前的段是不一样的,实模式下的段值仍可以看做是一个地址,但保护模式下段值只是一个索引。
(3)保护模式下有全局段表位置保存在GDTR这个新寄存器中,每个表项就是一个段描述符(图六),这是个描述段信息的结构,保存段索引的寄存器叫段选择子,它其实就是一个寄存器但有图五所描述的结构。

图一:新的寄存器们

图二:保护模式下的寻址,分段情况和分段分页情况

图三:段选择子选择GDT与LDT关系

图四:GDT与LDT关系

图五:段选择子(段选择符)TI标记位功能见图三

图六:全局段描述符GDT

struct SEGMENT_DESCRIPTOR
{
short limit_low,base_low;
char limit_high,base_high;
};


图七:LDT,IDT结构

struct GATE_DESCRIPTOR
{
short offset_low,selector;
char dw_count,access_right;
short offset_high;
};


 

图八:IDT原理

图九:GDT与IDT关系

3. gdt和idt初始化C代码

 

void init_gdtide()
{
	sturct SEGMENT_DESCRIPTOR* gdt = (sturct SEGMENT_DESCRIPTOR*)0x00270000;//gdt表的首位到0x0027ffff结束
	struct GATE_DESCRIPTOR* idt=(struct GATE_DESCRIPTOR*)0x0026f800;//idt表的首位到0x0026ffff结束
	
	int i;
	for(i=0;i<8192;i++)//段选择子用12位表示段值,故最大8192
	{
		set_segmdesc(gdt+i,0,0,0);//全部初始化为0
	}
	//0号段保留NULL Description
	set_segmdesc(gdt+1,0xffffffff,0x00000000,0x4092);//os数据段
	set_segmdesc(gdt+2,0x0007ffff,0x00280000,0x409a);//os代码段,bootback.c在这里
	load_gdtr(0xfff,0x00270000);//将GDT表首地址加载到GDTR
	
	for(i=0;i<256;i++)
	{
		set_gatedesc(idt+i,0,0,0);
	}
	load_idtr(0x7ff,0x0026f800);
	return ;	
}
/*
* 设置GDT
* sd:GDT表首址
* limit:段限长 
* base:段指向代码或数据段地址
* ar:段管理属性	00000000(0x00):未使用的记录表
*		10010010(0x92):os用,可读写段,不可执行,ring0
*		10011010(0x9a):os用,可执行段,可读不可写,ring0
*		11110010(0xf2):app用,可读写,不可执行,ring3
*		11111010(0xfa):app用,可执行,可读不可写,ring3
*/
void set_segmdesc(struct SEGMENT_DESCRIPTOR* sd,unsigned int limit,int base,int ar)
{
	if(limit>=0xffff)
	{
		ar!=0x8000;
		limit/=0x1000;
	}
	sd->limit_low = limit&0xffff;
	sd->base_low = base&0xffff;
	sd->base_mid = (base>>16)&0xff;
	sd->access_right = ar&0xff;
	sd->limit_high = ((limit>>16)&0x0f)|((ar>>8)&0xf0);
	sd->base_high = (base>>24)&0xff;
	return;
}
void set_gatedesc(struct GATE_DESCRIPTOR* gd,int offset,int selector,int ar)
{
	gd->offset_low = offset&0xffff;
	gd->selector = selector;
	gd->dw_count = (ar>>8)&0xff;
	gd->access_right = ar&0xff;
	gd->offset_high = (offset>>16)&0xffff;
	return ;
}


4. PIC的初始化,计算机上有两个PIC,从PIC连到了主PIC的IRQ2引脚,PIC的初始化一般使用都是固定的,对于PIC来说,PIC是外部设备所以cpu使用out指令将设置外设信息写到外设对应寄存器里就可以了。
PIC的寄存器们:(1)IMR是中断屏蔽寄存器,该寄存器为8位,每个PIC都有,如果某一位设置为1则表示PIC忽略该路中断信号。(2)ICW是初始化控制数据,ICW有四个ICW1与ICW4寄存器保存的数据是固定的。ICW3是主从连接设定其实也是固定的从PIC是连着主PIC的IRQ2引脚所以值为00000100。ICW2是我们需要设定的表示IRQ以哪一号中断通知CPU。


 

void init_pic()
{
	io_out8(PIC0_IMR,0xff);//禁止所有中断
	io_out8(PIC1_IMR,0xff);
	
	io_out8(PIC0_ICW1,0X11);//固定
	io_out8(PIC0_ICW2,0X20);//IRQ1~7中断信号由INT20~27发出
	io_out8(PIC0_ICW3,1<<2);//固定
	io_out8(PIC0_ICW4,0X01);//固定
	
	io_out8(PIC1_ICW1,0X11);//固定
	io_out8(PIC1_ICW2,0X28);//IRQ8~15中断信号由INT28~2f发出
	io_out8(PIC1_ICW3,2);//固定
	io_out8(PIC1_ICW4,0X01);//固定
	
	io_out8(PIC0_IMR,0Xfb);
	io_out8(PIC1_IMR,0xff);
	return;
}


5. 鼠标连接到了IRQ12上其中断响应号为0x2c,键盘是IRQ1中断响应号是0x21 。中断处理代码执行结束后应调用IRETD,该指令需要使用汇编编写,并且在处理中断时需要保存寄存器值,并在结束后恢复,所以调用C语言编写的中断处理程序代码要包装一下。

    extern _inthandler21
_asm_inthadler21:
    push es
    push ds
    pushad
    mov eax,esp
    push eax
    mov ax,ss
    mov ds,ax
    mov es,ax
    call _inthandler21
    pop eax
    popad
    pop ds
    pop es
    iretd


 

void inthandler21(int* esp)
{
//...
}


6. IDT的设置如下

set_gatedesc(idt+0x21,(int)asm_inthandler21,2*8,AR_INTGATE32);

上述代码中中断代码的偏移量由asm_inthandler21指出,而所在段为2号,而二号端是GDT中指出的

set_segmdesc(gdt+1,0xffffffff,0x00000000,0x4092);/*系统专用,不可执行,可读写数据段*/
set_segmdesc(gdt+2,0x0007ffff,0x00280000,0x409a);/*系统专用,可执行,只读代码段*/


可执行代码段2中保存了bootpack.c代码,在asmhead.nas中将bootpack.c代码memcpy到了0x00280000这里

BOTPAK	EQU		0x00280000

MOV		ESI,bootpack	
MOV		EDI,BOTPAK		
MOV		ECX,512*1024/4
CALL	memcpy

同样在asmhead.nas中有,跳入HairMain的代码,也是跳到2段中

JMP     DWORD 2*8:0x0000001b

这样当产生键盘中断时能调用inthandler21函数了。
 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值