匯編語言之應(yīng)用程序的設(shè)計(jì)說明_第1頁
匯編語言之應(yīng)用程序的設(shè)計(jì)說明_第2頁
匯編語言之應(yīng)用程序的設(shè)計(jì)說明_第3頁
匯編語言之應(yīng)用程序的設(shè)計(jì)說明_第4頁
已閱讀5頁,還剩21頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、第 10 章 應(yīng)用程序的設(shè)計(jì)在前面各章節(jié)中,我們側(cè)重介紹了匯編語言程序設(shè)計(jì)中各組成部分的作用,本章的重點(diǎn)是對前面所學(xué)知識的綜合運(yùn)用。 希望通過各種不同類型的例子, 使讀者能夠掌握用匯編語言編程的基本技巧。10.1 字符串的處理程序字符或字符串是一類重要的非數(shù)值計(jì)算的處理對象。 許多編輯軟件都具有字符串查找、替換、大小寫的轉(zhuǎn)換、單詞的自動(dòng)識別等功能,網(wǎng)絡(luò)上的信息搜索也是現(xiàn)在一種常用的功能等,這些功能的實(shí)現(xiàn)無疑都要涉及到字符串的處理功能。為了方便對字符串的處理, 各種常用的編程環(huán)境也都給予了足夠的支持。 如:C語言編程環(huán)境提供了大量處理字符串的標(biāo)準(zhǔn)函數(shù), 象 strlen 、strcmp 和 st

2、rcpy 等函數(shù); C+、VC或 VB等編程環(huán)境提供了字符串類 String 等。這些函數(shù)或類大大方便了程序員的編程。在計(jì)算機(jī)系統(tǒng),為了加快字符串的處理,在其指令系統(tǒng)中設(shè)置了多條處理字符串的指令,其詳細(xì)容請參閱 第節(jié)中的介紹。下面我們將通過幾個(gè)例子來學(xué)習(xí)匯編語言處理字符串的方法。例 10.1 編寫一個(gè)求字符串長度的子程序 Strlen ,要求字符串的首地址為入口參數(shù),且以 ASCII 碼 0 為結(jié)束符, CX為出口參數(shù),其存放該字符串的長度。解:.MODEL SMALL, C.DATAbuff DB"This is a example.", 0.CODEStrlen PRO

3、C USES AX BX, String:PTR BYTEMOVBX, StringXORCX, CXMOVAL, BX.WHILEAL!=0INCCXINCBXMOV AL, BX.ENDWRETStrlen ENDP.STARTUPINVOKE Strlen, ADDR buff.EXIT0END例 10.2 編寫一個(gè)把字符串中的所有小寫字符轉(zhuǎn)換成大寫字符的子程序Strupr ,要求字符串的首地址和結(jié)束符為其入口參數(shù)。解:.MODEL SMALL, C.DATAbuff DB"This is a example.", 0.CODEStrupr PROCUSES AX B

4、X, String:PTR BYTE, Tail:BYTEMOVBX, String.REPEATMOVAL, BX.IFAL>='a' && AL<='z'SUBAL, 20HMOV BX, AL.ENDIFINCBX.UNTILAL=TailRETStrupr ENDP.STARTUPINVOKE Strupr, ADDR buff, 0.EXIT0END例 10.3 編寫一個(gè)從字符串中拷貝子串的子程序Strncpy ,它有四個(gè)參數(shù)str1 、str2 、idx 和 num,其具體功能為把字符串str2 中從第 idx 個(gè)( 從

5、0 開始記數(shù) ) 字符開始、num個(gè)字符傳送給 str1 ,字符串 str1 和 str2 都是以 ASCII碼 0 為結(jié)束符。解:.MODEL SMALL, C.DATAstr1DB "12345ABCDEF", 0str2DB 20 DUP('A').CODEStrlen PROCUSES AX BX, String:PTR BYTE; 參見例 10.1Strlen ENDPStrncpy PROCUSESAX CX DI SI DS ES, str1:FAR PTRBYTE, str2:FAR PTRBYTE, idx:WORD, num:WORDLE

6、SDI, str1.LDSSI, str2; 取兩個(gè)字符串的首地址INVOKEStrlen, SI; 計(jì)算源字符串的長度,在CX中MOVAX, idx.IF AX >= CX; 若字符起點(diǎn)就超過源串的長度MOV BYTE PTR ES:DI, 0 ;拷貝的字符串為“空”JMP over.ENDIFADDSI, AX; 定源串中字符的起點(diǎn) SIMOVCX, numCLD.REPEATLODSBSTOSB.UNTILCXZ AL=0.IF AL!=0; 設(shè)置目標(biāo)串的結(jié)束符MOV BYTE PTRDI, 0.ENDIFover:RETStrncpy ENDP.STARTUPINVOKEStrn

7、cpy, ADDR str2, ADDR str1, 3, 5.EXIT 0END例 10.4 編寫一個(gè)把字符串中空格和 TAB壓縮掉的子程序 Compress,字符串String 是以 ASCII 碼 0 為結(jié)束符。解:.MODEL SMALL, C.DATASPACEEQU 20HTABEQU 9HBuffDB "12 3 4Abcdef", 0.CODECompressPROC USES AX BX SI DS, String:FAR PTR BYTELDS SI, String;SI 用于掃描字符串的指針MOV BX, SI;BX 用于存放結(jié)果的指針.REPEATM

8、OVAL, SIINCSI.IF AL!=SPACE && AL!=TABMOVBX, ALINC BX.ENDIF.UNTIL AL=0RETCompressENDP.STARTUPINVOKE Compress, ADDR Buff.EXIT 0END從上面四個(gè)例子,我們不難看出處理字符串的一般方法,感興趣的讀者可自行編寫實(shí)現(xiàn)字符串變小寫、 整體拷貝、逆轉(zhuǎn)和查找等功能的子程序, 甚至還可以建立起自己的字符串處理庫文件。10.2 數(shù)據(jù)的分類統(tǒng)計(jì)程序數(shù)據(jù)的分類和統(tǒng)計(jì)也是一類非數(shù)值計(jì)算,數(shù)據(jù)的分類統(tǒng)計(jì)方法在例 6.10中已介紹,下面通過一個(gè)例子介紹數(shù)據(jù)的分類存儲(chǔ)問 題 。例 10

9、.5 統(tǒng)計(jì)從地址 0040H:0000H開始的 100 個(gè)字中,把正數(shù)和負(fù)數(shù)按照它們先后出現(xiàn)的次序分別存儲(chǔ)在緩沖區(qū) Data1 和 Data2,并把每類的個(gè)數(shù)存入相應(yīng)緩沖區(qū)的第一個(gè)字單元中。解:由于在指定地址之后的 100 個(gè)字中,可能存在全是正數(shù)或負(fù)數(shù)的情況, 所以,緩沖區(qū) Data1 和 Data2 的容量都應(yīng)是 100 個(gè)字。.MODEL SMALL.DATANum = 100Data1 DW ?, Num dup(?)Data2 DW ?, Num dup(?).CODE.STARTUPMOV AX, 40HMOV ES, AXLEASI, Data1+2; 指向存儲(chǔ)正數(shù)的緩沖區(qū)LEA

10、DI, Data2+2; 指向存儲(chǔ)負(fù)數(shù)的緩沖區(qū)XOR BX, BX;BX 用于掃描存儲(chǔ)單元MOV CX, 100; 字符個(gè)數(shù).REPEATMOVAX, ES:BXADDBX, 2CMPAX, 0.CONTINUE .IFZERO?.JLnext1MOVSI, AX; 向正數(shù)緩沖區(qū)存儲(chǔ)數(shù)據(jù)ADDSI, 2.CONTINUEnext1:MOV DI, AX; 向負(fù)數(shù)緩沖區(qū)存儲(chǔ)數(shù)據(jù)ADD DI, 2.UNTILCXZSUB SI, OFFSET Data1+2SUB DI, OFFSET Data2+2SHR SI, 1SHR DI, 1MOV Data1, SIMOV Data2, DI.EXIT

