Files
Operating-System/Experiment/asm-exp/实验八/文件操作实验.md
2026-06-25 00:09:09 +08:00

554 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 实验八:文件操作
## 一、基础性实验
### 1.1 实验目的
掌握DOS功能调用进行文件操作的方法包括文件的创建、写入、读取和删除。
### 1.2 实验内容
#### 程序 1文件创建程序
使用功能号3CH创建新文件。
```asm
; 实验八-1: 文件创建程序
; 功能: 使用DOS功能号3CH创建新文件
; 说明: AL=00H表示普通文件属性
DATAS SEGMENT
FILENAME DB 'testfile.txt', 0 ; 要创建的文件名
HANDLE DW ? ; 文件句柄
ERR_MSG DB 'File creation error!', 0DH, 0AH, '$'
OK_MSG DB 'File created successfully!', 0DH, 0AH, '$'
DATAS ENDS
STACKS SEGMENT
DB 64 DUP(?)
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES, DS:DATAS, SS:STACKS
START:
MOV AX, DATAS
MOV DS, AX
; 创建文件
; AH = 3CH (创建文件功能号)
; AL = 00H (普通文件属性)
; DS:DX = 文件名地址
LEA DX, FILENAME
MOV AH, 3CH
MOV AL, 00H
INT 21H
; 检查是否成功 (CF=0表示成功)
JNC CREATE_SUCCESS
; 创建失败,显示错误信息
LEA DX, ERR_MSG
MOV AH, 09H
INT 21H
JMP PROGRAM_END
CREATE_SUCCESS:
; 保存文件句柄
MOV HANDLE, AX
; 显示成功信息
LEA DX, OK_MSG
MOV AH, 09H
INT 21H
PROGRAM_END:
MOV AH, 4CH
INT 21H
CODES ENDS
END START
```
说明功能号3CH用于创建文件。如果文件已存在则将其长度截断为0。文件属性通过AL寄存器设置00H表示普通文件01H表示只读02H表示隐含04H表示系统文件。
#### 程序 2文件写入程序
使用功能号40H向文件写入数据。
```asm
; 实验八-2: 文件写入程序
; 功能: 使用DOS功能号40H向文件写入数据
DATAS SEGMENT
FILENAME DB 'testfile.txt', 0
HANDLE DW ?
DATA_TO_WRITE DB 'Hello, Assembly!', 0DH, 0AH, '$'
DATA_LEN EQU $-DATA_TO_WRITE
ERR_MSG DB 'File write error!', 0DH, 0AH, '$'
OK_MSG DB 'Data written successfully!', 0DH, 0AH, '$'
DATAS ENDS
STACKS SEGMENT
DB 64 DUP(?)
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES, DS:DATAS, SS:STACKS
START:
MOV AX, DATAS
MOV DS, AX
; 创建文件
LEA DX, FILENAME
MOV AH, 3CH
MOV AL, 00H
INT 21H
JC WRITE_ERROR
MOV HANDLE, AX
; 写入文件内容 (功能号40H)
; AH=40H, BX=句柄, CX=字节数, DS:DX=缓冲区
MOV BX, HANDLE
LEA DX, DATA_TO_WRITE
MOV CX, DATA_LEN
MOV AH, 40H
INT 21H
JNC WRITE_SUCCESS
WRITE_ERROR:
LEA DX, ERR_MSG
MOV AH, 09H
INT 21H
JMP CLOSE_FILE
WRITE_SUCCESS:
LEA DX, OK_MSG
MOV AH, 09H
INT 21H
CLOSE_FILE:
MOV BX, HANDLE
MOV AH, 3EH
INT 21H
MOV AH, 4CH
INT 21H
CODES ENDS
END START
```
#### 程序 3文件读取程序
使用功能号3FH读取文件内容。
```asm
; 实验八-3: 文件读取程序
; 功能: 使用DOS功能号3FH读取文件内容
DATAS SEGMENT
FILENAME DB 'testfile.txt', 0
HANDLE DW ?
BUFFER DB 100 DUP(?)
ERR_MSG DB 'File open error!', 0DH, 0AH, '$'
READ_ERR_MSG DB 'File read error!', 0DH, 0AH, '$'
OK_MSG DB 'File read successfully!', 0DH, 0AH, '$'
CR_LF DB 0DH, 0AH, '$'
DATAS ENDS
STACKS SEGMENT
DB 64 DUP(?)
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES, DS:DATAS, SS:STACKS
START:
MOV AX, DATAS
MOV DS, AX
; 打开文件 (功能号3DH)
LEA DX, FILENAME
MOV AH, 3DH
MOV AL, 00H
INT 21H
JNC OPEN_SUCCESS
LEA DX, ERR_MSG
MOV AH, 09H
INT 21H
JMP PROGRAM_END
OPEN_SUCCESS:
MOV HANDLE, AX
; 读取文件内容 (功能号3FH)
MOV BX, HANDLE
LEA DX, BUFFER
MOV CX, 100
MOV AH, 3FH
INT 21H
JNC READ_SUCCESS
LEA DX, READ_ERR_MSG
MOV AH, 09H
INT 21H
JMP CLOSE_FILE
READ_SUCCESS:
MOV CX, AX
LEA DI, BUFFER
MOV AH, 02H
DISPLAY_LOOP:
MOV DL, [DI]
INT 21H
INC DI
LOOP DISPLAY_LOOP
LEA DX, CR_LF
MOV AH, 09H
INT 21H
LEA DX, OK_MSG
MOV AH, 09H
INT 21H
CLOSE_FILE:
MOV BX, HANDLE
MOV AH, 3EH
INT 21H
PROGRAM_END:
MOV AH, 4CH
INT 21H
CODES ENDS
END START
```
#### 程序 4文件删除程序
使用功能号41H删除文件。
```asm
; 实验八-4: 文件删除程序
; 功能: 使用DOS功能号41H删除文件
DATAS SEGMENT
FILENAME DB 'testfile.txt', 0
ERR_MSG DB 'File delete error!', 0DH, 0AH, '$'
OK_MSG DB 'File deleted successfully!', 0DH, 0AH, '$'
NO_FILE_MSG DB 'File does not exist!', 0DH, 0AH, '$'
DATAS ENDS
STACKS SEGMENT
DB 64 DUP(?)
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES, DS:DATAS, SS:STACKS
START:
MOV AX, DATAS
MOV DS, AX
; 删除文件 (功能号41H)
; AH=41H, AL=00H, DS:DX=文件名
LEA DX, FILENAME
MOV AH, 41H
MOV AL, 00H
INT 21H
JNC DELETE_SUCCESS
CMP AX, 02H
JE FILE_NOT_FOUND
LEA DX, ERR_MSG
MOV AH, 09H
INT 21H
JMP PROGRAM_END
FILE_NOT_FOUND:
LEA DX, NO_FILE_MSG
MOV AH, 09H
INT 21H
JMP PROGRAM_END
DELETE_SUCCESS:
LEA DX, OK_MSG
MOV AH, 09H
INT 21H
PROGRAM_END:
MOV AH, 4CH
INT 21H
CODES ENDS
END START
```
### 1.3 实验结果
程序运行后文件创建、写入、读取和删除功能均正常工作。功能号3CH用于创建文件并将句柄返回到AX寄存器功能号40H通过BX指定句柄进行数据写入功能号3FH通过BX指定句柄进行数据读取实际读取字节数返回到AX功能号41H删除指定文件。所有操作通过CF标志位判断成功与否。
### 1.4 思考题
1. DOS功能调用中文件创建使用哪个功能号创建时如何设置文件属性
文件创建使用功能号3CHCreate File。文件属性通过AL寄存器设置
- AL=00H普通文件
- AL=01H只读文件
- AL=02H隐含文件
- AL=04H系统文件
- AL=07H隐藏+系统+只读文件
2. 文件打开函数3DH的AL参数有什么含义
文件打开函数3DH的AL参数指定访问模式
- AL=00H只读模式
- AL=01H只写模式
- AL=02H读写模式
- AL=10H打开时共享模式
3. 如何判断文件操作是否成功?
文件操作是否成功通过CF标志位和AX寄存器联合判断
- 如果CF=0且AX不是错误码表示操作成功
- 如果CF=1AX中包含错误码02H=文件未找到05H=访问被拒绝11H=文件名已存在等)
---
## 二、加强性实验
### 2.1 实验目的
掌握DOS文件功能的综合应用实现文件复制和重命名功能。
### 2.2 实验内容
#### 程序 1文件复制程序
使用文件读写功能实现文件复制。
```asm
; 实验八-5: 文件复制程序
; 功能: 使用DOS功能号实现文件复制
DATAS SEGMENT
SRC_FILE DB 'source.txt', 0
DST_FILE DB 'dest.txt', 0
HANDLE DW ?
BUFFER DB 512 DUP(?)
ERR_OPEN DB 'Cannot open source file!', 0DH, 0AH, '$'
ERR_READ DB 'Read error!', 0DH, 0AH, '$'
ERR_WRITE DB 'Write error!', 0DH, 0AH, '$'
OK_MSG DB 'File copied successfully!', 0DH, 0AH, '$'
DATAS ENDS
STACKS SEGMENT
DB 64 DUP(?)
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES, DS:DATAS, SS:STACKS
START:
MOV AX, DATAS
MOV DS, AX
; 打开源文件
LEA DX, SRC_FILE
MOV AH, 3DH
MOV AL, 00H
INT 21H
JNC OPEN_OK
LEA DX, ERR_OPEN
MOV AH, 09H
INT 21H
JMP PROGRAM_END
OPEN_OK:
MOV HANDLE, AX
; 创建目标文件
LEA DX, DST_FILE
MOV AH, 3CH
MOV AL, 00H
INT 21H
MOV BX, AX
JNC CREATE_OK
MOV AH, 3EH
MOV BX, HANDLE
INT 21H
LEA DX, ERR_OPEN
MOV AH, 09H
INT 21H
JMP PROGRAM_END
CREATE_OK:
COPY_LOOP:
; 读取源文件
MOV CX, 512
LEA DX, BUFFER
MOV AH, 3FH
INT 21H
JNC READ_OK
MOV AH, 3EH
MOV BX, HANDLE
INT 21H
MOV AH, 3EH
INT 21H
LEA DX, ERR_READ
MOV AH, 09H
INT 21H
JMP PROGRAM_END
READ_OK:
CMP AX, 0
JE COPY_COMPLETE
; 写入目标文件
MOV CX, AX
MOV AH, 40H
INT 21H
JNC WRITE_OK
MOV AH, 3EH
MOV BX, HANDLE
INT 21H
MOV AH, 3EH
INT 21H
LEA DX, ERR_WRITE
MOV AH, 09H
INT 21H
JMP PROGRAM_END
WRITE_OK:
JMP COPY_LOOP
COPY_COMPLETE:
MOV AH, 3EH
MOV BX, HANDLE
INT 21H
MOV AH, 3EH
INT 21H
LEA DX, OK_MSG
MOV AH, 09H
INT 21H
PROGRAM_END:
MOV AH, 4CH
INT 21H
CODES ENDS
END START
```
#### 程序 2文件重命名程序
使用功能号56H重命名文件。
```asm
; 实验八-6: 文件重命名程序
; 功能: 使用DOS功能号56H重命名文件
DATAS SEGMENT
OLD_NAME DB 'oldname.txt', 0
NEW_NAME DB 'newname.txt', 0
ERR_MSG DB 'Rename error!', 0DH, 0AH, '$'
OK_MSG DB 'File renamed successfully!', 0DH, 0AH, '$'
EXIST_MSG DB 'Target file already exists!', 0DH, 0AH, '$'
DATAS ENDS
STACKS SEGMENT
DB 64 DUP(?)
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES, DS:DATAS, SS:STACKS
START:
MOV AX, DATAS
MOV DS, AX
; 重命名文件 (功能号56H)
; AH=56H, DS:DX=原文件名, ES:DI=新文件名
LEA DX, OLD_NAME
LEA DI, NEW_NAME
MOV AH, 56H
INT 21H
JNC RENAME_SUCCESS
CMP AX, 11H
JE FILE_EXISTS
LEA DX, ERR_MSG
MOV AH, 09H
INT 21H
JMP PROGRAM_END
FILE_EXISTS:
LEA DX, EXIST_MSG
MOV AH, 09H
INT 21H
JMP PROGRAM_END
RENAME_SUCCESS:
LEA DX, OK_MSG
MOV AH, 09H
INT 21H
PROGRAM_END:
MOV AH, 4CH
INT 21H
CODES ENDS
END START
```
### 2.3 实验结果
程序运行后文件复制程序使用512字节缓冲区循环读取源文件并写入目标文件直到遇到EOFAX=0为止。文件重命名程序使用功能号56H完成文件重命名操作。
### 2.4 思考题
1. 文件复制程序中为什么要使用循环读取?
源文件可能很大一次读取全部内容会占用大量内存。使用循环读取每次只读取512字节可以处理任意大小的文件提高内存利用率。
2. 功能号56H除了重命名外还有什么用途
功能号56HRename/Move File主要用于文件重命名和移动文件到不同目录。它可以将文件从一个目录移动到另一个目录只要目标路径不同即可。
---
## 附录DOS文件操作功能号速查表
| 功能号 | 名称 | 主要寄存器 |
|--------|------|-----------|
| 3CH | 创建文件 | DS:DX=文件名, AL=属性, 返回:AX=句柄 |
| 3DH | 打开文件 | DS:DX=文件名, AL=访问模式, 返回:AX=句柄 |
| 3EH | 关闭文件 | BX=句柄 |
| 3FH | 读文件 | BX=句柄, CX=字节数, DS:DX=缓冲区, 返回:AX=实际读入字节数 |
| 40H | 写文件 | BX=句柄, CX=字节数, DS:DX=缓冲区, 返回:AX=实际写入字节数 |
| 41H | 删除文件 | DS:DX=文件名, AL=00H |
| 56H | 重命名文件 | DS:DX=原文件名, ES:DI=新文件名 |