青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

天衣有縫

冠蓋滿京華,斯人獨憔悴~
posts - 35, comments - 115, trackbacks - 0, articles - 0
   :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

5課:中斷和異常2      下載源代碼


聲明:轉載請保留

譯者http://www.shnenglu.com/jinglexy

原作者:xiaoming.mo at skelix dot org

MSN & Email: jinglexy at yahoo dot com dot cn

目標


在上一節課中,我們介紹了如何處理異常。本課中,我們講學習如何在skelix中使用時鐘中斷和鍵盤。


可編程定時器通常使用主板上的8253/8254芯片。經過設置后,它每隔一段時間會觸發一個中斷,我們將利用它來實現多任務的搶占。這個定時器芯片有3個獨立的計數器模塊,可以使用0x40~0x42端口來操作它們,每個計數器有自己的16為計數寄存器,并且可以在6中狀態下工作運行,這個計數器可以使用BCD或者16進制。通過0x43端口可以訪問這3個計數寄存器,該控制端口操作字格式如下:

 

 7,6

Select Counter ,選擇對那個計數器進行操作。 “00” 表示選擇 Counter 0 “01” 表示選擇 Counter 1 “10” 表示選擇 Counter 2 “11” 表示 Read-Back Command (僅對于 8254 ,對于 8253 無效)

5,4

Read/Write/Latch 格式位。 “00” 表示鎖存( Latch )當前計數器的值; “01” 只讀寫計數器的高字節 ( MSB ); “10” 只讀寫計數器的低字節( LSB ); “11” 表示先讀寫計數器的 LSB ,再讀寫 MSB

3-1

Mode bits ,控制各通道的工作模式。 “000” 對應 Mode 0 “001” 對應 Mode 1 “010” 對應 Mode 2 “011”對應 Mode 3 “100” 對應 Mode 4 “101” 對應 Mode 5

  0

控制計數器的存儲模式。 0 表示以二進制格式存儲, 1 表示計數器中的值以 BCD 格式存儲

 

根據Intel手冊,系統上電后,8254狀態是不可知的。工作模式,計數值,輸出基數都是不可知的。只有對它進行編程,才能使用各個計數器模塊。現在我們來看下程序:
05/timer/time.c

 

void timer_install(int hz) {        // 設置定時器多長時間發送一個中斷給cpu
    unsigned int divisor = 1193180/hz;

由于外部晶振電路頻率是1193180, 所以設置計數器值為1193180/hz

表示當計數從0累加到1193180/hz后發一個方波脈沖給cpu


    outb(0x36, 0x43);               //
二進制,工作模式為3,先寫LSB再寫MSB
    outb(divisor&0xff, 0x40);
    outb(divisor>>8, 0x40);
    outb(inb(0x21)&0xfe, 0x21);     //
設置PIC1 的掩碼第0位:允許時鐘中斷
}

volatile unsigned int timer_ticks = 0;

void do_timer(void) {               //
時鐘中斷處理程序
    int x , y;
    ++timer_ticks;
    get_cursor(&x, &y);
    set_cursor(71, 24);
    kprintf(KPL_DUMP, "%x", timer_ticks);
    set_cursor(x, y);
    outb(0x20, 0x20);              //
發送eoi:通知PIC1 中斷例程已處理完成,可以接收新的中斷了

因為timer只鏈接在PIC1上,所以不需要 oub(0x20, 0xa0) 來告知PIC2

}

 

另外我們還需要改一些其他文件:
05/timer/include/isr.h

#define VALID_ISR    (32+1)        // 我們添加了一個新的ISR例程到isr表中


05/timer/isr.s

isr:    .long    divide_error, isr0x00, debug_exception, isr0x01
        .long    breakpoint, isr0x02, nmi, isr0x03
        .long    overflow, isr0x04, bounds_check, isr0x05
        .long    invalid_opcode, isr0x06, cop_not_avalid, isr0x07
        .long    double_fault, isr0x08, overrun, isr0x09
        .long    invalid_tss, isr0x0a, seg_not_present, isr0x0b
        .long    stack_exception, isr0x0c, general_protection, isr0x0d
        .long    page_fault, isr0x0e, reversed, isr0x0f
        .long    coprocessor_error, isr0x10, reversed, isr0x11
        .long    reversed, isr0x12, reversed, isr0x13
        .long    reversed, isr0x14, reversed, isr0x15
        .long    reversed, isr0x16, reversed, isr0x17
        .long    reversed, isr0x18, reversed, isr0x19
        .long    reversed, isr0x1a, reversed, isr0x1b
        .long    reversed, isr0x1c, reversed, isr0x1d
        .long    reversed, isr0x1e, reversed, isr0x1f
        .long    do_timer, isr0x20      # <<<<<
添加的項 >>>>>>
        isrNoError        0x1b
        isrNoError        0x1c
        isrNoError        0x1d
        isrNoError        0x1e
        isrNoError        0x1f
        isrNoError        0x20          # <<<<<
添加的項 >>>>>>

 

05/timer/init.c

void
init(void) {
    char wheel[] = {'\\', '|', '/', '-'};
    int i = 0;

    idt_install();
    pic_install();
    timer_install(100);            //
每秒中100次時鐘中斷,linux是這樣的,windows200

    sti();                         // 不要忘了使能中斷哦

    for (;;) {        __asm__ ("movb    %%al,    0xb8000+160*24"::"a"(wheel[i]));
        if (i == sizeof wheel)
            i = 0;
        else
            ++i;
    }
}

 

我們還是使用以前的Makefile,當然需要加入新的模塊到 KERNEL_OBJS 中:
05/timer/Makefile

KERNEL_OBJS= load.o init.o isr.o timer.o libcc.o scr.o kprintf.o exceptions.o

運行make編譯一把,在讓vmware執行一下final.img,是不是很有成就感?

鍵盤

好啦,我們已經知道在屏幕上顯示一些東西了,現在學習按鍵處理,然后在顯示出來。

當一個鍵按下時,一個8位掃描碼會發送給計算機。例如,‘a’鍵按下后,掃描碼0x1e(取決于鍵盤布局,不要告訴我你用的日本鍵盤,鄙視一個)發送,當翻開按鍵時,掃描碼最高位置一并發送:0x1e | 0x80 = 0x9e。對于一些特殊按鍵,如breakhome鍵等,這里不做處理,有興趣的同學可以查找相關資料。一些可見按鍵對于本課來說已足夠。

下面是我使用的按鍵碼表,如果你確實用到了特殊鍵盤,最好找到對應的資料。

掃描碼

掃描碼

.

......

......

......

......

 

 

 

01

ESC

02

1!

03

2@

04

3#

05

4$

06

5%

07

6^

08

7&

09

8*

0A

9(

0B

0)

0C

-_

0D

=+

0E

<--

0F

TAB

10

qQ

11

wW

12

eE

13

rR

14

tT

15

yY

16

uU

17

iI

18

oO

19

pP

1A

[{

1B

]}

1C

Enter

1D

LCTL

1E

aA

1F

sS

20

dD

21

fF

22

gG

23

hH

24

jJ

25

kK

26

lL

27

;:

28

'"

29