11、 0END; 把每類的統(tǒng)計(jì)個(gè)數(shù)存入緩沖區(qū)的第一個(gè)字單元例 10.6 用鍵盤輸入任意一字符串, 分類統(tǒng)計(jì)該字符串中每個(gè)數(shù)字和字母的出現(xiàn)次數(shù)。解:.MODEL SMALL.DATAN=80BuffDB N, ?, N DUP(?)NumDW 36 DUP(0); 每個(gè)字用于存放 '0''9', 'A''Z'出現(xiàn)的個(gè)數(shù).CODE.STARTUPLEADX, BuffMOVAH, 0AHINT21H; 輸入一個(gè)字符串XORCH, CHMOVCL, Buff+1;CX=輸入字符串的個(gè)數(shù)LEASI, Buff+2XORBX, BX.REPEA

12、TMOV BL, SI; 考慮下面的思考題INCSI.IFBL>='0' && 分類統(tǒng)計(jì) '0''9' 中的每個(gè)數(shù)字的個(gè)數(shù)BL<='9'SUBL, '0'ADDBX, BXINCNumBX.CONTINUE.ENDIF.IFBL>='a' && BL<='z'SUBL, 20H; 小寫變大寫.ENDIF.IFBL>='A' && 分類統(tǒng)計(jì) 'A''Z'中的每個(gè)

13、字母的個(gè)數(shù)BL<='Z'SUBL, 'A'-10ADDBX, BXINCNumBX.ENDIF.UNTILCXZ.EXIT0END思考題:在本例中,用指令“ MOV BL, SI ”來把當(dāng)前檢測的字符存入 BL,當(dāng)然,我們也可以用 AL 來代替 BL,有關(guān)指令要作相應(yīng)的改動(dòng),但這樣做,會(huì)更方便嗎?希望讀者能知道:為什么要用 BL,而不用 AL?10.3 數(shù)據(jù)轉(zhuǎn)換程序數(shù)據(jù)類型轉(zhuǎn)換是輸入輸出過程中經(jīng)常遇到的問題。輸入時(shí),計(jì)算機(jī)系統(tǒng)要把用戶從鍵盤上輸入的字符串轉(zhuǎn)變成相應(yīng)的數(shù)值, 并存儲(chǔ)在存中; 輸出時(shí),要把計(jì)算機(jī)部的二進(jìn)制數(shù)據(jù)形式轉(zhuǎn)換成相應(yīng)的十進(jìn)制字符串,然后再

14、輸出。在高級語言編程環(huán)境中,程序員能用各種輸入輸出語句,按一定的格式進(jìn)行交互式操作,很少或根本不關(guān)心輸入輸出是如何實(shí)現(xiàn)的。 有的程序員甚至認(rèn)為其輸入的就是十進(jìn)制數(shù)值, 輸出數(shù)據(jù)也就是把存中存儲(chǔ)的數(shù)據(jù)直接輸出出來。 其實(shí),輸入輸出過程并不是如此簡單, 計(jì)算機(jī)系統(tǒng)要進(jìn)行復(fù)雜而又細(xì)致的數(shù)據(jù)類型轉(zhuǎn)換和格式化等工作。本節(jié)試圖通過用匯編語言實(shí)現(xiàn)數(shù)據(jù)類型的轉(zhuǎn)換來反映輸入輸出的本來面目,使程序員在用高級語言編程時(shí), 對其輸入輸出語句的實(shí)現(xiàn)過程有所了解, 也知道有別人 ( 或編譯程序 ) 幫他完成了輸入輸出的準(zhǔn)備工作。例 10.7 編寫一個(gè)程序,它能把字類型變量的數(shù)值以十進(jìn)制形式輸出出來。若該數(shù)值為負(fù)數(shù),則需要

15、輸出負(fù)號 "-" ,否則,不輸出符號。解:鑒于按二進(jìn)制輸出的特殊性,我們可以把它優(yōu)化成 例 10.8 的形式,按十六進(jìn)制輸出也可以按“四位二進(jìn)制對應(yīng)一位十六進(jìn)制”的規(guī)則進(jìn)行優(yōu)化的。.例 10.8 編寫程序,它能把字類型變量的數(shù)值以二、八進(jìn)制或十六進(jìn)制形式輸出出來。若該數(shù)值為負(fù)數(shù),則需要輸出負(fù)號 "-" ,否則,不輸出符號。解:一、按二進(jìn)制形式輸出的程序二、按八進(jìn)制形式輸出的程序三、按十六進(jìn)制形式輸出的程序例 10.7 是用“用 16 位除 10”的方法從低向高依次得到每位的數(shù)值, 但若待輸出的數(shù)據(jù)是 32 位,用 10 除之后,其商很可能會(huì)超過 16 位

