📄 edit.asm
字号:
DATAS SEGMENT
;此处输入数据段代码
mode DB 03,80,25 ;显示方式以及显示大小
color DB 1FH ;窗口的背景色和前景色
cursor DB 0,0 ;光标的位置(行和列)
position DB 0,0,0,0 ;光标的当前位置(行和列)(在显示范围内)
;以及左上角字符所在的行和列,为ReDisplay传递参数
place DB 0,0 ;屏幕第一行显示的是第多少行
insert DB 1 ;标示事Insert还是Override
ctrlKey DB 0 ;ctrl是否按下,1表示按下
fileName DB 30,0,30 DUP (?),0 ;文件的路径及文件名
fileName1 DB 'E:\program\data.txt',0
handle DW ? ;文件句柄
mesg1 DB 'Please input file name:','$'
mesg2 DB 'Failed to open file!!','$'
mesg3 DB 'Failed to read file!!','$'
DATAS ENDS
EDATAS SEGMENT
;附加数据段,定义缓冲区
;buf的第一个字节为已经输入的行数(总行数为200)
;后面的为一个二维数组,每一行记录一行字符,每一行的
;第一字符为该行输入的字符数
buf DB 1,200 DUP (0,200 DUP (' '))
bufsize DB 200,200 ;能输入的最大行数和列数
ctrlInfile DB 0DH,0AH,0
EDATAS ENDS
STACKS SEGMENT
;此处输入堆栈段代码
stack DW 300 DUP (?)
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
;----------------------------------------------
;接收键盘的输入(调用BIOS)
;----------------------------------------------
INPUT MACRO
;取键盘的状态字
MOV AH, 02H
INT 16H
TEST AL, 04H ;测试Ctrl键
JZ getChar
MOV ctrlKey, 1
getChar:
MOV AH,0
INT 16H
ENDM
;----------------------------------------------
;读取光标的当前位置
;----------------------------------------------
READCURSOR MACRO
MOV BH, 0
MOV AH, 3H
INT 10H
MOV position, DH
MOV position[1], DL
ENDM
;----------------------------------------------
MOV AX,DATAS
MOV DS,AX
MOV AX, EDATAS
MOV ES, AX
MOV AX, STACKS
MOV SS, AX
;此处输入代码段代码
;初始化窗口
CALL InitWindow
MOV AH,0CH ;清空键盘的缓冲区
MOV AL,00H
INT 21H
;接收输入并显示
inputAndDisplay:
INPUT
CMP AH, 01H ;按下Esc键
JZ exit
CMP ctrlKey, 1 ;判断是否按下crtl
JZ others
CMP AL, 0
JZ contrl
CMP AL, 0DH
JZ contrl
CMP AH, 0EH
JZ contrl
CALL SaveAndDisplay ;保存并显示输入
JMP inputAndDisplay
contrl:
CMP AL, 0DH
JNZ n1
CALL crlf ;回车换行
JMP inputAndDisplay
n1:
CMP AH, 48H
JNZ n2
CALL up ;↑,光标向上移动一行
JMP inputAndDisplay
n2:
CMP AH, 4BH
JNZ n3
CALL left ;←,光标向左移动一列
JMP inputAndDisplay
n3:
CMP AH, 4DH
JNZ n4
CALL right ;→,光标向右移动一列
JMP inputAndDisplay
n4:
CMP AH, 50H
JNZ n5
CALL down ;↓,光标向下移动一行
JMP inputAndDisplay
n5:
CMP AH, 53H ;Delete键
JNZ n6
CALL Delete
JMP inputAndDisplay
n6:
CMP AH, 0EH ;Backspace键
JNZ n7
CALL Backspace
JMP inputAndDisplay
n7:
CMP AH, 3BH ;F1打开文件
JNZ n8
CALL openFile
JMP inputAndDisplay
n8:
CMP AH, 3CH ;F2保存文件
JNZ inputAndDisplay
CALL saveFile
JMP inputAndDisplay
others:
CMP AL, 's'
JNZ inputAndDisplay
CALL saveFile
JMP inputAndDisplay
Exit: ;推出
MOV AH,4CH
INT 21H
;----------------------------------------------
;初始化窗口
;----------------------------------------------
InitWindow PROC NEAR
PUSH AX
PUSH BX
PUSH CX
PUSH DX
MOV AL, mode ;设置显示方式
MOV AH, 0
INT 10H
MOV AH, 06H ;设置背景色
MOV AL, 0
MOV BH, color
MOV CH, 0
MOV CL, 0
MOV DH, 24
MOV DL, 79
INT 10H
POP DX
POP CX
POP BX
POP AX
RET
InitWindow ENDP
;----------------------------------------------
;保存输入并显示
;----------------------------------------------
SaveAndDisplay PROC NEAR
PUSH BX
PUSH CX
PUSH DX
PUSH AX
;读取光标的当前位置
READCURSOR
;获得该行已经输入的字符数[cursor]*(ES:[bufsize+1]+1)
MOV AL, cursor
MOV BL, ES:bufsize[1]
INC BL
MUL BL
MOV DI, AX
INC DI
MOV BL, ES:buf[DI]
CMP BL, ES:bufsize[1]
JZ over ;该行已经不能再输入的字符
MOV BH, cursor[1] ;获得光标的位置(列数)
INC BH
CMP BH, BL ;比较[cursor+1]和已经输入的字符数
JBE moveChar1
MOV CL, cursor[1]
MOV ES:buf[DI], CL
JMP saveChar
moveChar1:
CALL MoveChar ;移动字符
saveChar: ;保存输入的字符
INC cursor[1] ;重新设置cursor
INC ES:buf[DI] ;重设已经输入的字符数
MOV CL, ES:buf[DI]
MOV CH, 0
MOV SI, CX ;保存输入的字符数
INC BL
MOV CL, BH
MOV CH, 0
ADD DI, CX
POP AX
MOV ES:buf[DI], AL
;对光标的位置进行判断
MOV AL, position[1]
INC AL
CMP AL, mode[1]
JNZ display
;重新显示每一行
MOV AL, cursor ;设置参数
SUB AL, position
MOV position[2], AL
MOV AL, cursor[1]
SUB AL, position[1]
MOV position[3], AL
CALL ReDisplay ;光标在最右边
JMP over
display:
;显示
;MOV CL, BL
;SUB CL, BH
;MOV CH, 0
;INC CX
;MOV CX, 1
MOV CX, SI
SUB CL, cursor[1]
INC CX
CMP CX, 80
JB d1
MOV CX, 80
SUB CL, position[1]
;MOV CL, mode[1]
;SUB CL, position[1]
;MOV CH, 0
;DEC CX
d1:
LEA BP, ES:buf[DI]
MOV AL, 1
MOV BL, 1FH
MOV BH, 0
MOV AH, 13H
INT 10H
;重置光标
MOV BH, 0
MOV DH, position
MOV DL, position[1]
INC DL
MOV AH, 02H
INT 10H
over:
POP DX
POP CX
POP BX
RET
SaveAndDisplay ENDP
;----------------------------------------------
;将缓冲区的字符顺次向后移一个(光标后的字符)
;----------------------------------------------
MoveChar PROC NEAR
PUSH CX
PUSH DI
;计算该行最后一个字符的偏移地址
MOV CL, BL
MOV CH, 0 ;DX中是该行的字符数
ADD DI, CX
MOV CL, BL
SUB CL, BH
INC CL
n:
MOV CH, ES:buf[DI]
MOV ES:buf[DI+1], CH
DEC DI
DEC CL
JNZ n
POP DI
POP CX
RET
MoveChar ENDP
;----------------------------------------------
;显示[cursor+1]-79到[cursor+1]之间的字符(所有的行)
;调用之前要设置position的值
;----------------------------------------------
ReDisplay PROC NEAR
PUSH CX
PUSH AX
PUSH BX
PUSH DX
PUSH DI
PUSH SI
MOV BL, ES:bufsize[1]
INC BL
MOV BH, 0
MOV DI, BX ;设置增量
;计算左上角字符的地址
MOV AL, position[2]
MUL BL ;*增量
MOV BL, position[3]
MOV BH, 0
ADD AX, BX
INC AX
INC AX
MOV BP, AX
MOV AL, ES:buf ;读取已经输入的行数
SUB AL, position[2]
MOV AH, 0
MOV SI, AX
;INC SI
;MOV DL, ES:bufsize[1]
;MOV DH, 0
MOV DH, 0
;MOV DL, 0
nextLine:
MOV DL, 0
MOV CX, 80
MOV AL, 1
MOV BL, 1FH
MOV BH, 0
MOV AH, 13H
INT 10H
ADD BP, DI
INC DH
DEC SI
JNZ nextLine
;置光标的位置
MOV BH, 0
MOV DH, position
MOV DL, position[1]
MOV AH, 02H
INT 10H
POP SI
POP DI
POP DX
POP BX
POP AX
POP CX
RET
ReDisplay ENDP
;----------------------------------------------
;----------------------------------------------
crlf PROC NEAR
PUSH DX
PUSH AX
;读取光标的当前位置
INC cursor ;设置行号
MOV cursor[1], 0
INC ES:buf
MOV BH, 0 ;读取光标的位置
MOV AH, 03H
INT 10H
MOV DL, 0H
INC DH
MOV AH, 02H
INT 10H
READCURSOR
MOV AL, cursor ;设置参数
SUB AL, position
MOV position[2], AL
MOV position[3], 0
CALL ReDisplay
POP AX
POP DX
RET
crlf ENDP
;----------------------------------------------
;光标向上移动
;----------------------------------------------
up PROC NEAR
PUSH AX
MOV AL, cursor
CMP AL, 0
JZ up2 ;如果光标在第一行则不能移动
MOV BH, 0 ;读取光标的位置
MOV AH, 03H
INT 10H
CMP DH, 0 ;光标在屏幕的最上方
JNZ up1
DEC cursor ;设置参数
INC DH
MOV position, DH
MOV position[1], DL
MOV AH, cursor
SUB AH, DH
MOV position[2], AH
MOV AH, cursor[1]
SUB AH, DL
MOV position[3], AH
CALL ReDisplay ;重新显示每一行
JMP up2
up1:
DEC cursor
DEC DH ;重置光标的位置
MOV AH, 02H
INT 10H
up2:
POP AX
RET
up ENDP
;----------------------------------------------
;光标向左移动
;----------------------------------------------
left PROC NEAR
MOV BH, 0 ;读取光标的位置
MOV AH, 03H
INT 10H
CMP DL, 0
JNZ left1
CMP cursor[1], 0
JZ left2
DEC cursor[1] ;设置参数
;DEC DL
MOV position, DH
MOV position[1], DL
MOV AH, cursor
SUB AH, DH
MOV position[2], AH
MOV AH, cursor[1]
SUB AH, DL
MOV position[3], AH
CALL ReDisplay ;重新显示每一行
JMP left2
left1:
DEC cursor[1]
DEC DL
MOV AH, 02H
INT 10H
left2:
RET
left ENDP
;----------------------------------------------
;光标向右移动
;----------------------------------------------
right PROC NEAR
MOV BH, 0 ;读取光标的位置
MOV AH, 03H
INT 10H
CMP DL, 79
JNZ right1
CMP cursor[1], 199
JZ right2
INC cursor[1] ;设置参数
;DEC DL
MOV position, DH
MOV position[1], DL
MOV AH, cursor
SUB AH, DH
MOV position[2], AH
MOV AH, cursor[1]
SUB AH, DL
MOV position[3], AH
CALL ReDisplay ;重新显示每一行
JMP right2
right1:
INC cursor[1]
INC DL
MOV AH, 02H
INT 10H
right2:
RET
right ENDP
;----------------------------------------------
;光标向下移动
;----------------------------------------------
down PROC NEAR
MOV BH, 0 ;读取光标的位置
MOV AH, 03H
INT 10H
MOV AH, mode[2]
DEC AH
CMP DH, AH ;判断光标是否在屏幕的最下方
JNZ down1
INC cursor ;设置参数
DEC DH
MOV position, DH
MOV position[1], DL
MOV AH, cursor
SUB AH, DH
MOV position[2], AH
MOV AH, cursor[1]
SUB AH, DL
MOV position[3], AH
CALL ReDisplay ;重新显示每一行
down1:
INC cursor
INC DH ;重置光标的位置
MOV AH, 02H
INT 10H
down2:
RET
down ENDP
;----------------------------------------------
;删除光标处的字符
;----------------------------------------------
Delete PROC NEAR
;计算该行字符数的地址
MOV AL, cursor
MOV BL, ES:bufsize[1]
INC BL
MUL BL
INC AX
MOV DI, AX
;判断需不需要删除
MOV CL, ES:buf[DI]
;DEC CL
SUB CL, cursor[1]
JBE delete2
;计算光标处对应的缓冲区地址
DEC ES:buf[DI] ;字符数减一个
MOV AL, cursor[1]
MOV AH, 0
ADD DI, AX
INC DI
MOV BX, DI
;移动缓冲区的内容
MOV CH, 0 ;CX保存移动字符数
MOV SI, CX
delete1:
MOV AL, ES:buf[DI+1]
MOV ES:buf[DI], AL
INC DI
DEC CX
JNZ delete1
MOV ES:buf[DI], ' '
;重新显示光标后的字符
READCURSOR
MOV CX, SI
LEA BP, ES:buf[BX]
MOV AL, 1
MOV BH, 0
MOV BL, 1FH
MOV AH, 13H
INT 10H
;重置光标
MOV BH, 0
MOV DH, position
MOV DL, position[1]
MOV AH, 02H
INT 10H
delete2:
RET
Delete ENDP
;----------------------------------------------
;用Backspace删除光标前一个的字符
;----------------------------------------------
Backspace PROC NEAR
;计算该行字符数的地址
MOV AL, cursor
MOV BL, ES:bufsize[1]
INC BL
MUL BL
INC AX
MOV DI, AX
;判断需不需要删除
MOV CL, ES:buf[DI]
;DEC CL
SUB CL, cursor[1]
JB delete2
;计算光标处对应的缓冲区地址
DEC ES:buf[DI] ;字符数减一个
MOV AL, cursor[1]
MOV AH, 0
ADD DI, AX
;INC DI
MOV BX, DI
;移动缓冲区的内容
INC CL
MOV CH, 0 ;CX保存移动字符数
MOV SI, CX
backspace1:
MOV AL, ES:buf[DI+1]
MOV ES:buf[DI], AL
INC DI
DEC CX
JNZ backspace1
MOV ES:buf[DI], ' '
;重新显示光标后的字符
READCURSOR
DEC DL
MOV CX, SI
LEA BP, ES:buf[BX]
MOV AL, 1
MOV BH, 0
MOV BL, 1FH
MOV AH, 13H
INT 10H
;重置光标
DEC cursor[1]
MOV BH, 0
MOV DH, position
MOV DL, position[1]
DEC DL
MOV AH, 02H
INT 10H
backspace2:
RET
Backspace ENDP
;---------------------------------------------
;打开一个文件
;---------------------------------------------
openFile PROC NEAR
;清空窗口
MOV AH, 06H
MOV AL, 0
MOV BH, 04H
MOV CH, 0
MOV CL, 0
MOV DH, 24
MOV DL, 79
INT 10H
;输出提示信息
MOV BH, 0 ;置光标
MOV DX, 0
MOV AH, 02H
INT 10H
MOV AH, 09H
MOV DX, OFFSET mesg1
INT 21H
;输入文件名
MOV AH, 0AH
MOV DX, OFFSET fileName
INT 21H
MOV BL, fileName[1]
ADD BL, 2
MOV BH, 0
MOV fileName[BX], 0
;打开文件
MOV AH, 3DH
MOV AL, 2 ;设置访问模式
LEA DX, fileName[2]
INT 21H
JNC read
MOV DL, 0AH
MOV AH, 02H
INT 21H
MOV DL, 0DH
MOV AH, 02H
INT 21H
LEA DX, mesg2 ;打开文件失败
MOV AH, 09H
INT 21H
JMP EXIT
read:
MOV handle, AX ;保存文件句柄
PUSH DS
PUSH ES
MOV BX, ES ;交换DS和ES
MOV AX, DS
MOV DS, BX
MOV ES, AX
MOV SI, 1
next1:
INC DI
MOV AH, 3FH ;读入文件内容
MOV BX, ES:handle
;MOV CL, DS:bufsize[1]
;MOV CH, 0
MOV CX, 1
LEA DX, DS:buf[DI]
INT 21H
JNC next2
MOV DL, 0AH
MOV AH, 02H
INT 21H
MOV DL, 0DH
MOV AH, 02H
INT 21H
LEA DX, ES:mesg3 ;读入文件失败
MOV AH, 09H
INT 21H
JMP EXIT
next2:
CMP AX, 0
JZ next4
CMP DS:buf[DI], 0AH
JZ next3
CMP DS:buf[DI], 0DH
JZ next3
INC DS:buf[SI]
JMP next1
next3:
MOV DS:buf[DI], ' '
MOV AH, 3FH
MOV CX, 1
LEA DX, DS:ctrlInfile[2]
INT 21H
INC DS:buf
ADD SI, 201
;ADD DI, 201
MOV DI, SI
JMP next1
JNZ next1
next4:
POP ES
POP DS
;关闭文件
MOV AH, 3EH
INT 21H
DEC ES:buf
CALL InitWindow
CALL ReDisplay
RET
openFile ENDP
;----------------------------------------------
;保存文件
;----------------------------------------------
saveFile PROC NEAR
PUSH DS
;打开文件
MOV AH, 3DH
MOV AL, 2
LEA DX, fileName1
INT 21H
MOV BX, AX
MOV AL, ES:buf ;循环次数
MOV AH, 0
MOV SI, AX
MOV DI, 1
MOV AX, ES
MOV DS, AX
L1:
MOV CL, ES:buf[DI]
MOV CH, 0
LEA DX, ES:buf[DI+1]
;LEA DX, ES:buf[DI]
MOV AH, 40H
INT 21H
LEA DX, ES:ctrlInfile
MOV AH, 40H
MOV CX, 2
INT 21H
ADD DI,201
DEC SI
JNZ L1
;关闭文件
MOV AH, 3EH
INT 21H
POP DS
RET
saveFile ENDP
;----------------------------------------------
CODES ENDS
END START
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -