本节内容:磁盘文件管理功能号调用应用举例。
■例1:显示文本文件内容t13-1.asm。
■例2:将键盘输入字符存入文件t13-2.asm。
■例3:文件拼接t13-3.asm。
13.2.1 例1:显示文本文件内容
动手实验93:写一个显示文本文件test.txt内容的程序。
在理解下面示例程序的基础上,自己独立编写源程序。编译完成后,在debug调试器中单步跟踪调试,以验证程序的正确性。
■算法分析:
第一步:以只读方式打开文件,并检测错误;
第二步:循环顺序读文件,每次读一个字符,把所读字符在屏幕上显示出来,直到文件结束;
第三步:关闭文件;
■流程图:如图13-1所示。
图13-1 显示文件内容
■示例代码67:
;程序名:t13-1.asm
; 写一个显示文本文件test.txt内容的程序
;txt文本文件结束符ASCII码为1AH
;子程序readch,每次从文件中顺序读一个字符,CF=1,读时错误,CF=0时,正确。
;主程序通过CF位判断是否读取成功
;考虑:万一文件没有结束符,读到的字符数为0时文件结束,并返回一个文件结束符
;=========================================================================
;功能:显示当前目录下的文本文件test.txt
;符号常量定义
eof=1ah ;文件结束符ASCII码值
assume cs:code,ds:data
data segment
fname db 'test.txt',0 ;文件名
;提示信息,07h=响铃
error1 db 'File not found',07h,0
error2 db 'Reading error',07h,0
buffer db ? ;1字节的缓冲区
handle dw ?
data ends
code segment
start:
mov ax,data
mov ds,ax
;只读方式打开文件
;置文件名首地址
mov dx,offset fname
;只读方式打开文件
mov ax,3d00h
int 21h
jnc open_ok ;CF=0打开成功转
mov si,offset error1 ;打开失败
;显示打开不成功提示信息
call dmess
jmp over ;结束
open_ok:
mov bx,ax ;保存文件柄
mov handle,ax
;从文件中读取一个字符
cont: ;从文件中读取一个字符
call readch
jc readerr ;如读错,则转
cmp al,eof ;读到文件结束符?
jz type_ok
call putch ;显示所读字符
jmp cont
readerr:
mov si,offset error2
call dmess ;显示错误提示信息
;
type_ok:
mov bx,handle
mov ah,3eh ;关闭文件
int 21h
over:
mov ax,4c00h
int 21h
;==============================================
;子程序,屏幕显示al内容
;2号调用功能,向屏幕写入dl内容
;入口参数dl
putch proc
push dx
mov dl,al
mov ah,2
int 21h
pop dx
ret
putch endp
;-------------------------------------
;子程序:从文件中读取一个字符
;子程序名:readch
readch proc
mov cx,1 ;置读字节数
mov dx,offset buffer ;置读缓冲区地址
mov ah,3fh ;置功能调用号
int 21h
jc readch2 ;cf=1
cmp ax,cx ;判断文件是否结束,ax为实际读到的字节数
mov al,eof ;设文件已结束,置文件结束符,此时CF=0
jb readch1 ;文件已结束,转
mov al,buffer ;取所读字符
readch1:
clc ;文件结束CF=0
readch2:
ret
readch endp
;---------------------------------------
;子程序显示一个以0结尾的字符串
;子程序名:dmess
;入口参数si=字符串首地址
;出口参数无
dmess proc
dmess1:
mov dl,[si]
inc si
or dl,dl
jz dmess2
mov ah,2
int 21h
jmp dmess1
dmess2:
ret
dmess endp
code ends
end start
提示
1.示例代码64每次只从文件读取一个字节数据,可以改为每次读取多个字节数据以提高效率。
2.如果文件内存在结束符,则结束符后的内容将无法读取,可以修改为不以结束符为判断依据。
请读者根据上述两点建议,尝试修改示例,独立完成。
13.2.2 例2:将键盘输入字符存入文件
动手实验94:写一个把键盘上输入的字符(直到CTRL+Z键,值1AH)写入一个文件的程序。
在理解下面示例程序的基础上,自己独立编写源程序。编译完成后,在debug调试器中单步跟踪调试,以验证程序的正确性。
■算法分析:
先建立指定文件,然后读键盘,把所有字符顺序写入文件,循环到文件结束符1AH,最后关闭文件。
■流程图:如图13-2所示。
图13-2 键盘输入存入文件
■示例代码68:
;程序名:t13-2.asm
;例2:写一个能把键盘上输入的字符(直到CTRL+Z键,值1AH)写入一个文件的程序。
;文件固定为当前根目录下的tast.txt。如果它已存在,则更新它
;===========================================================
;功能:把键盘上输入的字符全部存入
;文件test.txt。
;常量定义
eof=1ah ;结束符
assume cs:code,ds:data
data segment
fname db 'tast.txt',0 ;文件名
errmess1 db 'Can not create file',07h,'$'
errmess2 db 'Writing error',07h,'$'
buffer db ? ;一个字节缓冲区
handle dw ?
data ends
code segment
start:
mov ax,data
mov ds,ax
;新建文件
mov dx,offset fname
mov cx,0 ;建立普通文件
mov ah,3ch
int 21h
;检测错误
jnc crea_ok ;cf=0,建立成功跳转
;显示建立失败提示信息
mov dx,offset errmess1
;调用显示字符串子程序
call dispmess
jmp over
crea_ok:
mov handle,ax
mov bx,ax ;保存文件柄
cont:
;写法1
call getchar ;接收一个键
;保存AL=输入的ASCII码字符
push ax
call writech ;向文件写入字符
pop ax ;恢复ax值
jc werror ;cf=1,写入失败跳转
cmp al,eof ;判断是否结束
jnz cont ;不是,继续
jmp closef ;是,关闭文件
;写法2
;call getchar ;接收一个键
;判断是否结束,没有写入结束符
;cmp al,eof
;jz closef ;是,关闭文件
;call writech ;向文件写入字符
;jc werror ;cf=1,写入失败跳转
;jmp cont ;不是,继续
werror:
mov dx,offset errmess2 ;显示写入错误提示信息
call dispmess ;调用子程序,显示提示信息
closef:
mov bx,handle
mov ah,3eh ;调用功能号3eh,关闭文件
int 21h
over:
mov ax,4c00h
int 21h
;-----------------------------------------------
;子程序:向文件写入字符
;子程序名:writech
;入口参数al,读到的字符ASCII码
;调用40h功能号,写入文件
writech proc
mov buffer,al ;al移入缓冲区
mov dx,offset buffer ;缓冲区首地址
mov cx,1 ;每次写入一个字节
mov ah,40h ;置功能号
int 21h ;写
ret
writech endp
;-----------------------------------------
;子程序:接收按键字符
;子程序名:getchar
;调用1号功能
;入口参数无
;出口参数:AL=读到字符的代码ASCII码
getchar proc
mov ah,1
int 21h
ret
getchar endp
;-----------------------------------------
;子程序:显示字符串提示信息
;子程序名:dispmess
;入口参数:dx
;出口参数:无
dispmess proc
mov ah,09h
int 21h
ret
dispmess endp
code ends
end start
提示
1.尝试一次读取多个字节数据;
2.按回车键或退格键时,会有些特殊异常,该如何处理?
请读者尝试完成修改。
13.2.3 例3:文件拼接
动手实验95:写一个程序把文件test2.txt拼接到文件test1.txt上。
在理解下面示例程序的基础上,自己独立编写源程序。编译完成后,在debug调试器中单步跟踪调试,以验证程序的正确性。
■算法分析:
第一步:为写打开文件test1.txt;
第二步:为读打开文件test2.txt;
第三步:把文件test1的读写指针移到尾;
第四步:读test2的一块到缓冲区;
第五步:写一个块到test1.txt,如此循环,直到test2.txt结束;
第六步:关闭两个文件;
■流程图:如图13-3所示。
图13-3 文件拼接
■示例代码69:
;程序名:t13-3.asm
;例3:写一个程序把文件test2.txt拼接到文件test1.txt上
;功能:把文件test2拼接到文件test1之后
;==================================================
;符号常量定义
bufflen=512
assume cs:code,ds:data
;数据段
data segment
fname1 db 'test1.txt',0 ;文件名1
fname2 db 'test2.txt',0 ;文件名2
handle1 dw 0 ;存放文件1的文件柄
handle2 dw 0 ;存放文件2的文件柄
errmess1 db 'Can not open file',07h,'$'
errmess2 db 'Reading error',07h,'$'
errmess3 db 'Writing error',07h,'$'
buffer db bufflen dup(0)
data ends
;代码段
code segment
start:
mov ax,data
mov ds,ax
;打开文件1
mov dx,offset fname1 ;打开文件1
mov ax,3d01h ;只写方式打开
int 21h
jc error1
mov handle1,ax;打开成功,保存文件柄
;打开文件2
mov dx,offset fname2
mov ax,3d00h ;只读方式打开
int 21h
jc error2 ;打开失败
;打开成功,保存文件2的柄
mov handle2,ax
;移动文件内读写指针
mov bx,handle1
xor cx,cx
xor dx,dx
;移动文件1的指针到文件尾
mov ax,4202h
int 21h
;拼接文件
cont: ;读取文件2,并写入文件1
;指针移到读文件2
mov dx,offset buffer
mov cx,bufflen
mov bx,handle2
mov ah,3fh ;读文件2到缓冲区
int 21h
jc rerror ;读取失败
or ax,ax ;判断是否读完?
jz copyok ;是,转结束
;写入文件1
;写到文件1的长度等于读出的长度
mov cx,ax
mov bx,handle1
mov ah,40h ;写入文件1
int 21h
jnc cont ;写正确,继续
jmp werror ;写错误,跳转
werror:
mov dx,offset errmess3
call dispmess
jmp copyok
rerror:
mov dx,offset errmess2
call dispmess;显示读取错误提示信息
copyok:
mov bx,handle1 ;关闭文件1
mov ah,3eh
int 21h
mov bx,handle2 ;关闭文件2
mov ah,3eh
int 21h
error2:
mov bx,handle1 ;文件2打开失败
mov ah,3eh ;关闭文件1
int 21h
jmp over
error1:
mov dx,offset errmess1 ;显示提示信息
call dispmess
;jmp over
over:
mov ax,4c00h
int 21h
;------------------------------------
;子程序:显示字符串提示信息
;子程序名:dispmess
;入口参数:dx
;出口参数:无
dispmess proc
mov ah,09h
int 21h
ret
dispmess endp
code ends
end start
提示
1.可以尝试文件名有键盘输入;
2.可以尝试将两个文件合并为第三个文件;
请读者尝试完成修改。
练习
1、写一个复制指定文件程序。源文件名和目标文件名由用户从键盘输入。
2、写一个程序,把0000:0000地址开始的1024个字节写入文件MEM.DAT中。
3、写一个程序,把0000:0000地址开始的1024个字节,以双字为单位,以8字节十六进制ASCII码串的形式,顺序写入到文件MEM.TXT中,写入时每存放8字节ASCII码字符串换一行继续写入。
4、将例1改为每次从文件中读取指定字节数据。不以结束符为文件结尾标志。
5、将例2改成每次向文件写若干字节。并且屏蔽非可见字符。
6、修改程序例3,文件名由用户输入,并且把两个文件合并成第三个文件。
7、写一个能够显示指定文件长度的程序,文件名由键盘输入。
8、 写一个程序,统计文件中十进制数字符和字母符的个数,并以十进制ASCII字符串形式输出。
9、写一个比较文本文件的程序。假设文本文件由若干行组成,文本行以回车符0DH和换行符0AH结束。比较以行为单位按顺序进行。如果对应两行不等,那么就显示两行,并标上行号。
本文摘自编程达人系列教材《X86汇编语言基础教程》。