`~

2A

LSHT

2B

\|

2C

zZ

2D

xX

2E

cC

2F

vV

30

bB

31

nN

32

mM

33

,<

34

.>

35

/?

36

RSHT

37

**

38

LALT

39

SPACE

3B-44

F1-F10

57

F11

58

F12

正如你看到的,ctrlshiftalt鍵以普通掃描碼發送,所以我們可以重新映射這些鍵以顯示到屏幕上。

訪問鍵盤控制器仍然經由端口:

05/keyboard/kb.c

void
do_kb(void) {
    int com;
    void (*key_way[0x80])(void) = {
        /*00*/unp, unp, pln, pln, pln, pln, pln, pln,
        /*08*/pln, pln, pln, pln, pln, pln, pln, pln,
        /*10*/pln, pln, pln, pln, pln, pln, pln, pln,
        /*18*/pln, pln, pln, pln, pln, ctl, pln, pln,
        /*20*/pln, pln, pln, pln, pln, pln, pln, pln,
        /*28*/pln, pln, shf, pln, pln, pln, pln, pln,
        /*30*/pln, pln, pln, pln, pln, pln, shf, pln,
        /*38*/alt, pln, unp, fun, fun, fun, fun, fun,
        /*40*/fun, fun, fun, fun, fun, unp, unp, unp,
        /*48*/unp, unp, unp, unp, unp, unp, unp, unp,
        /*50*/unp, unp, unp, unp, unp, unp, unp, fun,
        /*58*/fun, unp, unp, unp, unp, unp, unp, unp,
        /*60*/unp, unp, unp, unp, unp, unp, unp, unp,
        /*68*/unp, unp, unp, unp, unp, unp, unp, unp,
        /*70*/unp, unp, unp, unp, unp, unp, unp, unp,
        /*78*/unp, unp, unp, unp, unp, unp, unp, unp,
    };

上面是一堆函數指針,當獲取到掃描碼后,我們使用這個表找到相關的處理函數,進行相關的處理。unp是未定義的鍵,pln是可顯示字符,ctl是控制鍵ctrlshf是控制鍵shiftalt是控制鍵altfun函數用于F1F12

    com = 0;
    scan_code = inb(0x60);                //
80420x60端口獲取掃描碼

    (*key_way[scan_code&0x7f])();         // 0x7f是放開按鍵的掩碼


    /*
按鍵已處理 */
    outb((com=inb(0x61))|0x80, 0x61);     //
當我們從0x60端口讀完掃描碼后,這個掃描碼并不會自動刪除,

    outb(com&0x7f, 0x61);                 // 同時也阻止了我們讀下一系列按鍵,所以我們需要通知鍵盤控制器按鍵已處理,

                                          // 做法很簡單:只需要通過0x61端口的最高位disablere-enable鍵盤即可,

                                          //  7: 0=Enable keyboard; 1=Disable keyboard
    outb(0x20, 0x20);                     //
發送EOI:中斷處理已完成
}

static unsigned char shf_p = 0;           //
保存Ctrl, Shift  Alt鍵的狀態
static unsigned char ctl_p = 0;
static unsigned char alt_p = 0;
static unsigned char scan_code;           //
當前處理的掃描碼

/*
這個函數用于打印可打印字符 */
static void
pln(void) {
    static const char key_map[0x3a][2] = {
        /*00*/{0x0, 0x0}, {0x0, 0x0}, {'1', '!'}, {'2', '@'},
        /*04*/{'3', '#'}, {'4', '$'}, {'5', '%'}, {'6', '^'},
        /*08*/{'7', '&'}, {'8', '*'}, {'9', '('}, {'0', ')'},
        /*0c*/{'-', '_'}, {'=', '+'}, {'\b','\b'},{'\t','\t'},
        /*10*/{'q', 'Q'}, {'w', 'W'}, {'e', 'E'}, {'r', 'R'},
        /*14*/{'t', 'T'}, {'y', 'Y'}, {'u', 'U'}, {'i', 'I'},
        /*18*/{'o', 'O'}, {'p', 'P'}, {'[', '{'}, {']', '}'},
        /*1c*/{'\n','\n'},{0x0, 0x0}, {'a', 'A'}, {'s', 'S'},
        /*20*/{'d', 'D'}, {'f', 'F'}, {'g', 'G'}, {'h', 'H'},
        /*24*/{'j', 'J'}, {'k', 'K'}, {'l', 'L'}, {';', ':'},
        /*28*/{'\'','\"'},{'`', '~'}, {0x0, 0x0}, {'\\','|'},
        /*2c*/{'z', 'Z'}, {'x', 'X'}, {'c', 'C'}, {'v', 'V'},
        /*30*/{'b', 'B'}, {'n', 'N'}, {'m', 'M'}, {',', '<'},
        /*34*/{'.', '>'}, {'/', '?'}, {0x0, 0x0}, {'*', '*'},
        /*38*/{0x0, 0x0}, {' ', ' '} };

 

定義可打印字符碼表,鍵key_map[?][0]shift未按下的掃描碼對應的字符,