16、,所以,不能簡單地引用例 10.7 的方法來輸出 32 位二進(jìn)制。16假設(shè):32 位二進(jìn)制數(shù) Z 為 A×2 B,其中:A 和 B 都是 16 位二進(jìn)制數(shù)。用10 去除 A,得: AA1×10 A2,于是,(1)216除后所得的商和余數(shù)分別為11110)。假設(shè) A×2B 被 10B和 C(B0,C利用式16(1) 和“A<10”,我們不難看出: Z 的個(gè)位就是 C 和 B <2 。211.16令 Z1 A1 ×2 B1,顯然, Z1 就是 Z/10 所得到的商。對于 Z1,再利用式 (1) 得到商 Z2 和 C2。,重復(fù)上面的步驟,直到所得商

17、為0為止。下面的例 10.9 就是利用上面方法來輸出32 位二進(jìn)制數(shù)值。例 10.9 編寫一個(gè)子程序,該子程序能把 32 位二進(jìn)制變量的數(shù)值以十進(jìn)制形式輸出出來。若該數(shù)值為負(fù)數(shù),則需要輸出負(fù)號 "-" ,否則,不輸出符號。解:.MODEL SMALL, C.DATACR=13LF=10Data1 DD908976789.CODE; 子程序 Display 是按十進(jìn)制輸出 32 位二進(jìn)制數(shù)值 SOURCEDisplay PROC USES AX BX CX DX SI DI SOURCE:DWORDLOCAL FLAG:BYTE; 定義一個(gè)字節(jié)類型的局部變量 FLAGMOVB

18、X, WORD PTR SOURCEMOVCX, WORD PTR SOURCE+2MOVFLAG, 0;FLAG=0正數(shù)CMPCX, 0JGEnextINCFLAG;FLAG=1負(fù)數(shù)NOTBXNOTCXADDBX, 1; 能否用指令 INC BX?ADCCX, 0; 上四條指令把 32 位數(shù) CX-BX變?yōu)檎龜?shù)next:XORDI, DI; 壓入堆棧字符的個(gè)數(shù)MOVSI,10;用10來除.REPEAT; 本循環(huán)把 32 位二進(jìn)制數(shù)轉(zhuǎn)換成十進(jìn)制XOR DX, DX; 數(shù)的字符串存入堆棧之中MOV AX, CXDIV SIMOV CX, AXMOV AX, BXDIV SIADD DL, 

19、9;0'PUSHDXINC DIMOV BX, AX.UNTIL BX=0 && CX=0.IFFLAG=1; 判斷前面轉(zhuǎn)換的數(shù)是否為負(fù)數(shù)MOV AL, '-' 若是,把符號 '-' 壓入堆棧PUSHAXINC DI.ENDIFMOVCX, DI.REPEAT; 本循環(huán)把堆棧中的字符串顯示出來POP DXMOV AH, 2INT 21H.UNTILCXZMOVDL, CR; 下面六條指令顯示回車、換行MOVAH, 2INT21HMOVDL, LFMOVAH, 2INT21HRETDisplay ENDP.STARTUPINVOKEDisp

20、lay, Data1INVOKEDisplay, -123456789.EXIT 0END例 10.10 編寫一個(gè)程序,它能把用鍵盤輸入的字符串轉(zhuǎn)化成相應(yīng)的數(shù)值。具體功能如下:1、 輸入的數(shù)據(jù)字符串可以帶正、負(fù)符號,如:1234、+1234 或-1234 ;2、 字符串的最后一個(gè)字符表示數(shù)據(jù)的進(jìn)制, 默認(rèn)的進(jìn)制為十進(jìn)制, 如:1234H表示十六進(jìn)制數(shù) 1234,1234 為十進(jìn)制數(shù);3、 對于任何進(jìn)制的數(shù)據(jù),當(dāng)遇到一個(gè)非進(jìn)制圍的字符時(shí),則顯示出錯(cuò)信息,并以數(shù)值為其轉(zhuǎn)換結(jié)果來結(jié)束該類型轉(zhuǎn)換過程。解:略10.4 文件操作程序有關(guān)目錄和順序文件的操作在第節(jié)中已有介紹和舉例, 本節(jié)主要介紹對記錄文件的

