• <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>

            luqingfei@C++

            為中華之崛起而崛起!
            兼聽(tīng)則明,偏聽(tīng)則暗。

            匯編語(yǔ)言--使用BIOS進(jìn)行鍵盤輸入和磁盤讀寫(xiě)

             

            使用BIOS進(jìn)行鍵盤輸入和磁盤讀寫(xiě)

             

            大多數(shù)有用的程序都需要處理用戶的輸入,鍵盤輸入是最基本的輸入。程序和數(shù)據(jù)通常需要長(zhǎng)期存儲(chǔ),磁盤是最常用的存儲(chǔ)設(shè)備。

            BIOS為這兩種外設(shè)的I/O提供了最基本的中斷例程。下面將對(duì)它們的應(yīng)用和相關(guān)問(wèn)題進(jìn)行學(xué)習(xí)。

             

            int 9中斷例程對(duì)鍵盤輸入的處理

            鍵盤輸入將引發(fā)9號(hào)中斷,BIOS提供了int 9中斷例程。

            CPU9號(hào)中斷發(fā)生后,執(zhí)行int 9中斷例程,從60h端口讀出掃描碼,并將其轉(zhuǎn)化為相應(yīng)的ASCII碼或狀態(tài)信息,存儲(chǔ)在內(nèi)存的指定空間(鍵盤緩沖區(qū)或狀態(tài)字節(jié))中。

             

            一般的鍵盤輸入,在CPU執(zhí)行完int 9中斷例程后,都放到了鍵盤緩沖區(qū)中。鍵盤緩沖區(qū)有16個(gè)字單元,可以存儲(chǔ)15個(gè)按鍵的掃描碼和對(duì)應(yīng)的ASCII碼。

             

            下面我們按照鍵盤緩沖區(qū)的邏輯結(jié)構(gòu),來(lái)看一下鍵盤輸入的掃描碼和對(duì)應(yīng)的ASCII碼是如何寫(xiě)入鍵盤緩沖區(qū)的。

             

            注意:在我們的課程中,僅在邏輯結(jié)構(gòu)的基礎(chǔ)上,討論BIOS鍵盤緩沖區(qū)的讀寫(xiě)問(wèn)題。其實(shí)鍵盤緩沖區(qū)是用環(huán)形隊(duì)列結(jié)構(gòu)管理的內(nèi)存區(qū),但我們不對(duì)隊(duì)列和環(huán)形隊(duì)列的實(shí)現(xiàn)進(jìn)行討論,因?yàn)槟鞘橇硪婚T專業(yè)課《數(shù)據(jù)結(jié)構(gòu)》的內(nèi)容。

             

            下面,我們通過(guò)下面幾個(gè)鍵:

            ABCDEshift_AA

            的輸入過(guò)程,簡(jiǎn)要地看一下int 9中斷例程對(duì)鍵盤輸入的處理方法:

            1)初始狀態(tài)下,沒(méi)有鍵盤輸入,鍵盤緩沖區(qū)空,此時(shí)沒(méi)有任何元素:

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

            2)按下A鍵,引發(fā)鍵盤中斷:CPU執(zhí)行int 9中斷例程,從60h端口讀出A鍵的通碼;然后檢測(cè)狀態(tài)字節(jié),看看是否有shiftCtrl等切換鍵按下;發(fā)現(xiàn)沒(méi)有切換鍵按下,則將A鍵的掃描碼1eh和對(duì)應(yīng)的ASCII碼,即字母“a”的ASCII61h,寫(xiě)入鍵盤緩沖區(qū)。緩沖區(qū)的字單元中,高位字節(jié)存儲(chǔ)掃描碼,低位字節(jié)存儲(chǔ)ASCII碼。此時(shí)緩沖區(qū)中的內(nèi)容如下:

            1E61

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

            3)按下B鍵,引發(fā)鍵盤中斷:CPU執(zhí)行int 9中斷例程,從60h端口讀出B鍵的通碼;然后檢測(cè)狀態(tài)字節(jié),看看是否有切換鍵按下;發(fā)現(xiàn)沒(méi)有切換鍵按下,將B鍵的掃描碼30h和對(duì)應(yīng)的ASCII碼,即字母“b”的ASCII62h,寫(xiě)入鍵盤緩沖區(qū)。此時(shí)緩沖區(qū)中的內(nèi)容如下:

            1E61

            3062

             

             

             

             

             

             

             

             

             

             

             

             

             

             

            4)按下CDE鍵后,緩沖區(qū)中的內(nèi)容如下:

            1E61

            2062

            2E63

            2064

            1265

             

             

             

             

             

             

             

             

             

             

             

            5)按下左shift鍵,引發(fā)鍵盤中斷:int 9中斷例程接收左shift鍵的通碼,設(shè)置0040:17處的狀態(tài)字節(jié)的第1位為1,表示左shift鍵按下。

            6)按下A鍵,引發(fā)鍵盤中斷:CPU執(zhí)行int 9中斷例程;從60h端口讀出A鍵的通碼;檢測(cè)狀態(tài)字節(jié),看看是否有切換鍵按下,發(fā)現(xiàn)左shift鍵被按下,則將A鍵的掃描碼1Ehshift_A對(duì)應(yīng)的ASCCII碼,即字母“A”的ASCII41,寫(xiě)入鍵盤緩沖區(qū),此時(shí)緩沖區(qū)中的內(nèi)容如下:

            1E61

            2062

            2E63

            2064

            1265

            1E41

             

             

             

             

             

             

             

             

             

             

            7)松開(kāi)左shift鍵,引發(fā)鍵盤中斷:int 9中斷例程接收左shift鍵的斷碼,設(shè)置0040:17處的狀態(tài)字節(jié)的第1位為0,表示左shift鍵松開(kāi)。

            8)按下A鍵,引發(fā)鍵盤中斷:CPU執(zhí)行int 9中斷例程,從60h端口讀出A鍵的通碼,然后檢測(cè)狀態(tài)字節(jié),看看是否有切換鍵按下,發(fā)現(xiàn)沒(méi)有切換鍵按下,則將A鍵的掃描碼1EhA對(duì)應(yīng)的ASCCII碼,即字母“a”的ASCII61h,寫(xiě)入鍵盤緩沖區(qū),此時(shí)緩沖區(qū)中的內(nèi)容如下:

            1E61

            2062

            2E63

            2064

            1265

            1E41

            1E61

             

             

             

             

             

             

             

             

             

             

             

             

            使用int 16h中斷例程讀取鍵盤緩沖區(qū)

            BIOS提供了int 16h中斷例程供程序員調(diào)用。int 16h中斷例程中包含的一個(gè)最重要的功能是從鍵盤緩沖區(qū)中讀取一個(gè)鍵盤輸入,該功能的編號(hào)為0

            下面的指令從鍵盤緩沖區(qū)中讀取一個(gè)鍵盤輸入,并將其從緩沖區(qū)中刪除

            mov ah,0

            int 16h

            結(jié)果:(ah)=掃描碼,(al)=ASCII碼。

             

            int 16h中斷例程的0號(hào)功能,進(jìn)行如下的工作:

            1)檢測(cè)鍵盤緩沖區(qū)中是否有數(shù)據(jù);

            2)沒(méi)有則繼續(xù)做第1步;

            3)讀取緩沖區(qū)第一個(gè)字單元中的鍵盤輸入;

            4)將讀取的掃描碼送入ahASCII碼送入al

            5)將已讀取的鍵盤輸入從緩沖區(qū)中刪除。

             

            可見(jiàn),BIOSint 9中斷例程和int 16h中斷例程是一對(duì)相互配合的程序,int 9中斷例程向鍵盤緩沖區(qū)中寫(xiě)入,int 16h中斷例程從緩沖區(qū)中讀出。

            它們寫(xiě)入和讀出的時(shí)機(jī)不同,int 9中斷例程是在有按鍵按下的時(shí)候向鍵盤緩沖區(qū)中寫(xiě)入數(shù)據(jù);而int 16h中斷例程是在應(yīng)用程序?qū)ζ溥M(jìn)行調(diào)用的時(shí)候,將數(shù)據(jù)從鍵盤緩沖區(qū)中讀出。

             

            我們?cè)诰帉?xiě)一般的處理鍵盤輸入的程序的時(shí)候,可以調(diào)用int 16h從鍵盤緩沖區(qū)中讀取鍵盤的輸入。

             

            編程,接收用戶的鍵盤輸入,輸入“r”,將屏幕上的字符設(shè)置為紅色;輸入“g”,將屏幕上的字符設(shè)置為綠色;輸入“b”,將屏幕上的字符設(shè)置為藍(lán)色。

             

            程序如下:

            assume cs:code

            code segment

             start:mov ah,0

                    int 16h

                   

                    mov ah,1

                    cmp al,'r'

                    je red

                    cmp al,'g'

                    je green

                    cmp al,'b'

                    je blue

                    jmp short sret

                   

                red:shl ah,1

             green:shl ah,1

               blue:mov bx,0b800h

                    mov es,bx

                    mov cx,2000

                  s:add byte ptr es:[bx],11111000b

                    or es:[bx],ah

                    add bx,2

                    loop s

                   

               sret:mov ax,4c00h

                    int 21h

                   

            code ends

            end start

             

             

             

            字符串的輸入

            用戶通過(guò)鍵盤輸入的通常不僅僅是單個(gè)字符而是字符串。

            最基本的字符串輸入程序,需要具備下面的功能:

            1)在輸入的同時(shí)需要顯示這個(gè)字符串;

            2)一般在輸入回車符后,字符串輸入結(jié)束;

            3)能夠刪除已經(jīng)輸入的字符。

             

            編寫(xiě)一個(gè)接收字符串的輸入子程序,實(shí)現(xiàn)上面三個(gè)基本功能。

            子程序的參數(shù)如下:

            (dh)(dl)=字符串在屏幕上顯示的行、列位置;

            ds:si指向字符串的存儲(chǔ)空間,字符串以0為結(jié)尾符。

             

            分析:

            1)字符的輸入和刪除。

                   每個(gè)新輸入的字符都存儲(chǔ)在前一個(gè)輸入的字符之后,而刪除是從最后面的字符進(jìn)行的。

                   看下面的過(guò)程:

                   空字符串:

                   輸入“a”:a

                   輸入“b”:ab

                   輸入“c”:abc

                   輸入“d”:abcd

                   刪除一個(gè)字符:abc

                   刪除一個(gè)字符:ab

                   刪除一個(gè)字符:a

                   刪除一個(gè)字符:

             

                   可以看出在字符串輸入的過(guò)程中,字符的輸入和輸出是按照棧的訪問(wèn)規(guī)則進(jìn)行了的,即后進(jìn)先出。這樣,我們就可以用棧的方式來(lái)管理字符串的存儲(chǔ)空間,也就是說(shuō),字符串的存儲(chǔ)空間實(shí)際上是一個(gè)字符棧。字符棧中的所有字符,從棧底到棧頂,組成一個(gè)字符串。

             

            2)在輸入回車符后,字符串輸入結(jié)束。

                   輸入回車符后,可以在字符串中加入0,表示字符串結(jié)束。

             

            3)在輸入的同時(shí)需要顯示這個(gè)字符串。

                   每次有新的字符輸入和刪除一個(gè)字符的時(shí)候,都應(yīng)該重新顯示字符串,即從字符棧的棧底到棧頂,顯示所有的字符。

             

            4)程序的處理過(guò)程。

                   1)調(diào)用int 16h讀取鍵盤輸入;

                   2)如果是字符,進(jìn)入字符棧,顯示字符棧中的所有字符;繼續(xù)執(zhí)行1

                   3)如果是退格鍵,從字符棧中彈出一個(gè)字符,顯示字符棧中的所有字符;繼續(xù)執(zhí)行1

                   4)如果是Enter鍵,向字符棧中壓入0,返回。

             

                   從程序的處理過(guò)程中可以看出,字符棧的入棧、出棧和顯示棧中的內(nèi)容,是需要在多處使用的功能,應(yīng)該將它們寫(xiě)為子程序。

                   子程序:字符棧的入棧、出棧和顯示。

                   參數(shù)說(shuō)明:(ah)=功能號(hào),0表示入棧,1表示出棧,2表示顯示;

                                        ds:si指向字符棧空間;

                                        對(duì)于0號(hào)功能:(al)=入棧字符;

                                        對(duì)于1號(hào)功能:(al)=返回字符;

                                        對(duì)于2號(hào)功能:(dh)(dl)=字符串在屏幕上顯示的行、列位置。

             

            charstack:       jmp short charstart

                   table dw charpush,charpop,charshow

                   top dw 0             ;棧頂

             

             charstart:    push bx

                                 push dx

                                 push di

                                 push es

             

                                 cmp ah,2

                                 ja sret

                                 mov bl,ah

                                 mov bh,0

                                 add bx,bx

                                 jmp word ptr table[bx]

             

             charpush:    mov bx,top

                                 mov [si][bx],al

                                 inc top

                                 jmp sret

             

             charpop:     cmp top,0

                                 je sret

                                 dec top

                                 mov bx,top

                                 mov al,[si][bx]

                                 jmp sret

             

             charshow:   mov bx,0b800b

                                 mov es,bx

                                 mov al,160

                                 mov ah,0

                                 mul dh

                                 mov di,ax

                                 add dl,dl

                                 mov dh,0

                                 add di,dx

             

                                 mov bx,0

             

             charshows: cmp bx,top

                                 jne noempty

                                 mov byte ptr es:[dl],’ ‘

                                 jmp sret

             noempty:     mov al,[si][bx]

                                 mov es:[di],al

                                 mov byte ptr es:[di+2], ‘ ‘

                                 inc bx

                                 add di,2

                                 jmp charshows

            sret:        pop es

                          pop di

                          pop dx

                          pop bx

                          ret

             

            顯示棧中字符的時(shí)候,要注意清除屏幕上上一次顯示的內(nèi)容。

             

            完整的接收字符串輸入的子程序:

            getstr:     push ax

            getstrs:    mov ah,0

                          int 16h

             

                          cmp al,20h

                          jb nochar               ;ASCII碼小于0,說(shuō)明不是字符

                          mov ah,0

                          call charstack         ;字符入棧

                          mov ah,2

                          call charstack         ;顯示棧中的字符

                          jmp getstrs

             nochar:cmp ah,0eh            ;退格鍵的掃描碼

                          je backspace

                          cmp ah,1ch           ;回車鍵的掃描碼

                          je enter

                          jmp getstrs

            backspace:mov ah,1

                          call charstack         ;字符出棧

                          mov ah,2

                          call charstack         ;顯示棧中的字符

                          jmp getstrs

             enter:     mov al,0

                          mov ah,0

                          call charstack         ;0入棧

                          mov ah,2

                          call charstack               ;顯示棧中的字符

                          pop ax

                          ret

             

             

             

             

            應(yīng)用int 13h中斷例程對(duì)磁盤進(jìn)行讀寫(xiě)

            BIOS提供的訪問(wèn)磁盤的中斷例程為int 13h

             

            入口參數(shù):

            (ah)=int 13h的功能號(hào)(2表示讀扇區(qū)、3表示寫(xiě)扇區(qū))

            (al)=讀取的扇區(qū)數(shù)/寫(xiě)入的扇區(qū)數(shù)

            (ch)=磁道號(hào)

            (cl)=扇區(qū)號(hào)

            (dh)=磁頭號(hào)(對(duì)于軟盤即面號(hào),因?yàn)橐粋€(gè)面用一個(gè)磁頭來(lái)讀寫(xiě)。)

            (dl)=驅(qū)動(dòng)器號(hào)       軟驅(qū)從0開(kāi)始,0:軟驅(qū)A1:軟驅(qū)B

                                        硬盤從80h開(kāi)始,80h:硬盤C81h:硬盤D

            es:bx指向接收從扇區(qū)讀入數(shù)據(jù)的內(nèi)存區(qū)/將寫(xiě)入磁盤的數(shù)據(jù)

             

            返回參數(shù):

            操作成功:(ah)=0(al)=讀入的扇區(qū)數(shù)/寫(xiě)入的扇區(qū)數(shù)

            操作失敗:(ah)=出錯(cuò)代碼

             

            以下指令,讀取001扇區(qū)的內(nèi)容到內(nèi)存單元0:200

            mov ax,0

            mov es,ax

            mov bx,200h

             

            mov al,1

            mov ch,0

            mov cl,1

            mov dl,0

            mov dh,0

            mov ah,2

            int 13h

             

            以下指令,將0:200中的內(nèi)容寫(xiě)入001扇區(qū):

            mov ax,0

            mov es,ax

            mov bx,200h

             

            mov al,1

            mov ch,0

            mov cl,1

            mov dl,0

            mov dh,0

            mov ah,3

            int 13h

             

             

             

             

            PC機(jī)是如何進(jìn)入操作系統(tǒng)的?

            開(kāi)機(jī)后,CPU自動(dòng)進(jìn)入到FFFF:0單元處執(zhí)行,此處有一條轉(zhuǎn)跳指令。CPU執(zhí)行該指令后,轉(zhuǎn)去執(zhí)行BIOS中的硬件系統(tǒng)檢測(cè)和初始化程序。

             

            初始化程序?qū)⒔?/span>BIOS所支持的中斷向量,即將BIOS提供的中斷例程的入口地址登記在中斷向量表中。

             

            硬件系統(tǒng)檢測(cè)和初始化完成后,調(diào)用int 19h進(jìn)行操作系統(tǒng)的引導(dǎo)。

            如果設(shè)為從軟盤啟動(dòng)操作系統(tǒng),則int 19h將主要完成以下工作:

            1)控制0號(hào)軟驅(qū),讀取軟盤001扇區(qū)的內(nèi)容到0:7c00

            2)將CS:IP指向0:7c00

             

            軟盤的001扇區(qū)中裝有操作系統(tǒng)引導(dǎo)程序。int 19h將其裝到0:7c00處后,設(shè)置CPU0:7c00開(kāi)始執(zhí)行此處的引導(dǎo)程序,操作系統(tǒng)被激活,控制計(jì)算機(jī)。

             

             

             

            posted on 2010-08-04 16:50 luqingfei 閱讀(5098) 評(píng)論(1)  編輯 收藏 引用 所屬分類: 匯編語(yǔ)言基礎(chǔ)學(xué)習(xí)

            評(píng)論

            # re: 匯編語(yǔ)言--使用BIOS進(jìn)行鍵盤輸入和磁盤讀寫(xiě) 2011-06-13 19:22 abcgril

            您好:
            最近在寫(xiě)一個(gè)terminate and stay resident程式
            從鍵盤接收"*"(shift+8)
            然後會(huì)顯示一段字串,如ABCD
            但按其他鍵如"8"卻沒(méi)有反應(yīng)

            我已經(jīng)寫(xiě)出大部分
            可以傳給你看看
            目前程式是輸入"*"和"8"都會(huì)顯示一段ABCD
            所以還沒(méi)完成!
            希望您可以幫忙
            或是教我怎樣寫(xiě)
            不知道要怎樣改了
            謝謝  回復(fù)  更多評(píng)論   

            導(dǎo)航

            <2010年9月>
            2930311234
            567891011
            12131415161718
            19202122232425
            262728293012
            3456789

            統(tǒng)計(jì)

            留言簿(6)

            隨筆分類(109)

            隨筆檔案(105)

            Blogers

            Game

            Life

            NodeJs

            Python

            Useful Webs

            大牛

            搜索

            積分與排名

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            国产情侣久久久久aⅴ免费| 精品午夜久久福利大片| AA级片免费看视频久久| 久久久精品国产sm调教网站| 日产久久强奸免费的看| 91久久精品国产91性色也| 久久久久99精品成人片直播| 色综合久久久久综合体桃花网| 97视频久久久| 久久久噜噜噜久久中文字幕色伊伊 | 欧美久久综合九色综合| 国产精品女同一区二区久久| 狠狠久久综合伊人不卡| 国产高潮久久免费观看| 久久久精品人妻无码专区不卡| 九九久久精品国产| 精品水蜜桃久久久久久久| 久久精品亚洲福利| 日韩十八禁一区二区久久| 久久久黄色大片| 午夜天堂av天堂久久久| 国产亚洲综合久久系列| 97久久精品人妻人人搡人人玩| 国产V综合V亚洲欧美久久| 女人香蕉久久**毛片精品| 国内精品欧美久久精品| 色偷偷88欧美精品久久久| 久久亚洲日韩看片无码| 久久99国产精品尤物| 久久久国产精品网站| 久久伊人五月天论坛| 久久成人小视频| 久久96国产精品久久久| 精品一久久香蕉国产线看播放| 久久久久久久久66精品片| 色偷偷88888欧美精品久久久| 成人久久精品一区二区三区| 久久伊人精品青青草原日本| 亚洲午夜久久久久久久久电影网| 久久青青草原精品影院| 久久无码专区国产精品发布|