使用汇编开发小巧的文件复制程序

介绍了使用ASM在DOS环境下实现的一个简单文件复制程序,该程序能够自动为已存在的目标文件名添加数字后缀以避免覆盖。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这是05年学ASM期间,同学用BT狂下大片,通过QQ传输给我。看着文件传输进度,突然萌发想法写了下面这个复制文件的小程序。

;程序    :复制文件程序,自动更名
;说明    :由于DOS不支持超过8个字符的文件名,因此不能复制本程序,因为本程序文件名已经是8个了,再加一个无法复制
_data    SEGMENT
mess    DB    
'Please,input file name.',0DH,0AH,24H
fnf        DB    0DH,0AH,
'File not found.',07H,0DH,0AH,24H
fce        DB    0DH,0AH,
'File copying error.',07H,0DH,0AH,24H
fre        DB    0DH,0AH,
'File reading error.',07H,0DH,0AH,24H
fwe        DB    0DH,0AH,
'File writting error.',07H,0DH,0AH,24H
fcs        DB    0DH,0AH,
'File copyed succeed.',0DH,0AH,24H
fbuffer    DB    
128    ;文件名缓冲区
        DB    
?
fname    DB    
128 DUP (?)    
fnum_s    DW    
?    ;源文件号
fnum_d    DW    
?    ;新文件号
buffer    DB     
512 DUP (?)    ;读写缓冲区
_data    ENDS
        ;
_text    SEGMENT
    ASSUME CS:_text,DS:_data
start:    MOV AX,_data
        MOV DS,AX
        PUSH DS
        POP ES
full0:    LEA DX,mess
        MOV AH,
9
        INT 21H
        CLD    ;充0,将上次输入的文件名清零
        MOV CX,
128    ;文件名最大128字符,包括回车符
        MOV AL,
0
        LEA DI,fname
        REP STOSB
        ;
-------------
        LEA DX,fbuffer    ;输入文件名
        MOV AH,0AH
        INT 21H
        ;
------------------
        MOV BL,[fbuffer
+1]    ;将输入文件名的最后一个回车符换成0,因为建立的文件名不能包括不可见字符
        XOR BH,BH
        MOV SI,OFFSET fname
        ADD SI,BX
        MOV BYTE PTR [SI],
0
        ;
---------------------
        LEA DX,fname    ;以只读方式打开源文件
        MOV AX,3D00H
        INT 21H
        JNC open    ;打开成功
        LEA DX,fnf    ;不成功,显示提示信息
        MOV AH,
9
        INT 21H
        JMP    full0    ;重新输入
        ;
--------------
open:    MOV fnum_s,AX    ;打开成功,保存源文件号
rebs:    MOV BL,[fbuffer
+1]    ;从‘.’到ODH前一格的所有字符退一格(包括‘.’)
        XOR BH,BH
        MOV SI,OFFSET fname
        ADD SI,BX
        DEC SI    ;SI指向ODH前一格
        INC BX    ;BX指向ODH后一格
        MOV [fbuffer
+1],BL    ;存入,为下次修改文件名做准备
        ;
---------------
        XOR CX,CX    ;CX为计数器,计算从‘.’到ODH前一格共几个字符(包括‘.’)
        MOV DI,SI
sourch:    CMP BYTE PTR [DI],
'.'    ;从后向前查找‘.’
        JE    ext    ;找到
        DEC DI    ;没找到,到前一格找
        INC CX
        JMP sourch
ext:    INC CX    ;找到后CX要加才会包括‘.’
        MOV DI,SI
        ADD DI,
1    ;DI指向SI的后一格
        STD
        REP MOVSB    ;开始执行,将文件名后缀退后一格(包括‘.’)
        ;
-------------------------------
        MOV AL,
'1'    ;将原本的‘.’改为‘1
testf:    PUSH AX
        MOV [DI],AL
        LEA DX,fname
        MOV AX,3D00H    ;以只读方式打开新文件名,判断是否已经有这个文件名了
        INT 21H
        JC    exist    ;打开失败,即这个文件名尚不存在,可以以这个文件名建立文件
        MOV BX,AX    ;存在,关闭打开的文件
        MOV AH,3EH
        INT 21H
        POP AX
        INC AL    ;‘
1’改为‘2
        CMP AL,
'9'+1    ;超出‘9’,文件名后缀再退一格
        JAE    rebs
        JMP testf    ;不超出的,继续判断是否已经有这个文件名了
exist:    MOV CX,
0
        LEA DX,fname
        MOV AH,3CH    ;建立普通新文件
        INT 21H
        JNC save    ;建立成功,保存新文件号
        LEA DX,fce    ;不成功,显示错误信息
        MOV AH,
9
        INT 21H
        JMP full0    ;重新输入
save:    MOV fnum_d,AX    ;保存新文件号
        MOV AX,3D01H    ;以只写方式打开新文件
        INT 21H
        ;
---------------------
readf:    MOV BX,fnum_s    ;取源文件号
        MOV CX,
512    ;读出512个字符
        MOV DX,OFFSET buffer
        MOV AH,3FH
        INT 21H
        JNC writef    ;读成功,则写
        LEA DX,fre    ;不成功,显示错误信息,关闭文件,并结束程序
        MOV AH,
9
        INT 21H
        JMP    exit
        ;
--------------------------
writef:    MOV BX,fnum_d    ;取新文件号
        MOV CX,AX    ;按实际读入字数写文件
        MOV AH,40H
        INT 21H
        JNC cmpcx    ;写成功
        LEA DX,fwe    ;不成功,显示错误信息,关闭文件,并结束程序
        MOV AH,
9
        INT 21H
        JMP exit
cmpcx:    CMP CX,
512    ;判断实际读入的字数是不是512
        JE    readf    ;如果是512,说明还没读到文件尾
        ;
        LEA DX,fcs    ;显示‘复制成功’
        MOV AH,
9
        INT 21H
        ;
exit:    MOV AH,3EH    ;关闭文件
        INT 21H
        MOV BX,fnum_s
        MOV AH,3EH
        INT 21H
        MOV AX,4C00H
        INT 21H
        ;
_text    ENDS
    END    start

源代码 3.47KB,生成的EXE  1.52KB,这个是汇编的一大优点啊,哈哈。

csdn 怎么插入的代码没汇编选项?只好用 C# 的代替下

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值