?? reader.asm
字號(hào):
MYDAT SEGMENT
MAXLEN DW 300 ;最大行數(shù)
INDEX DW 300 DUP(?) ;行索引
LENCT DW 0 ;實(shí)際行數(shù)
CURLINE DW 0 ;當(dāng)前頁(yè)第一行行數(shù)
CCOUNT DW ? ;文件總字符數(shù)
TOP DB 5 ;窗口左上角行數(shù)
LEFT DB 5 ;窗口左上角列數(shù)
WS DW 60 ;窗口寬度
HS DW 15 ;窗口高度
FG DB 17H ;文字屬性
FGB DB 1FH ;窗口邊框?qū)傩?
MSG1 DB 'File:$' ;輸入文件名提示
MSG2 DB 'File open error!$' ;打開文件出錯(cuò)時(shí)提示
MSG3 DB 'File read error!$' ;讀文件出錯(cuò)時(shí)提示
FILENA DB 80,?,80 DUP(?) ;輸入文件名緩沖區(qū)
;下面是定義功能鍵和相應(yīng)的處理程序
;每個(gè)功能定義兩個(gè)數(shù)據(jù):掃描碼,處理程序入口地址
;該數(shù)據(jù)由DOSUB子程序使用
KEYSUB DW 48H,SUB1 ,50H,SUB2, 0
MYDAT ENDS
BUFFER SEGMENT
DB 65535 DUP(?) ;文件緩沖區(qū),文件最大為64K
BUFFER ENDS
CODE SEGMENT
ASSUME CS:CODE, DS:MYDAT, ES:BUFFER
START: CALL INIT ;程序初始化
CALL READFILE ;讀入文件
CALL CLIST ;初始化索引行
CALL CLSDISP ;清屏
CALL CREWIN ;創(chuàng)建窗口
CALL SHOWCUR ;顯示當(dāng)前頁(yè)
CALL MAIN ;進(jìn)入主程序
CALL CLSDISP ;清屏
MOV AX,4C00H
INT 21H ;退出本程序
;顯示當(dāng)前頁(yè)子程序
SHOWCUR PROC
MOV DH,0 ;窗口最頂行
MOV SI,CURLINE ;取當(dāng)前頁(yè)第一行行數(shù)
MOV CX,HS ;窗口的第一行和最后一行為邊框,
SUB CX,2 ;所以能夠顯示內(nèi)容的高度為窗口高度減二
SC1: PUSH CX
PUSH SI
PUSH DX
CALL SHOWLINE ;顯示一行
POP DX
POP SI
POP CX
INC DH ;窗口下一行
INC SI ;文件下一行
MOV AX,LENCT ;
CMP SI,AX ;文件是否顯示完
JNC SC2 ;顯示完則轉(zhuǎn)SC2
LOOP SC1
JMP SC1X
SC2: JCXZ SC1X ;該頁(yè)顯示滿則結(jié)束
;該頁(yè)沒有顯示滿,則用空行填滿該頁(yè)
SC3: PUSH CX
PUSH DX
CALL SHOWSPLINE ;顯示空行
POP DX
POP CX
INC DH
LOOP SC3
SC1X:
RET
SHOWCUR ENDP
;顯示一行子程序
;輸入:SI=顯示行行號(hào)
; DH=窗口中的行號(hào)
SHOWLINE PROC
ADD DH,TOP ;
INC DH ;實(shí)際行數(shù)=窗口左上角行數(shù)+DI+1
MOV DL,LEFT ;
INC DL ;實(shí)際列數(shù)=窗口左上角列數(shù)+1
CALL VADD ;
MOV CX,WS ;窗口的第一列和最后一列是邊框,
SUB CX,2 ;所以能夠顯示內(nèi)容的寬度為窗口寬度減二
SHL SI,1 ;行索引為字類型,所以乘二
MOV SI,INDEX[SI] ;取該行第一個(gè)字符在文件緩沖區(qū)的地址
PUSH DS
MOV AX,0B800H
MOV DS,AX ;DS指向顯示緩沖區(qū)段地址
SL1: MOV AX,ES:[SI]
CMP AX,0A0DH
JZ SL2 ;如果是回車換行,則該行結(jié)束
MOV DS:[DI],AL ;顯示一個(gè)字符
ADD DI,2 ;
INC SI ;取下一個(gè)字符
LOOP SL1 ;
JCXZ SLX ;該行正好顯示完,則結(jié)束,否則用空格填滿
SL2: MOV BYTE PTR DS:[DI],' ' ;該行沒有顯示滿,則用空格填滿
ADD DI,2
LOOP SL2
SLX: POP DS
RET
SHOWLINE ENDP
;顯示空行子程序
;輸入:DI=窗口中的行號(hào)
SHOWSPLINE PROC ;
MOV AX,HS ;
SUB AX,2 ;
CMP DH,AL ;顯示的空行是否超出最低行
JNC SSLX ;如果是,則轉(zhuǎn)SSLX
ADD DH,TOP ;
INC DH ;實(shí)際行數(shù)=窗口左上角行數(shù)+DI+1
MOV DL,LEFT ;
INC DL ;實(shí)際列數(shù)=窗口左上角列數(shù)+1
CALL VADD ;
MOV CX,WS ;窗口的第一列和最后一列是邊框,
SUB CX,2 ;所以能夠顯示內(nèi)容的寬度為窗口寬度減二
PUSH DS
MOV AX,0B800H
MOV DS,AX
SSL1: MOV BYTE PTR DS:[DI],' '
ADD DI,2
LOOP SSL1
POP DS
SSLX: RET
SHOWSPLINE ENDP
;索引行初始化子程序
CLIST PROC
MOV CX,CCOUNT
JCXZ CSTX ;文件為空結(jié)束
MOV SI,0 ;文件緩沖區(qū)字符指針
MOV DI,0 ;索引行指針
MOV DX,0 ;行數(shù)計(jì)數(shù)
MOV INDEX[DI],0
INC DX ;假設(shè)文件至少有一行
CST1: CMP WORD PTR ES:[SI], 0A0DH ;判斷是否為回車換行符
JNZ CST2 ;不是行結(jié)束,轉(zhuǎn)CST2
INC DX ;行數(shù)加一
ADD SI,2 ;跳過回車換行符
ADD DI,2 ;索引行指針加一
MOV INDEX[DI],SI ;指向本行開始地址
CMP DX,MAXLEN
JNC CST4 ;是否超過最大行,超過轉(zhuǎn)CST4,結(jié)束
JMP CST3 ;
CST2: INC SI ;文件緩沖區(qū)字符指針指向下一字符
CST3: LOOP CST1 ;
CST4: MOV LENCT,DX ;保存行數(shù)到LENCT中
CSTX: RET
CLIST ENDP
;創(chuàng)建窗口子程序
CREWIN PROC
PUSH ES
MOV AX,0B800H ;顯示緩沖區(qū)地址為B800:0
MOV ES,AX ;
MOV DH,TOP
MOV DL,LEFT ;窗口左上角行列數(shù)
MOV CX,HS ;窗口高度(行數(shù))
CW1: PUSH DX ;
CALL VADD ;計(jì)算地址
PUSH CX ;
MOV CX,WS ;窗口寬度(列數(shù))
MOV AL,FG ;取屬性
CW2: MOV BYTE PTR ES:[DI],' ' ;送空白字符
INC DI ;
MOV BYTE PTR ES:[DI],AL ;送屬性
INC DI ;
LOOP CW2 ;
POP CX
POP DX
INC DH ;行數(shù)加一
LOOP CW1
CALL DRAWB ;畫邊框
POP ES
RET
CREWIN ENDP
;畫邊框子程序
DRAWB PROC
MOV BL,FGB ;取邊框?qū)傩? MOV DH,TOP
MOV DL,LEFT ;窗口左上角行列數(shù)
CALL VADD ;計(jì)算地址
;畫左上角角框
MOV BYTE PTR ES:[DI],0C9H ;
INC DI
MOV BYTE PTR ES:[DI],BL
INC DI
;畫第一行邊框
MOV CX,WS
SUB CX,2 ;因?yàn)槿サ袅俗笥医强颍詫挾葴p二
DB1: MOV BYTE PTR ES:[DI],0CDH ;
INC DI
MOV BYTE PTR ES:[DI],BL
INC DI
LOOP DB1
;畫右上角角框
MOV BYTE PTR ES:[DI],0BBH ;
INC DI
MOV BYTE PTR ES:[DI],BL
;畫第二行到倒數(shù)二行左右邊框
MOV DH,TOP
MOV DL,LEFT
INC DH ;從第二行開始
MOV CX,HS ;第一行和最后一行沒有左右邊框,
SUB CX,2 ;所以高度減二
DB2: PUSH DX ;
CALL VADD ;計(jì)算左邊框地址
MOV BYTE PTR ES:[DI],0BAH ;
INC DI
MOV BYTE PTR ES:[DI],BL
DEC DI
MOV AX,WS ;
DEC AX ;
SHL AX,1 ;
ADD DI,AX ;計(jì)算右邊框地址
MOV BYTE PTR ES:[DI],0BAH ;
INC DI
MOV BYTE PTR ES:[DI],BL
POP DX
INC DH ;下一行
LOOP DB2 ;
;畫左下角角框
MOV DH,TOP ;
MOV DL,LEFT ;
MOV AX,HS ;
DEC AX ;
ADD DH,AL ;左下角行數(shù)=右上角行數(shù)+窗口高度-1
CALL VADD
MOV BYTE PTR ES:[DI],0C8H ;
INC DI
MOV BYTE PTR ES:[DI],BL
INC DI
;畫最低行邊框
MOV CX,WS ;
SUB CX,2 ;因?yàn)槿サ袅俗笥医强颍詫挾葴p二
DB3: MOV BYTE PTR ES:[DI],0CDH ;
INC DI
MOV BYTE PTR ES:[DI],BL
INC DI
LOOP DB3
;畫右下角角框
MOV BYTE PTR ES:[DI],0BCH
INC DI
MOV BYTE PTR ES:[DI],BL
RET
DRAWB ENDP
;計(jì)算行列對(duì)應(yīng)顯存地址子程序
;輸入:DH=行 DL=列
;輸出:DI為顯存地址
VADD PROC
MOV AL,80 ;
MUL DH ;
XOR DH,DH ;
ADD AX,DX ;行數(shù)×80+列數(shù)
SHL AX,1 ;乘2,因?yàn)槊總€(gè)字符占兩個(gè)字節(jié)
MOV DI,AX
RET
VADD ENDP
;提示并讀入文件子程序
READFILE PROC
MOV DX,OFFSET MSG1 ;
CALL PROMPT ;
CALL GETFILE ;
RET
READFILE ENDP
;將文件讀入文件緩沖區(qū)子程序
GETFILE PROC
CALL SIN ;讀入文件名
MOV AX,3D00H
MOV DX,OFFSET FILENA+2
INT 21H ;打開文件讀
JC GETERR1 ;打開文件出錯(cuò)轉(zhuǎn)GETERR1
PUSH DS
PUSH ES
POP DS ;將DS指向文件緩沖區(qū)段
MOV BX,AX ;BX=文件號(hào)
MOV AH,3FH ;讀文件
MOV CX,0FFF0H ;讀入最多64K
MOV DX,0 ;DS:DX指向文件緩沖區(qū)
INT 21H
POP DS
JC GETERR2 ;讀入文件出錯(cuò)轉(zhuǎn)GETERR2
MOV CCOUNT,AX ;實(shí)際讀入字符數(shù)存入CCOUNT中
RET
GETERR2:MOV DX,OFFSET MSG3 ;打開文件出錯(cuò)處理
CALL PROMPT
CALL KEYIN
MOV AX,4C00H
INT 21H ;
GETERR1:MOV DX,OFFSET MSG2 ;讀入文件出錯(cuò)處理
CALL PROMPT
CALL KEYIN
MOV AX,4C00H
INT 21H
GETFILE ENDP
;讀文件名子程序
SIN PROC
MOV AH,0AH
MOV DX,OFFSET FILENA
INT 21H ;讀文件名
XOR CH,CH
MOV CL,FILENA+1 ;取文件名長(zhǎng)度
LEA BX, FILENA+2
ADD BX,CX ;計(jì)算字符串結(jié)尾地址
MOV BYTE PTR [BX],'0' ;在字符串未加0
RET
SIN ENDP
;主循環(huán)程序
MAIN PROC
NEXT: CALL KEYIN ;讀鍵盤
CALL COMMAND ;命令分析
JNC NEXT ;非x鍵繼續(xù)循環(huán)
RET
MAIN ENDP
;命令分析子程序
COMMAND PROC
CMP AH,2DH ;2DH為x鍵的掃描碼
JNZ COM1 ;不是x鍵,轉(zhuǎn)COM1
STC ;值x鍵標(biāo)志
RET
COM1: CALL DOSUB ;轉(zhuǎn)命令散轉(zhuǎn)子程序
CLC
RET
COMMAND ENDP
;讀鍵子子程序
;這么簡(jiǎn)單的子程序最好使用宏
KEYIN PROC
MOV AH,0 ;讀鍵
INT 16H ;AH中為掃描碼
RET
KEYIN ENDP
;命令散轉(zhuǎn)子程序
DOSUB PROC
MOV AL,AH
MOV AH,0 ;將鍵掃描碼放入AX中
MOV BX,OFFSET KEYSUB ;BX指向KEYSUB
DOSUB1: CMP WORD PTR [BX],0
JZ DOSUBX ;KEYSUB表查完,即沒有找到轉(zhuǎn)DOSUBX
CMP AX,[BX]
JZ DOSUB2 ;找到掃描碼轉(zhuǎn)DOSUB2
ADD BX,4
JMP DOSUB1 ;
DOSUB2: ADD BX,2
MOV BX,[BX] ;取處理程序入口地址
JMP BX ;轉(zhuǎn)處理程序
DOSUBX: RET
;SUB1和SUB2均為功能鍵處理程序
;處理完后應(yīng)使用JMP DOSSUBX結(jié)束
;上箭頭鍵處理程序
SUB1:
CMP CURLINE,0
JZ SUB1X ;已到第一行,結(jié)束
DEC CURLINE ;向上一行
CALL SHOWCUR ;顯示當(dāng)前頁(yè)
SUB1X:
JMP DOSUBX
;下箭頭鍵處理程序
SUB2:
MOV AX,LENCT
DEC AX
DEC AX ;至少顯示一行
CMP AX,CURLINE ;已到最后一行
JZ SUB2X
INC CURLINE ;向下一行
CALL SHOWCUR ;顯示當(dāng)前頁(yè)
SUB2X:
JMP DOSUBX
DOSUB ENDP
;清屏子程序
CLSDISP PROC
MOV AX,0600H ;清屏
MOV CX,0
MOV DH,50
MOV DL,79
MOV BH,07H
INT 10H
RET
CLSDISP ENDP
;顯示方式初始化子程序
DISPINIT PROC
MOV AH,0003H ;文本方式 25x80
INT 10H
RET
DISPINIT ENDP
;顯示子程序
;輸入:DS:DX=字符串首地址,'$'結(jié)束
;如此簡(jiǎn)單的子程序最好使用宏
PROMPT PROC
MOV AH,09H ;
INT 21H ;
RET
PROMPT ENDP
;初始化子程序
INIT PROC
MOV AX,MYDAT
MOV DS,AX
MOV AX,BUFFER
MOV ES,AX
CALL DISPINIT ;顯示方式初始化
RET
INIT ENDP
CODE ENDS
END START
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -