大家一起写操作系统(3)-时钟中断
2013-01-26 12:36
387 查看
大家都知道操作系统利用中断来与外设进行交互。80xx86兼容机使用两片级联的8259A可编程中断控制芯片组成一个中断控制器,用于实现与I/O设备的交互。可编程意味着我们可以为不同的外设(时钟,键盘,鼠标等)分配不同的中断号,从而执行不同的中断处理过程。
BIOS初始化这个中断控制器时将中断号8分配给了时钟控制器,因而下面我们通过将中断向量表中的8号描述符设为我们的中断程序地址,进而实现时钟中断程序。我们在中断程序中打印字符'E',每打2000次后再从头开始打,为了能够看出重复打印的效果,满2000次后更换颜色。
LATCH equ 11930
VIDEO_DS equ 0x18
[SECTION text]
[BITS 32]
startup_32:
mov eax,0x10
mov ds,ax
lss esp,[init_stack] ;mem low->reg,mem high->ss
call setup_idt ;初始化IDT中断向量表
call setup_gdt ;初始化GDT
mov eax,0x10 ;初始化完GDT后重新加载ds,es,fs,gs,ss,sp
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
lss esp,[init_stack]
;设置8253定时芯片,把计数器通道0设置成每隔10ms向中断控制器发送一个中断请求
mov al,0x36
mov edx,0x43
out dx,al
mov eax,LATCH
mov edx,0x40
out dx,al
mov al,ah
out dx,al
sti ;开中断
loop:
jmp loop
setup_gdt:
lgdt [lgdt_opcode]
ret
;begin setup_idt fun ;初始化idt,256个描述符全初始化为打印字符函数
setup_idt:
lea edx,[ignore_int] ;中断入口偏移放入edx
mov eax,0x00080000 ;eax高位为内核代码段选择子
mov ax,dx ;eax低位为中断入口偏移低位
mov dx,0x8E00 ;edx低位为中断门定义.DPL=0
lea edi,[idt] ;得到idt表位置,准备初始化
mov ecx,256 ;初始化256 IDT描述符
rp_idt:
mov [edi],eax
mov [edi+4],edx
add edi,8
dec ecx
jne rp_idt
lidt [lidt_opcode]
ret
;end setup_idt fun
ignore_int: ;默认中断处理函数
push ds
push eax
mov eax,0x10
mov ds,ax
mov eax,69
call write_char
mov al,0x20
out 0x20,al
pop eax
pop ds
iret
;BEGIN lidt
;Begin write_char
write_char: ;打印字符函数
push gs
push ebx
mov ebx,VIDEO_DS ;取显存数据段
mov gs,bx
mov bx,[color] ;取显示颜色
cmp bx,0
jg change_color ;当前显示1
mov ah, 0Ch ;黑底红字
jmp dis
change_color:
mov ah, 0Fh ;
dis:
mov bx,[DWORD scr_loc] ;取显存位置
mov [byte gs:ebx],ax ;写入显存
add ebx,2 ;下一个位置
mov [DWORD scr_loc],ebx ;放入内存保存
cmp ebx,2000 ;是否大于2000
jb exit ;小于2000直接退出
mov bx,[color]
cmp bx,0
jz change_color1 ;原来为0,改为1
mov bx,0 ;原来为1,改为0
jmp exit1
change_color1:
mov bx,1
exit1:
mov [color],bx
xor ebx,ebx ;位置置0
mov [DWORD scr_loc],ebx
exit:
pop ebx
pop gs
ret
;End write_char
color: db 0 ;显示颜色
current: dd 0 ;当前执行的任务号
scr_loc: dw 0 ;屏幕位置
align 2
lidt_opcode: ;LIDT寄存器加载的内容
dw 256*8-1 ;长度
dd idt ;线性基址
;END lidt
lgdt_opcode: ;GDT寄存器加载的内容
dw (end_gdt - gdt)-1
dd gdt
align 3 ;GDT内容
gdt:
dd 0x00000000 ;NULL
dd 0x00000000
dd 0x000007ff
dd 0x00c09a00 ;内核代码段0x08
dd 0x000007ff
dd 0x00c09200 ;内核数据段0x10
dd 0x80000002
dd 0x00c0920b ;显存数据段描述符0x18
dw 0x68
dw tss0
dw 0x8900
dw 0x0000 ;内核TSS 0x20
end_gdt:
tss0:
dd 0
dd init_stack,0x10 ;内核esp0,ss0
dd 0,0,0,0,0 ;esp1,ss1,esp2,ss2,cr3
dd 0,0,0,0,0 ;eip,eflags,eax,ecx,edx
dd 0,0,0,0,0 ;ebx,esp,ebp,esi,edi
dd 0,0,0,0,0,0 ;es,cs,ss,ds,fs,gs
dd 0,0x80000000 ;ldt,trace bitmap
idt:
times 512 dd 0 ;初始化中断描述表
kernel_stack:
times 128 dw 0 ;512B内核堆栈
init_stack:
dd init_stack ;堆栈段偏移位置
dw 0x10 ;内核数据段选择符
同样,将编译生成的bin文件复制到前面所说的软盘映像IMG的第2扇区开始处,引导程序就会将其加载到内存0处并执行,然后可以看到屏幕上不停地打印字符'E'.如果对程序中有所疑问,可以查看大家一起写操作系统预备知识.我会将中断的相关知识写到预备知识里。下一章将会介绍如何创建2个任务,并在任务间来回调度。
BIOS初始化这个中断控制器时将中断号8分配给了时钟控制器,因而下面我们通过将中断向量表中的8号描述符设为我们的中断程序地址,进而实现时钟中断程序。我们在中断程序中打印字符'E',每打2000次后再从头开始打,为了能够看出重复打印的效果,满2000次后更换颜色。
LATCH equ 11930
VIDEO_DS equ 0x18
[SECTION text]
[BITS 32]
startup_32:
mov eax,0x10
mov ds,ax
lss esp,[init_stack] ;mem low->reg,mem high->ss
call setup_idt ;初始化IDT中断向量表
call setup_gdt ;初始化GDT
mov eax,0x10 ;初始化完GDT后重新加载ds,es,fs,gs,ss,sp
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
lss esp,[init_stack]
;设置8253定时芯片,把计数器通道0设置成每隔10ms向中断控制器发送一个中断请求
mov al,0x36
mov edx,0x43
out dx,al
mov eax,LATCH
mov edx,0x40
out dx,al
mov al,ah
out dx,al
sti ;开中断
loop:
jmp loop
setup_gdt:
lgdt [lgdt_opcode]
ret
;begin setup_idt fun ;初始化idt,256个描述符全初始化为打印字符函数
setup_idt:
lea edx,[ignore_int] ;中断入口偏移放入edx
mov eax,0x00080000 ;eax高位为内核代码段选择子
mov ax,dx ;eax低位为中断入口偏移低位
mov dx,0x8E00 ;edx低位为中断门定义.DPL=0
lea edi,[idt] ;得到idt表位置,准备初始化
mov ecx,256 ;初始化256 IDT描述符
rp_idt:
mov [edi],eax
mov [edi+4],edx
add edi,8
dec ecx
jne rp_idt
lidt [lidt_opcode]
ret
;end setup_idt fun
ignore_int: ;默认中断处理函数
push ds
push eax
mov eax,0x10
mov ds,ax
mov eax,69
call write_char
mov al,0x20
out 0x20,al
pop eax
pop ds
iret
;BEGIN lidt
;Begin write_char
write_char: ;打印字符函数
push gs
push ebx
mov ebx,VIDEO_DS ;取显存数据段
mov gs,bx
mov bx,[color] ;取显示颜色
cmp bx,0
jg change_color ;当前显示1
mov ah, 0Ch ;黑底红字
jmp dis
change_color:
mov ah, 0Fh ;
dis:
mov bx,[DWORD scr_loc] ;取显存位置
mov [byte gs:ebx],ax ;写入显存
add ebx,2 ;下一个位置
mov [DWORD scr_loc],ebx ;放入内存保存
cmp ebx,2000 ;是否大于2000
jb exit ;小于2000直接退出
mov bx,[color]
cmp bx,0
jz change_color1 ;原来为0,改为1
mov bx,0 ;原来为1,改为0
jmp exit1
change_color1:
mov bx,1
exit1:
mov [color],bx
xor ebx,ebx ;位置置0
mov [DWORD scr_loc],ebx
exit:
pop ebx
pop gs
ret
;End write_char
color: db 0 ;显示颜色
current: dd 0 ;当前执行的任务号
scr_loc: dw 0 ;屏幕位置
align 2
lidt_opcode: ;LIDT寄存器加载的内容
dw 256*8-1 ;长度
dd idt ;线性基址
;END lidt
lgdt_opcode: ;GDT寄存器加载的内容
dw (end_gdt - gdt)-1
dd gdt
align 3 ;GDT内容
gdt:
dd 0x00000000 ;NULL
dd 0x00000000
dd 0x000007ff
dd 0x00c09a00 ;内核代码段0x08
dd 0x000007ff
dd 0x00c09200 ;内核数据段0x10
dd 0x80000002
dd 0x00c0920b ;显存数据段描述符0x18
dw 0x68
dw tss0
dw 0x8900
dw 0x0000 ;内核TSS 0x20
end_gdt:
tss0:
dd 0
dd init_stack,0x10 ;内核esp0,ss0
dd 0,0,0,0,0 ;esp1,ss1,esp2,ss2,cr3
dd 0,0,0,0,0 ;eip,eflags,eax,ecx,edx
dd 0,0,0,0,0 ;ebx,esp,ebp,esi,edi
dd 0,0,0,0,0,0 ;es,cs,ss,ds,fs,gs
dd 0,0x80000000 ;ldt,trace bitmap
idt:
times 512 dd 0 ;初始化中断描述表
kernel_stack:
times 128 dw 0 ;512B内核堆栈
init_stack:
dd init_stack ;堆栈段偏移位置
dw 0x10 ;内核数据段选择符
同样,将编译生成的bin文件复制到前面所说的软盘映像IMG的第2扇区开始处,引导程序就会将其加载到内存0处并执行,然后可以看到屏幕上不停地打印字符'E'.如果对程序中有所疑问,可以查看大家一起写操作系统预备知识.我会将中断的相关知识写到预备知识里。下一章将会介绍如何创建2个任务,并在任务间来回调度。
相关文章推荐
- 大家一起写操作系统(1)-引导程序
- 操作系统开发系列—8.时钟中断
- 一个操作系统的实现-笔记-开启时钟中断
- 大家一起写操作系统(2)-简单的内核
- 大家一起写操作系统(4)-简单的任务切换
- 大家一起写操作系统-准备知识(1)--计算机的启动过程
- 嵌入式实时操作系统μC/OS-||原理及应用学习3----μC/OS-||的中断和时钟
- 时钟中断周期对操作系统整体实时性的影响分析
- 时钟中断周期对操作系统整体实时性的影响分析
- 时钟中断周期对操作系统整体实时性的影响分析
- 一起学mini2440裸机开发(十二)--mini2440的串口中断实验
- Asp.Net中的正则表达式问题可以在此提问,今后大家一起研究!贴出基本语法参考
- \t\t百度邮箱 免费邮箱 最新开发进度——大家很快就可以一起high了
- 《一个操作系统的实现》(三):4.中断和异常&5.保护模式下的I/O
- 今天开通了CSDN博客,希望能结识更多的朋友,大家一起学习交流!
- 超级面试(大家一起娱乐一下)
- 时钟中断TIMER_BH(bottom_half)实现分析
- 一起学CC3200系列教程之中断优先级设置
- S3C2440中断解析和基于WINCE操作系统的中断分析(整理于网络,用于按键中断使用)
- c# 写的 功能强大的 FTP服务器 完全兼容 任何 FTP客户端,最兼容 IE.功能强大 防DDOS 等 .目前只提供下载.希望大家一起改善