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

            無(wú)我

            讓內(nèi)心永遠(yuǎn)燃燒著偉大的光明的精神之火!
            靈活的思考,嚴(yán)謹(jǐn)?shù)膶?shí)現(xiàn)
            豪邁的氣魄、頑強(qiáng)的意志和周全的思考

            [轉(zhuǎn)]匯編語(yǔ)言課程設(shè)計(jì)——調(diào)試并修改一個(gè)小的內(nèi)存駐留程序(http://www.4ngel.net/article/31.htm)

            匯編語(yǔ)言課程設(shè)計(jì)——調(diào)試并修改一個(gè)小的內(nèi)存駐留程序
            本文作者:Kasi
            文章性質(zhì):原創(chuàng)
            發(fā)布日期:2004-07-16

            2004.4.18

            一、課程設(shè)計(jì)之目的

              學(xué)習(xí)DOS下內(nèi)存駐留程序的基本思想,了解與熟悉用匯編語(yǔ)言編寫(xiě)程序。本課程設(shè)計(jì)將完成一個(gè)小的.com程序,運(yùn)行程序后,你的所有按鍵輸入(指在DOS或Windows的DOS模式下)將不被接受,所有輸入將被替換成特定的字符串(回車(chē)鍵除外)。

            二、內(nèi)存駐留程序的基本框架(framework of a TSR)

              內(nèi)存駐留程序的基本思想就是讓程序一直停留在內(nèi)存中,不斷的執(zhí)行特定的命令。但內(nèi)存駐留如何被執(zhí)行呢?一般地,內(nèi)存駐留程序都是通過(guò)修改BIOS或DOS的系統(tǒng)中斷向量表來(lái)實(shí)現(xiàn)的。比如修改向量表中16H位置的中斷(這個(gè)中斷接收鍵盤(pán)的按鍵,在DOS中,按鍵按下,這個(gè)中斷就會(huì)被調(diào)用),讓其指向我的程序,這時(shí)若有按鍵被按下,則執(zhí)行的是我的程序。下面是一個(gè)最簡(jiǎn)單的框架:

            CSEG SEGMENT
              ASSUME   CS:CSEG, DS:CSEG
              ORG    100H
            Start:
              JMP    Initialize

            new_keyboard_io PROC FAR // 這一部分是駐留在內(nèi)存的內(nèi)容
              STI
              NOP
              IRET
            new_keyboard_io ENDP // 到這里結(jié)束

            Initialize:
              MOV DX, OFFSET new_keyboard_io // 新的鍵盤(pán)處理程序
              MOV AL, 16H // 需更改的向量號(hào)(interrupt index)
              MOV AH, 25H // 更改系統(tǒng)中斷向量表
              INT 21H

            MOV DX, OFFSET Initialize
              INT 27H // 將標(biāo)簽Initialize前的程序駐留內(nèi)存

            CSEG ENDS
              END Start

            三、實(shí)現(xiàn)原來(lái)設(shè)計(jì)程序

            首先,我需要還是需要捕獲用戶(hù)的回車(chē)鍵,所以需要將原來(lái)的DOS本身的鍵盤(pán)處理程序保留起來(lái)。下面的代碼:

            old_keyboard_io DD ?
            ……
            Initialize:
            ……
              MOV AL, 16H          ; Interrupt index in vector table
              MOV AH, 35H          ; Get the interrupt dealing
              INT 21H            ; program's pointer
              MOV old_keyboard_io, BX    ; offset
              MOV old_keyboard_io[2], ES   ; base address
            ……

              old_keyboard_io用來(lái)儲(chǔ)存原鍵盤(pán)處理程序的指針,其中INT 21H – AH=35H,是獲得其指針,返回值在ES:BX中。ES是指針的基地址,BX是偏移量。

              其次,就是實(shí)現(xiàn)我原來(lái)設(shè)計(jì)的功能,截獲按鍵信息,并改為特定的字符串。下面的實(shí)現(xiàn)的代碼:

            ……
            Hello_Msg DB 'Kasi, haha!'    ; string to display when catch a key-press
            Msg_Index DW 0          ; which char in the string been displayed(char index)
            ……
            new_keyboard_io PROC FAR
              ASSUME CS:CSEG, DS:CSEG
                STI

                CMP AH, 00H        ; INT 16H - AH = 0 to catch
                JE new_io_0        ; key-press func
                ASSUME DS:nothing
                JMP old_keyboard_io    ; No catch, jump to old handler
            new_io_0:
                PUSHF
              ASSUME DS:nothing
                CALL old_keyboard_io
                CMP AL, 0DH        ; Is a ENTER been pressed ?
                JNE new_io_1       ; no, output string 'Kasi, haha!'
                MOV Msg_Index, 0     ; yes, reset the string index
                JMP new_io_done      ; and return
            new_io_1:
                PUSH SI
                MOV SI, Msg_Index     ; Get current char index
                MOV AL, Hello_Msg[SI]   ; Get current char

                INC SI          ; Next char in the Hello_Msg
                CMP SI, 11        ; Reach the end of the Hello_Msg ?
                JNE new_io_2       ; no, jump
                MOV SI, 0         ; yes, set the char index to the beginning
            new_io_2:
                MOV Msg_Index, SI     ; Save the char index
                POP SI
            new_io_done:
                IRET
            new_keyboard_io ENDP
            ……

              下面的分段說(shuō)明:

                CMP AH, 00H        ; INT 16H - AH = 0 to catch
                JE new_io_0        ; key-press func
                ASSUME DS:nothing
                JMP old_keyboard_io    ; No catch, jump to old handler

              這一段代碼是根據(jù)書(shū)上抄下來(lái)的,先檢測(cè)AH中是否為0(INT 21H - AH=0表示用戶(hù)按下鍵盤(pán)),不為0就進(jìn)入old_keyboard_io,由系統(tǒng)原來(lái)的處理程序去處理用戶(hù)的請(qǐng)求。這里”ASSUME DS:nothing”是告訴編譯器忽略DS的內(nèi)容,這樣才能正確跳轉(zhuǎn)。

            new_io_0:
                PUSHF
              ASSUME DS:nothing
                CALL old_keyboard_io
                CMP AL, 0DH        ; Is a ENTER been pressed ?
                JNE new_io_1       ; no, output string 'Kasi, haha!'
                MOV Msg_Index, 0     ; yes, reset the string index
                JMP new_io_done      ; and return

              如果是有按鍵被按下,則先檢測(cè)按鍵是否為回車(chē)鍵(0DH),如果不是則跳轉(zhuǎn)到new_io_1去處理,否則將字符串的索引置0(Msg_Inedx = 0)并結(jié)束程序。

            new_io_1:
                PUSH SI
                MOV SI, Msg_Index     ; Get current char index
                MOV AL, Hello_Msg[SI]   ; Get current char

                INC SI          ; Next char in the Hello_Msg
                CMP SI, 11        ; Reach the end of the Hello_Msg ?
                JNE new_io_2       ; no, jump
                MOV SI, 0         ; yes, set the char index to the beginning
            new_io_2:
                MOV Msg_Index, SI     ; Save the char index
                POP SI

              若用戶(hù)按下的不是回車(chē)鍵,將Hello_Msg[Msg_Index]這個(gè)字符放入AL中(因?yàn)锳L是INT 21H – AH=16H調(diào)用的返回值)并讓Msg_Index的值加1,然后判斷Msg_Index是否指向Hello_Msg的尾部了,是的話將Msg_Index置0。
              這樣,就完成了整個(gè)程序。

            四、調(diào)試程序

              程序?qū)懞昧耍?dāng)然就要編譯和運(yùn)行。編譯通過(guò),但程序運(yùn)行后卻沒(méi)有任何效果。
              按理說(shuō),程序應(yīng)該是沒(méi)有問(wèn)題的,但為何沒(méi)有任何效果呢?我懷疑new_keyboard_io是不是沒(méi)其作用,如何檢查錯(cuò)誤呢?用debug一步步跟蹤顯然不明智,于是我在這里加了一個(gè)斷點(diǎn):

            new_keyboard_io PROC FAR
              ASSUME CS:CSEG, DS:CSEG
                STI
                  INT 03H        ; break point
                CMP AH, 00H        ; INT 16H - AH = 0 to catch

              編譯運(yùn)行,并在debug用a命令寫(xiě)入

            mov ah, 10
            mov al, 00
            int 21

              手動(dòng)調(diào)用INT 21H – AH=16H,希望能在程序中停住,看new_keyboard_io是否被執(zhí)行了。但我在debug中一t(trace),整個(gè)debug就出問(wèn)題了,原因不明,看來(lái)不能用這種方法試驗(yàn)。
              那我就換一個(gè)方法,用一個(gè)沒(méi)有任何命令的new_keyboard_io作測(cè)試,代碼如下:

            CSEG SEGMENT
              ASSUME CS:CSEG, DS:CSEG
              ORG 100H
            Start:
              JMP Initialize
            new_keyboard_io PROC FAR
              ASSUME CS:CSEG, DS:CSEG
                STI
                  NOP
                IRET
            new_keyboard_io ENDP
            Initialize:
              ASSUME CS:CSEG, DS:CSEG
                MOV DX, OFFSET new_keyboard_io
                MOV AL, 16H
                MOV AH, 25H
                INT 21H

                MOV DX, OFFSET Initialize
                INT 27H

            CSEG ENDS
              END Start

              編譯運(yùn)行之后,任何按鍵輸入都不起作用了,看來(lái)new_keyboard_io還是被執(zhí)行了的,那問(wèn)題就出現(xiàn)在我寫(xiě)的new_keyboard_io的代碼里面了。我查了查書(shū),INT 21H – AH=00H是接受按鍵消息的啊。但我還發(fā)現(xiàn)了一個(gè)INT 21H – AH=10H也是接受鍵盤(pán)消息的,會(huì)不會(huì)DOS在提示符(c:\>)下用的是AH=10H呢?我馬上在原程序中加了一下代碼:

            ……
                CMP AH, 00H        ; INT 16H - AH = 0 to catch
                JE new_io_0        ; key-press func
            ;-------------------------------
            ; In the DOS prompt(C:>), DOS uses
            ; INT 16H - AH = 10H to get a char, not
            ; AH = 00H
                CMP AH, 10H        ; new added codes
                JE new_io_0
            ;-------------------------------
                ASSUME DS:nothing
                JMP old_keyboard_io    ; No catch, jump to old handler
            ……

              然后編譯運(yùn)行,一切OK!看來(lái)是書(shū)上的代碼給錯(cuò)了。(注:我只是在Win98的MS-DOS環(huán)境下調(diào)試的,不知道純DOS用的是AH=00H還是AH=10H)

            五、參考書(shū)目

              《IBM PC Assembly Language and Programming(Fourth Edition)》, Peter Abel, Prentice Hall, 1998

              《DOS內(nèi)存駐留程序設(shè)計(jì)與實(shí)例》,李振格等,北京航空航天大學(xué)出版社,1994

             

              附:打包下載

              trick.asm   匯編源程序
              trick.com   編譯好的com程序
              trick_d.asm  用于調(diào)試的源程序
              trick_d.com  編譯好的測(cè)試程

                                                   Copyright © 2004 Security Angel Team [S4T] All Rights Reserved.

            posted on 2009-09-25 18:03 Tim 閱讀(481) 評(píng)論(0)  編輯 收藏 引用 所屬分類(lèi): 匯編語(yǔ)言

            <2011年3月>
            272812345
            6789101112
            13141516171819
            20212223242526
            272829303112
            3456789

            導(dǎo)航

            統(tǒng)計(jì)

            公告

            本博客原創(chuàng)文章,歡迎轉(zhuǎn)載和交流。不過(guò)請(qǐng)注明以下信息:
            作者:TimWu
            郵箱:timfly@yeah.net
            來(lái)源:www.shnenglu.com/Tim
            感謝您對(duì)我的支持!

            留言簿(9)

            隨筆分類(lèi)(173)

            IT

            Life

            搜索

            積分與排名

            最新隨筆

            最新評(píng)論

            閱讀排行榜

            久久精品9988| 久久亚洲欧美国产精品| 久久久国产精品亚洲一区| 久久青青国产| 日本精品久久久久久久久免费| 99久久精品免费看国产| 伊人热人久久中文字幕| 久久国产精品久久国产精品| 精品午夜久久福利大片| 亚洲国产成人久久综合碰碰动漫3d| 久久99精品久久久久婷婷| 99国产欧美精品久久久蜜芽| 久久综合久久综合久久综合| 一本伊大人香蕉久久网手机| 99久久精品免费观看国产| 久久一区二区三区99| 伊人精品久久久久7777| 亚洲AV无码久久| 99久久国产亚洲高清观看2024| 国产999精品久久久久久| 亚洲午夜福利精品久久| 亚洲午夜无码久久久久| AV色综合久久天堂AV色综合在| 99久久er这里只有精品18| 99久久久久| 狠狠色丁香久久婷婷综合| 99久久婷婷免费国产综合精品| 99久久精品免费国产大片| 久久久这里有精品| 亚洲女久久久噜噜噜熟女| 久久亚洲国产精品一区二区| 久久夜色精品国产| 国产精品9999久久久久| 久久久久久亚洲精品无码| 亚洲AV日韩AV永久无码久久| 久久精品一区二区三区不卡| 青青久久精品国产免费看| 久久香蕉国产线看观看精品yw| 久久精品国产清自在天天线| 天天爽天天狠久久久综合麻豆| 欧美精品福利视频一区二区三区久久久精品 |