21、讀寫方法。 記錄文件是指文件中的每個(gè)分量是一個(gè)結(jié)構(gòu)的文件, 如: Fox 系列數(shù)據(jù)庫管理系統(tǒng)中的 DBF文件,該文件除了文件頭是由記錄文件的整體信息和各字段描述信息之外,文件的主體容就是由同一個(gè)結(jié)構(gòu)組成的。下面通過二個(gè)例子來介紹記錄文件的讀寫方法。.例 10.11 假設(shè)有一個(gè)簡單的學(xué)生結(jié)構(gòu)類型 student ,其包括:學(xué)號、和年齡等信息,要求編寫一個(gè)程序,該程序接受從鍵盤輸入的學(xué)生記錄信息,并把它們保存在文件 students.dat 之中。解:.MODEL SMALL, C.486student STRUCTidDW ?sname DB 10 DUP(?)ageDB ?student EN

22、DS.DATAfname DB"Students.dat",0msg1DB"Id:$"msg2DB"Name:$"msg3DB"Age:$"msg4DB"Continue?$"msg5DB"Fail to create file$"CRLFDB0AH, 0DH, "$"buffDB?, ?, 11 DUP(?)peasonSTUDENT <>.CODEDispMsg PROC USES AXDX, Msg:PTR顯示字符串 Msg;BYTE;

23、參見例 10.7DispMsg ENDP; 程序功能:把字符串 Data 轉(zhuǎn)化成數(shù)值,不考慮負(fù)數(shù)。當(dāng)遇到非法字符時(shí),則結(jié)束轉(zhuǎn)換操作;; 入口參數(shù): Data 為字符串的首地址, Len 為該字符串的長度;; 出口參數(shù):數(shù)值存放在 AX中。GetData PROC USES BX CX SI, Len:BYTE, Data:PTR BYPE XOR CX, CXMOVCL, LenMOVSI, DataXORAX, AXXORBX, BX.REPEATMOV BL, SISUB BL, '0'.BREAK.IF BL<0 | BL>9; 判斷當(dāng)前數(shù)值是否在 09 之間

24、 IMULAX, 10ADD AX, BXINC SI.UNTILCXZRETGetData ENDP; 程序功能:讀取指定長度的字符串,在輸入前,顯示有關(guān)輸入容的提示信息;; 入口參數(shù):讀入字符串的長度為 Len,提示信息的首地址為 MSG;; 出口參數(shù):讀入信息 ( 字符串 ) 存放緩沖區(qū) buff 中。GetInfo PROCUSES AX DX, Len:BYTE, Msg:PTR BYTEINVOKEDispMsg, Msg; 顯示提示信息MOVAL, LenMOVbuff, ALMOVAH, 0AHLEADX, buffINT21HINVOKEDispMsg, ADDRCRLF;顯

25、示回車、換行RETGetInfo ENDP.STARTUPMOVAX, DSMOVES, AXLEADX, fnameMOVCX, 20HMOVAH, 3CHINT21H; 創(chuàng)建文件.IF CARRY?; 若創(chuàng)建失敗,則顯示失敗信息INVOKE DispMsg, ADDR msg5JMP over.ENDIFMOVBX, AX; 把句柄存入 BX,為后面使用作準(zhǔn)備again:INVOKEDispMsg, ADDRCRLF;顯示回車、換行GetInfo, 5, ADDR; 讀取學(xué)號 ( 假定學(xué)號為 4 位整數(shù) )INVOKEmsg1GetData, 4, ADDR; 把學(xué)號字符串轉(zhuǎn)化成數(shù)值INV

26、OKEbuff+2MOVpeason.id, AX; 把數(shù)值型學(xué)號存入學(xué)號字段GetInfo, 11, ADDR; 讀取(假定為 10 個(gè)字符)INVOKEmsg2MOVCX, 10MOVAL,''LEADI, peason.snameREPSTOSB; 先置字段為 10 個(gè)空格MOVCL, buff+1MOVSI, OFFSET buff+2.LEADI, peason.snameREPMOVSB; 把輸入的存入字段GetInfo, 3, ADDR; 讀取年齡 ( 假定年齡為 2 位整數(shù) )INVOKEmsg3GetData, 2, ADDR; 把年齡字符串轉(zhuǎn)化成數(shù)值INVO

