代码拉取完成,页面将自动刷新
IDT_BASE:
%rep 256
Gate CODE32_FLAT_SELECTOR, 0, 0, DA_INTR_GATE
%endrep
IDT_LEN equ $ - IDT_BASE
IDT_PTR :
dw IDT_LEN - 1
dd IDT_BASE
lidt [IDT_PTR]
通过共享内存的方式将 IDT 信息告诉 kernel
共享内存一般用于实现不同程序间数据交互
比如,我们规划内存地址 0xA000 为共享内存的起始地址。目前内存中的使用情况如下:
共享内存中的数据位置必须双方提前定义好,虽然我们现在只需要将 IDT 位置信息传递到 kernel,但是未雨绸缪,我们把 GDT 和 LDT 信息都放到共享内存吧,说不定以后有需要
loader.asm 中将数据放入共享内存
PutDataToShare:
; 将 GDT 描述符表基地址放到共享内存 GDT_ENTRY_ADDR 中
mov dword [GDT_ENTRY_ADDR], GDT_BASE
; 将 GDT 描述符个数放到共享内存 GDT_SIZE_ADDR 中
mov dword [GDT_SIZE_ADDR], GDT_LEN / 8
...
ret
在 kernel 中取数据
U32* p = (U32*)0xA000;
printk("GDT Entry: %x\n", *p);
p = (U32*)0xA004;
printk("GDT Size: %d\n", *p);
// ... 读取其它数据
创建 “share.h” 文件,将共享内存相关数据地址放入,如果想使用共享内存中的数据,则包含头该文件,通过指针解引用的方式就可获取到数据了
#define SHARE_START_ADDR 0xA000
#define GDT_ENTRY_ADDR (SHARE_START_ADDR + 0)
#define GDT_SIZE_ADDR (SHARE_START_ADDR + 4)
#define LDT_ENTRY_ADDR (SHARE_START_ADDR + 8)
#define LDT_SIZE_ADDR (SHARE_START_ADDR + 12)
#define IDT_ENTRY_ADDR (SHARE_START_ADDR + 16)
#define IDT_SIZE_ADDR (SHARE_START_ADDR + 20)
// ...
共享内存用法是不是很简单,接下来继续主线任务吧
E_RET IrqRegister(E_IRQ_NUM irqNmu, F_ISR ifunc)
{
// 检查参数合法性
if(irqNmu >= IRQ_TOTAL || NULL == ifunc)
return E_ERR;
// 从共享内存中获取中段描述符表 IDT 地址 和大小
GATE* gate = (GATE*)(*(U32*)IDT_ENTRY_ADDR);
U32 idtSize = *((U32*)(IDT_SIZE_ADDR));
// 合法性检查
if(NULL == gate || 0 == idtSize || irqNmu >= idtSize)
return E_ERR;
// 函数名就相当于函数入口地址
// 由于使用平坦模式,段基址为 0,那么函数名 func 地址就等同于段内偏移
(gate+irqNmu)->offset1 = (U16)((U32)ifunc);
(gate+irqNmu)->offset2 = (U16)(((U32)ifunc)>>16);
return E_OK;
}
void int0x80_func(void)
{
printk("int0x80\n");
while (1);
}
IrqRegister(0x80, int0x80_func);
asm volatile("int $0x80");
void int0x80_func(void)
{
printk("int0x80\n");
asm volatile("iret");
}
IrqRegister(0x80, int0x80_func); // 注册 0x80 号中断服务程序
asm volatile("int $0x80"); // 触发 0x80 号中断
printk("After int 0x80\n");
void int0x80_func(void)
{
printk("int0x80\n");
asm volatile("leave;iret");
}
static void DefaultHander(void)
{
asm volatile("leave;iret"); // 中断返回
}
asm_func:
push ebp
mov ebp, esp
xxx
;pop ebp ; 推荐使用 leave
leave
ret
global pic_init
global write_m_EOI
global write_s_EOI
global read_m_ISR
global read_s_ISR
global read_m_IRR
global read_s_IRR
global read_m_IMR
global write_m_IMR
global read_s_IMR
global write_s_IMR
global set_m_smm
void pic_init(void); // 初始化可编程中断控制器 8259A - 级联
void write_m_EOI(void); // 手动结束主片中断
void write_s_EOI(void); // 手动结束从片中断
void read_m_ISR(void); // 读主片 ISR 寄存器的值,返回值存入 al 寄存器
void read_s_ISR(void); // 读从片 ISR 寄存器的值,返回值存入 al 寄存器
void read_m_IRR(void); // 读主片 IRR 寄存器的值,返回值存入 al 寄存器
void read_s_IRR(void); // 读从片 IRR 寄存器的值,返回值存入 al 寄存器
void read_m_IMR(void); // 读主片 IMR 寄存器的值,返回值存入 al 寄存器
void write_m_IMR(void); // 将 al 寄存器的值写入主片 IMR 中
void read_s_IMR(void); // 读从片 IMR 寄存器的值,返回值存入 al 寄存器
void write_s_IMR(void); // 将 al 寄存器的值写入从片 IMR 中
void set_m_smm(void); // 设置主片工作在特殊屏蔽模式
void TimerHandle(void)
{
static U32 count;
SetCursorPos(0, 3);
printk("TimerHandle: %d", count++);
write_m_EOI(); // 手动结束主片中断
asm volatile("leave;iret"); // 中断返回
}
IrqRegister(IRQ32, TimerHandle); // 注册 0x20 号中断(时钟中断)
pic_init();
...
asm volatile("sti"); // 开中断
DefaultHandle:
ret
Int0x00_Entry:
call DefaultHandle
iret
Int0x01_Entry:
call DefaultHandle
iret
Int0x02_Entry:
call DefaultHandle
iret
; 下面是所有的中断服务程序入口,省略 ...
Int0x20_Entry:
; 保存上下文
; ...
call Int0x20Handle ; 中断逻辑功能
; 恢复上下文
; ...
iret
void Int0x20Handle(void)
{
static U32 count;
SetCursorPos(0, 3);
printk("TimerHandle: %d", count++);
write_m_EOI(); // 手动结束主片中断
// asm volatile("leave;iret"); // 中断返回
}
IntVectorStart:
dd Int0x00_Entry
dd Int0x01_Entry
dd Int0x02_Entry
...
IntVectorLen:
dd ($-IntVectorStart)/4
E_RET IrqInit(void)
{
E_IRQ_NUM irqNum = IRQ0;
E_RET ret = E_ERR;
U32 idtSize = *((U32*)(IDT_SIZE_ADDR));
U32* isr = (U32*)&IntVectorStart;
U32 isrSize = (U32)IntVectorLen;
for(irqNum = IRQ0; irqNum < IRQ_TOTAL && irqNum < idtSize && irqNum < isrSize; irqNum++, isr++)
{
ret |= IrqRegister(irqNum, (F_ISR)(*isr));
}
return ret;
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。