key_map[?][1]責對應按下shift的鍵碼。


    if (scan_code & 0x80)
        return;

    // 已經按下這個鍵了,那就什么也不做

    print_c(key_map[scan_code&0x7f][shf_p], WHITE, BLACK);    //
打印它:黑紙白字,清清楚楚
}

/* Ctrl
*/
static void
ctl(void) {
    ctl_p ^= 0x1;
}

/* Alt
*/
static void
alt(void) {
    alt_p
^= 0x1;
}

/* Shift
*/
static void
shf(void) {
    shf_p ^= 0x1;
}

/* F1, F2 ~ F12
*/
static void
fun(void) {
}

/*
暫不實現特殊鍵 */
static void
unp(void) {
}

 

當有shift鍵按下時,我們打印大寫字母。
void
kb_install(void) {
    outb(inb(0x21)&0xfd, 0x21);
}

 

我們幾乎實現完了,最后在中斷入口表中添加一項:
05/keyboard/isr.s

        .long    do_timer, isr0x20, do_kb, isr0x21  # 注意:加入了按鍵處理項
        isrNoError        0x20
        isrNoError        0x21      #
這里也加一個宏定義

05/keyboard/include/isr.h

#define VALID_ISR    (32+2)         # ISR個數再加1


05/keyboard/init.c

    timer_install(100);
    kb_install();      /*
安裝鍵盤處理 */
    sti();

 

MakefileKERNEL_OBJS 加入新的模塊:

05/keyboard/MakefileKERNEL_OBJS= load.o init.o isr.o timer.o libcc.o scr.o kprintf.o exceptions.o kb.o

 

運行make編譯一把,再用vmware執行,看看是不是可以處理按鍵了,退格鍵也可以了。