27、KEbuff+2MOVpeason.age, AL; 把數(shù)值型年齡存入年齡字段MOVCX, SIZE peasonLEADX, peasonMOVAH, 40HINT21H; 把學(xué)生記錄寫入文件INVOKEDispMsg, ADDRmsg4; 提示是否繼續(xù)輸入MOVAH, 1INT21HANDAL, 0DFHCMPAL, 'Y'JZagain; 若按 y 或 Y,則繼續(xù)輸入MOVAH, 3EHINT21Hover:.EXIT 0END例 10.12 編寫一個(gè)程序顯示由 例 10.11建立的記錄文件 students.dat中的學(xué)生信息。解:.MODEL SMALL,Cstude

28、ntSTRUCTidDW ?sname DB10 DUP(?)ageDB?studentENDS.DATAfname DB"Students.dat",0id1DB"Id:", 4 dup(?), 0dh, 0ah, "$"name1 DB"Name:", 10 dup(' '), 0dh, 0ah, "$"age1DB"Age:", 2 dup(?), 0dh, 0ah, "$"msg1DB"Fail to open file$

29、"peasonstudent <>.CODEDispMsg PROC USES AX DX, Msg:PTR BYTE;顯示字符串 Msg; 參見例 10.7DispMsg ENDP.; 程序功能:把數(shù)據(jù)Data 轉(zhuǎn)換成長度為 Len 的字符串;; 入口參數(shù):待轉(zhuǎn)換數(shù)據(jù) Data,轉(zhuǎn)換成字符串的長度為 Len,存放字符串的首地址為 PStr ;; 出口參數(shù):讀入信息 ( 字符串 ) 存放緩沖區(qū) buff 中。GetStrPROC USES AX CX DX DI, Data:WORD, Len:WORD, PStr:PTR BYTE MOV CX, LenMOVDI, P

30、StrMOVAL, ' 'REPSTOSB; 把存放字符串的緩沖區(qū)填充為空格MOVDI, PStrADDDI, LenDECDI; 確定最后一個(gè)字符在緩沖區(qū)中的位置MOVAX, DataMOVCX, 10.REPEATXORDX, DXIDIVCX; 除 10,從低位向高位求得每一位ADDDL, '0' 把余數(shù)轉(zhuǎn)變成字符,然后存放目標(biāo)單元MOVDI, DLDECDI.UNTIL AX=0RETGetStr ENDP.STARTUPMOVAX, DSMOVES, AXLEADX, fnameMOVAL, 0HMOVAH, 3DHINT21H; 以“只讀”方式打開指

31、定的文件.IFCARRY?; 若創(chuàng)建失敗,則顯示失敗信息INVOKE DispMsg, ADDR msg1JMP over.ENDIFMOVBX, AX; 把句柄存入 BX,為后面使用作準(zhǔn)備again:MOVCX, SIZE peasonLEADX, peason.MOVAH, 3FHINT21H; 從文件中讀出一個(gè)記錄.IFCARRY? | AX=0; 若讀記錄出錯(cuò)或遇到文件尾,結(jié)束JMPclose.ENDIFGetStr, peason.id, 4,; 把“學(xué)號”轉(zhuǎn)換成字符串INVOKEADDR Id1+3INVOKEDispMsg, ADDR Id1; 顯示“學(xué)號”字符串MOVCX, 1

32、0LEASI, peason.snameLEADI, Name1+5REPMOVSB; 把“”轉(zhuǎn)移到顯示區(qū)INVOKEDispMsg, ADDR Name1; 顯示“”字符串Getstr, peason.age, 2,; 把“年齡”轉(zhuǎn)換成字符串INVOKEADDR Age1+4INVOKEDispmsg, ADDR Age1; 顯示“年齡”字符串JMPagainclose:MOVAH, 3EHINT21H; 關(guān)閉當(dāng)前打開的文件over:.EXIT 0END從例 10.11 和 10.12 ,我們不難掌握記錄文件的讀寫方法。有興趣的讀者,還可以利用文件指針的定位來指定讀寫某個(gè)具體的記錄。10.5

