操作系统与网络实现 之二十三(丙)

addinter.asm

[BITS 32]

 

[GLOBAL _addin]    ;我们必须导出这个函数让C程序使用,注意此函数名不用出现在头文件里

[EXTERN _keyboard_interrupt_handle]    ;用到本文件外定义的函数

 

[SECTION .data]

 

pdescr        equ    0x8000

null          equ    0h

os_code32_sel equ    8h        ;1,gdt,rpl=00

os_data32_sel equ    10h    ;2,gdt,rpl=00

gdt_entries   equ    3         ;共有3个段描述符:null,os code32,os data32,

idt_entries   equ    47       

gdt_table     equ pdescr + 6

idt_table     equ pdescr + 6 +3*8

kb            equ pdescr + 6 +3*8 + 33*8  ;键盘中断的段 在irq132+1=33294=0x126

tm            equ pdescr + 6 + 3*8 + 32*8 ;时钟中断的段,irq0

ms            equ pdescr + 6 + 3*8 + 44*8 ;鼠标中断的段,鼠标在irq12 32+12=44

woll equ 0x500000

[SECTION .text]

_addin:            ;入口

pushad

 

jmp                 main

 

default_hand:

;默认中断处理函数  在256个中断里大部分用此中断,什么也不做就返回

;告诉硬件,中断处理完毕,即发送 EOI 消息

mov  eax, 0x500000

mov  word[eax],04321h  ;0x500000处留下足迹,

;运行调试模式,c,程序结束, 先敲击键盘几下,ctrl+c退出程序,通过 x/10 0x500000查看

  mov               al , 0x20

  out               0x20 , al

  out               0xa0 , al

iret

 

time_hand:

;时钟中断处理函数 

mov  eax, 0x500000

mov  word[0x500000+8],09876h  ;0x500000处留下足迹,

  mov               al , 0x20

  out               0x20 , al

  out               0xa0 , al

iret

 

keyboard_hand:

;键盘中断处理函数。

;告诉硬件,中断处理完毕,即发送 EOI 消息

inc word[woll+2]       ;0x500002处字作为计数中断次数,一次键击产生两次计数。

mov ebx,0x500007 

add bx,word[woll+2]

mov dx,0x60

in al,dx   ;接受键盘输出值

mov  byte[ebx],al  ;0x500008开始处留下中断扫描码

mov  word[0x500004],0abcdh  ;0x500004处留下足迹,

;运行调试模式,命令窗口,c,转到主窗口, 敲击键盘几下,转到命令窗口,ctrl+c退出程序,通过 x/10 0x500000查看

  pushad

  call              _keyboard_interrupt_handle

 

  mov               al , 0x20

  out               0x20 , al

  out               0xa0 , al

  popad

iret

 

mouse_hand:

;时钟中断处理函数 

mov  eax, 0x500000

mov  word[0x500000+12],01515h  ;0x500012处留下足迹,

  mov               al , 0x20

  out               0x20 , al

  out               0xa0 , al

iret

 

init_8259A:

;发送 ICW1 : 使用 ICW4,级联工作

mov al,011h 

out 020h,al  ;8259ICW1

out 0A0h,al  ;8259ICW1

;发送 ICW2,中断起始号从 0x20 开始(第一片)及 0x28开始(第二片)

mov al,020h ;IRQ0 对应中断向量0x20

out 021h,al  ;8259ICW2

mov al,028h ;IRQ8 对应中断向量0x28

out 0A1h,al  ;8259ICW2

 

mov al,04h   ;IRQ2与从8259相连

out 021h,al  ;8259ICW3

mov al,02h   ;对应主8259IRQ2

out 0A1h,al  ;8259ICW3

 

mov al,01h 

out 021h,al  ;8259ICW4

out 0A1h,al  ;8259ICW4

 

mov al,11111101b;屏蔽主8259,不屏蔽,IRQ1键盘外所有中断

out 021h,al      ;8259,OCW1

 

mov al,0xff ;屏蔽从8259所有中断

out 0A1h,al      ;8259,OCW1

 

ret

 

main:

 

;built up GDT table

cli

 

;初始化8259A