你甚至可以再上面寫一個hello, world,只是不能編譯:)

 

 

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美三级韩国三级日本三斤| 久久国产综合精品| 欧美久色视频| 一区二区av| 亚洲一区二区免费| 国产一区二区中文字幕免费看| 欧美资源在线| 久久在线视频在线| 一本在线高清不卡dvd| 亚洲一区视频在线| 黄色一区二区三区| 亚洲七七久久综合桃花剧情介绍| 欧美日韩国产精品一卡| 欧美一区二区三区啪啪| 久久性天堂网| 亚洲午夜精品久久| 久久本道综合色狠狠五月| 91久久在线播放| 中文av字幕一区| 在线观看视频一区二区| 亚洲美女av网站| 国内久久精品视频| 亚洲人成网站在线播| 国产免费一区二区三区香蕉精| 久久人人爽国产| 欧美人体xx| 久久综合国产精品| 国产精品xvideos88| 免费一级欧美片在线播放| 欧美精品一区二区在线播放| 久久久久久有精品国产| 欧美日韩免费区域视频在线观看| 久久夜色精品国产| 国产精品久久久久毛片软件| 亚洲第一精品夜夜躁人人爽| 国产女人水真多18毛片18精品视频| 免费成人你懂的| 国产日韩精品一区二区三区在线 | 亚洲三级电影在线观看| 性伦欧美刺激片在线观看| 夜夜嗨av一区二区三区网站四季av| 欧美在线看片a免费观看| 一个人看的www久久| 美女视频黄a大片欧美| 欧美在线观看视频在线| 欧美日韩精品在线| 亚洲二区视频| 亚洲盗摄视频| 欧美一区精品| 性欧美办公室18xxxxhd| 欧美午夜电影网| 亚洲美女区一区| 99v久久综合狠狠综合久久| 久久视频国产精品免费视频在线| 久久成人av少妇免费| 国产精品免费一区豆花| 一区二区三区欧美日韩| 一本色道久久综合一区| 欧美日本不卡| 久久精品女人的天堂av| 亚洲影院免费观看| 欧美三区视频| 99riav久久精品riav| 一本高清dvd不卡在线观看| 蜜桃久久精品乱码一区二区| 欧美不卡激情三级在线观看| 好看的日韩视频| 久久久久国产一区二区三区| 久久综合99re88久久爱| 在线日韩av片| 欧美国产日韩一区二区三区| 亚洲丁香婷深爱综合| 亚洲精品一品区二品区三品区| 欧美r片在线| 亚洲精品日韩在线| 亚洲亚洲精品在线观看| 国产精品免费小视频| 欧美一级大片在线观看| 麻豆av福利av久久av| 亚洲精品国产无天堂网2021| 欧美—级高清免费播放| 一区二区三区免费在线观看| 欧美一区二区在线免费观看| 黄色成人免费观看| 欧美va亚洲va国产综合| 99综合精品| 欧美一区二区女人| 激情懂色av一区av二区av| 欧美ed2k| 亚洲欧美福利一区二区| 欧美国产日韩在线观看| 亚洲欧美日韩精品久久久| 国产日韩专区| 欧美激情成人在线视频| 亚洲免费在线播放| 欧美va亚洲va日韩∨a综合色| 99热这里只有成人精品国产| 国产精品视频男人的天堂| 久久综合九色欧美综合狠狠| 日韩亚洲不卡在线| 久久综合狠狠| 亚洲在线观看免费视频| 亚洲成色999久久网站| 欧美日韩视频在线第一区| 久久国产99| 亚洲视频免费| 亚洲电影专区| 久久综合999| 香蕉久久夜色精品国产使用方法| 亚洲成人资源网| 国产欧美日韩视频在线观看| 欧美人成免费网站| 久久久久综合一区二区三区| 亚洲婷婷国产精品电影人久久| 欧美成人免费网| 久久久久久久欧美精品| 亚洲一二区在线| 亚洲伦理一区| 黄色在线一区| 国产人久久人人人人爽| 欧美视频在线观看免费| 欧美第一黄网免费网站| 久久夜色精品一区| 久久都是精品| 欧美专区在线观看一区| 亚洲综合精品一区二区| 一区二区电影免费观看| 亚洲精品国精品久久99热一| 欧美激情网友自拍| 麻豆久久久9性大片| 久久久噜噜噜久久中文字幕色伊伊| 亚洲一区二区三区免费视频| 日韩一级片网址| 亚洲精品久久久久久下一站| 欧美成熟视频| 欧美jizzhd精品欧美喷水| 老司机成人在线视频| 久久久久久穴| 欧美亚洲一级| 欧美在线看片| 久久久久在线观看| 久久中文在线| 蜜臀a∨国产成人精品| 欧美不卡视频一区| 最新日韩av| 日韩性生活视频| 亚洲一区日韩在线| 羞羞答答国产精品www一本| 欧美一区二区大片| 欧美中文在线观看| 久久久伊人欧美| 免费永久网站黄欧美| 女主播福利一区| 欧美日韩亚洲综合| 国产精品国产精品国产专区不蜜| 国产精品久久一区主播| 国产一区二区av| 国内精品免费在线观看| 亚洲国产精品成人久久综合一区| 亚洲全黄一级网站| 中文网丁香综合网| 久久精品卡一| 欧美激情精品久久久久久免费印度 | 最新中文字幕一区二区三区| 亚洲免费观看视频| 亚洲男人的天堂在线观看 | 亚洲欧洲视频在线| 中文欧美日韩| 久久久噜噜噜久久中文字免| 亚洲国产欧美精品| 亚洲一区二区视频在线| 久久人人爽人人| 国产精品爱啪在线线免费观看| 国产欧美亚洲精品| 亚洲精品一二区| 久久久久久久久久久一区| 亚洲黄色免费网站| 午夜精品av| 欧美激情a∨在线视频播放| 国产欧美日韩伦理| 亚洲精品一区二区三| 久久不射2019中文字幕| 亚洲人成网站999久久久综合| 9l国产精品久久久久麻豆| 久久久久久免费| 国产精品草莓在线免费观看| 在线观看日韩专区| 性一交一乱一区二区洋洋av| 欧美国产欧美亚洲国产日韩mv天天看完整 | 欧美精品久久久久久久久久| 国产美女精品免费电影| 亚洲精品日韩精品| 久久青草福利网站| 一区二区三区精品视频| 免费看亚洲片| 国产真实久久| 欧美一区二区私人影院日本| 亚洲九九精品| 免费欧美视频| 狠狠色丁香久久婷婷综合丁香|