33、 動(dòng)態(tài)數(shù)據(jù)的編程動(dòng)態(tài)數(shù)據(jù)結(jié)構(gòu)是一種常用的數(shù)據(jù)結(jié)構(gòu), 在事先不知道所處理數(shù)據(jù)容量的情況,用動(dòng)態(tài)數(shù)據(jù)是一種行之有效的方法, 也為許多 C語言程序員所采用。 在匯編語言中,我們也可以采用動(dòng)態(tài)數(shù)據(jù)的方式來存儲(chǔ)數(shù)據(jù),并進(jìn)行鏈表的遍歷。為了使讀者盡快理解本例的功能, 我們把與之相似功能的 C 語言程序書寫如下:#include <stdio.h>#include <alloc.h>structlink intdata;struct link*next;void main( ).struct link *head=NULL, *temp, *pt;int i;for (i = 20;

34、 i > 0; i-) ; 生成 20 個(gè)結(jié)點(diǎn)的鏈表temp = (struct link; 申請一個(gè)結(jié)點(diǎn)的空間*)calloc(1,sizeof(struct link);if (temp = NULL) break; 若分配存失敗temp->data = i;temp->next = NULL;if (head = NULL) head = temp;else pt->next = temp;pt = temp;while (head != NULL) ; 遍歷結(jié)點(diǎn)并輸出其數(shù)據(jù)字段printf("%dn",head->data);pt =

35、head;head = head->next;free(pt);例 10.13 編寫一個(gè)程序用動(dòng)態(tài)鏈表存儲(chǔ) 20,19,1,并用遍歷鏈表的方法來顯示每個(gè)結(jié)點(diǎn)的數(shù)值。解:顯示解答10.6 COM文件的編程COM文件和 EXE文件都是可執(zhí)行文件,最典型的COM文件是 Command.COM。COM文件的主要特點(diǎn)如下:1、 COM文件只有一個(gè)段,其字節(jié)數(shù)不會(huì)超過64K;2、當(dāng)操作系統(tǒng)裝入 COM文件時(shí),四個(gè)段寄存器 (CS、DS、ES和 SS)都 用 PSP 的段值來初始化;3、必須用偽指令ORG 100H來說明空出前256 個(gè)字節(jié)。例 10.14 編寫一個(gè)顯示字符串“ Hello ”的 CO

36、M類型的程序。解:CSEGSEGMENT 'CODE'ORG 100H; 空出前 256 個(gè)字節(jié)start: LEADX, MSGMOV AH, 09HINT21HMOV AX, 4C00HINT21HMSG DB"Hello$" 定義字符串.CSEGENDSEND start對上面程序,其生成的 COM文件只有 23 個(gè)字節(jié),而其 EXE文件的字節(jié)數(shù)會(huì)超過 1K。在 PWB編程環(huán)境下,可在 Option Project Templates Set Project Template 在列表框中選 DOS COM來指定生成 COM文件。在 Turbo Asse

37、mber 系統(tǒng)中,可用 TASM、TLINK /T 來指定生成 COM文件。10.7 駐留程序駐留程序 TSR(Terminate but Stay Resident) 是一種特殊應(yīng)用程序,它在裝入存運(yùn)行后, 其部分代碼仍然駐留在存, 當(dāng)該段代碼被激活時(shí), 它又進(jìn)入運(yùn)行狀態(tài)。常用的駐留程序是作為某個(gè)中斷處理程序的一部分, 其激活條件就是系統(tǒng)產(chǎn)生了此中斷的中斷請求。雖然駐留程序可根據(jù)具體的需要有不同的編寫方式, 但其典型結(jié)構(gòu)包括以下幾部分:1、保存、修改中斷向量表;2、程序第一次運(yùn)行時(shí)的初始化部分:用自己定義的地址來取代中斷向量表中的原地址確定駐留代碼部分的字節(jié)數(shù)用中斷 21H之功能 31H把需

38、要駐留代碼部分駐留在存3、駐留存的代碼部分。例 10.15 在 NumLock處于“開狀態(tài)”時(shí),每按小鍵盤 (Numeric Keypad) 上的數(shù)字鍵,給出“啪啪”響聲。解:顯示解答例 10.16 編寫一個(gè)駐留程序,它可顯示當(dāng)前時(shí)間的秒數(shù)。解:顯示解答10.8 程序段前綴及其應(yīng)用程序段前綴 PSP(ProgramSegment Prefix) 是一個(gè)具有 256 個(gè)字節(jié)的信息區(qū),是可執(zhí)行文件 (EXE和 COM)所特有的,其容在操作系統(tǒng)裝入該文件運(yùn)行時(shí)存入。.程序段前綴的字段含義PSP信息區(qū)的字段分布如下表10.1 所列。表 10.1 PSP 信息區(qū)的字段分布表偏移量 容含義偏移量 容含義0

39、001H 程序結(jié)束指令中斷 20H2E31H保留分配給該程序的最后段3233H 文件句柄表的長度0203H的段地址0409H 保留指向文件句柄表的遠(yuǎn)指3437H針中斷 22H的地址 ( 處理終384FH 保留0A0DH止程序 )中斷 23H 的地址 ( 處理5051H 中斷 21H的功能調(diào)用0E11HBreak)中斷 24H的地址 ( 處理嚴(yán)525BH保留1215H重錯(cuò)誤 )1617H 保留5C6BH參數(shù)區(qū) 1182BH缺省的文件句柄表6C7FH參數(shù)區(qū) 22C2DH程序環(huán)境塊的段地址80FFH存儲(chǔ)缺省 DTA的緩沖區(qū)PSP信息區(qū)的字段說明:182BH字 該字段共有20 個(gè)字節(jié),每個(gè)字節(jié)存儲(chǔ)一個(gè)

40、文件句柄,所以,系統(tǒng)允許應(yīng)段: 用程序在某一時(shí)刻最多只能打開20 個(gè)文件。前 5 個(gè)字節(jié)存儲(chǔ)系統(tǒng)標(biāo)準(zhǔn)設(shè)備的句柄,可參閱節(jié)系統(tǒng)標(biāo)準(zhǔn)設(shè)備的句柄。若某文件需要同時(shí)打開更多的文件, 則需要調(diào)整文件句柄數(shù)。 即:先用中斷 21H之功能 4AH釋放存,再用其功能 67H 來設(shè)置新的文件句柄數(shù)。MOV BX, NewNum; 新的文件句柄最大數(shù)(2065535)MOV AH, 67HINT 21H2C2DH字 該字段存放程序運(yùn)行環(huán)境的段地址,程序的缺省運(yùn)行環(huán)境有160 個(gè)字節(jié),段: 最多可達(dá)32K。該環(huán)境含有系統(tǒng)命令,如:COMSPEC、PATH、PROMPT和 SET。 5C6BH 字 該字段存放命令行的

41、第一個(gè)參數(shù)。假設(shè)要執(zhí)行下列命令:段:Masm D:test.asm.這時(shí), 04H(驅(qū)動(dòng)器 D)、 8 個(gè)字符的文件名和 3 個(gè)字符的后綴存放在該區(qū)域,沒有存放字符的單元用空格 (20H) 來填充。若省缺驅(qū)動(dòng)器和文件名,則第一個(gè)字節(jié)為 00H,其它單元為 20H。 6C7FH 字 該字段存放命令行的第二個(gè)參數(shù)。假設(shè)要執(zhí)行下列命令:段:Masm D:test.asm, test.obj這時(shí), test.obj 作為第二參數(shù)存入該字段,存儲(chǔ)方式如上字段。 80FFH 字 該字段的第一個(gè)字節(jié)存放命令行參數(shù)的字符數(shù),第二個(gè)字節(jié)為空格,從第段: 三個(gè)字節(jié)開始存放命令行參數(shù)字符。程序段前綴的應(yīng)用了解和掌握 PSP中的信息分布就是為了利用其信息。對于 EXE文件,可用中斷 21H之功能 51H 獲取其段地址。如:MOVAH, 51HINT21H;BX=PSP 的段地址MOVES, BXCMPbyte ptrES:80H,0; 檢查 PSP的長度JEnext對于 COM文件,因?yàn)槠渲挥幸粋€(gè)段,所以,可用更簡單的方式來檢查PSP的容。MOVBX, 80HCMPbyte

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論