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

11 KiB
Raw Permalink Blame History

实验八:文件操作

一、基础性实验

1.1 实验目的

掌握DOS功能调用进行文件操作的方法包括文件的创建、写入、读取和删除。

1.2 实验内容

程序 1文件创建程序

使用功能号3CH创建新文件。

; 实验八-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向文件写入数据。

; 实验八-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读取文件内容。

; 实验八-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删除文件。

; 实验八-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文件复制程序

使用文件读写功能实现文件复制。

; 实验八-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重命名文件。

; 实验八-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=新文件名