call init_8259A

 

mov  eax,gdt_table

;item 0:null descriptor,

mov  dword[eax],0

mov  dword[eax+4],0

add  eax,8

;item 1,OS code32 descriptor,

;Base=00000000h,limit=0ffh,G=1,D=1,type=a,dpl=0

mov  word[eax],0ffh

mov  word[eax+2],0

mov  byte[eax+4],00h

mov  byte[eax+5],09ah

mov  byte[eax+6],0c0h

mov  byte[eax+7],00h

add  eax,8

;item 2,OS data32 descriptor

;Base=00000000h,Limit=0fffffh,G=1,D=1,Type=2,DPL=0

mov  word[eax],0ffffh

mov  word[eax+2],0000h

mov  byte[eax+4],00h

mov  byte[eax+5],092h

mov  byte[eax+6],0cfh    ;高四位是G D 0 AVL,此处为1100 = c ,低四位是limit bit 16-19 此处为f

mov  byte[eax+7],00h

add  eax,8

;built false GDT descriptor

mov  word[pdescr+0],(gdt_entries*8) 

mov  dword[pdescr+2],gdt_table

lgdt [pdescr]

 

;建中断门

mov  eax,idt_table

mov  ebx,default_hand

mov  word[eax],bx     ;offset 15:0   在于0x801e  显示0x0c4e

mov  word[eax+2],os_code32_sel

mov  byte[eax+4],00h  ;000 + 五位保留 = 00h

mov  byte[eax+5],8eh  ;高四位是 P=1 DPL=00 0 此处为1000 =8  ,低四位是 D=1 110  =E

shr  ebx,16

mov  word[eax+6],bx   ;offset 31:16  显示0x0008  与前面合成地址为 0x80c4e

 

;fill all IDT table with default item

mov  esi,idt_table

mov  edi,(idt_table+8)

mov  ecx,(idt_entries-1)*2

rep  movsd    

;IRQ0         定时计数 

mov  eax, tm

mov  ebx, time_hand

mov  word[eax],bx     ;offset 15:0   0x8  显示0x

shr  ebx,16

mov  word[eax+6],bx   ;offset 31:16  显示0x0008  与前面合成地址为

 

;IRQ1         键盘 其表地址在 pdescr + 6 +3*8 + 33*8  将其处理程序地址填上keyboard_hand

mov  eax, kb

mov  ebx, keyboard_hand

mov  word[eax],bx     ;offset 15:0   0x8126  显示0x0c5f

shr  ebx,16

mov  word[eax+6],bx   ;offset 31:16  显示0x0008  与前面合成地址为 0x80c5f

 

;built false GDT descriptor for 中断

mov  word[pdescr+0],(idt_entries*8) 

mov  dword[pdescr+2],idt_table

lidt [pdescr]

 

sti   ;开中断

 

popad

ret

 

keyboard.c

#include "..\include\graph.h"

void keyboard_interrupt_handle() ; 

unsigned short color ;

unsigned int x = 250 ;

unsigned int y = 80 ;

//扫描码与数字及字母对应的一维数组

char ch[51]={'A','B','1','2','3','4','5','6','7','8','9','0','C','D','E','F','q','w','e','r','t','y','u','i','o','p','G','H','I','J','a','s','d','f','g','h','j','k','l','K','L','M','N','O','z','x','c','v','b','n','m'} ;

// 键盘中断处理函数

char *b = (char *) 0x500008; //0x500008处有扫描码,这个是初始值,在中断之前赋一个初始值,随着键盘中断增加,这个值也要增加,所以把它拿出来在中断例程之外。

void keyboard_interrupt_handle() {

//写字的颜色

color = rgb_mix( 0 , 200 , 100 ) ;

int i ;

unsigned char ch2 = *(b +0) ;

unsigned char lo4,hi4 ;

hi4 = (ch2 & 0xf0) >> 4;

lo4 = ch2 & 0x0f;

i = hi4*16+lo4 ;

if(i<52){   //超出数组下标的乱码不显示

  ya_draw_english(  x, y, ch[i] , color ) ;

x=x+10 ;

}

b=b+1;  //b值随着中断增加,以便显示下一个字

}

 

 

 

makefile

######################

#声明要编译的所有组成,这里的ya是本工程名称,可以取任何名字,这里就用ya

######################

ya:out/boot.bin out/kernelloader.bin out/kernel.asmo out/kernel.o out/graph.o out/keyboard.o out/kernel.ld  out/kernel.bin out/addinter.asmo out/creat_img.exe out/write_in_img.exe A B C D E F G H

#开始对各部分编译,注意不是空格是Tab

out/boot.bin:code/boot.asm

nasm code/boot.asm -o out/boot.bin

out/kernelloader.bin:code/kernelloader.asm

nasm code/kernelloader.asm -o out/kernelloader.bin

# 编译asm文件,生成中间文件

out/kernel.asmo:code/kernel.asm

nasm -f aout code/kernel.asm -o out/kernel.asmo

out/addinter.asmo:code/addinter.asm

nasm -f aout code/addinter.asm -o out/addinter.asmo

# 编译C文件,生成中间文件

out/kernel.o:code/kernel.c

gcc -fpack-struct -std=c99 -c code/kernel.c -o out/kernel.o

out/graph.o:code/graph.c

gcc -fpack-struct -std=c99 -Wno-packed-bitfield-compat -c code/graph.c -o out/graph.o

out/keyboard.o:code/keyboard.c

gcc -fpack-struct -std=c99 -Wno-packed-bitfield-compat -c code/keyboard.c -o out/keyboard.o

# 链接内核

out/kernel.ld:out/kernel.asmo out/kernel.o out/graph.o out/keyboard.o out/addinter.asmo

ld  -Ttext 0x80000 -e start -o out/kernel.ld out/kernel.asmo out/kernel.o out/graph.o  out/keyboard.o out/addinter.asmo

# 生成可执行代码文件

out/kernel.bin:out/kernel.ld

objcopy -R .note -R .comment -S -O binary out/kernel.ld out/kernel.bin

# 制作内核映象文件

out/creat_img.exe:code/creat_img.c

gpp code/creat_img.c -o out/creat_img.exe

# 执行dos命令,在final目录下生成a.img文件

A:

out/creat_img.exe final/a.img

 

# 写入文件,argv[1]=目标文件 argv[2]=源文件  argv[3]=写入偏移量  

#DOS下用法: write.exe a.img kernelloader.bin 512

out/write_in_img.exe:code/write_in_img.c

gpp code/write_in_img.c -o out/write_in_img.exe

# 执行dos命令,向a.img写入代码,内容是boot.bin

# 写入磁盘位置从0偏移量起始,1个扇区512字节

B:

out/write_in_img.exe final/a.img out/boot.bin 0

# 执行dos命令,向a.img写入代码,内容是kernelloader.bin

# boot.bin已经占用了512字节,写入磁盘位置从512偏移量起始,2个扇区1024字节

C:

out/write_in_img.exe final/a.img out/kernelloader.bin 512

# 执行dos命令,向a.img写入代码,内容是asc16

# boot.bin+kernelloader.bin已经占用了512+1024 = 1536字节,写入磁盘位置从1536偏移量起始

D:

out/write_in_img.exe final/a.img charpic/asc16 1536

E:

out/write_in_img.exe final/a.img charpic/hzk16f 5632

F:

out/write_in_img.exe final/a.img charpic/ya.bmp 267776

G:

out/write_in_img.exe final/a.img charpic/faya.bmp 361984

H:

out/write_in_img.exe final/a.img out/kernel.bin 479232

 

 

######################

 

 

bochsrc.bxrc   (for Bochs-2.6.8)

 

###############################################################

# bochsrc.txt file for flopy image.

###############################################################

 

# how much memory the emulated machine will have

megs: 32

 

# filename of ROM images

romimage: file=../BIOS-bochs-latest

vgaromimage: file=../VGABIOS-lgpl-latest

 

# what disk images will be used

floppya: 1_44=a.img, status=inserted

 

# choose the boot disk.

boot: a

 

# where do we send log messages?

log: bochsout.txt

 

程序运行效果如图:

键入type12345

wps366.tmp

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值