📄 1.asm
字号:
stack segment stack
db 256 dup(0)
stack ends
;-------------------------------------------------
DATA SEGMENT
maxpl equ 10 ;密码最大长度
maxnl equ 20 ;名字最大长度
namepar label byte ;name parameter list
db maxnl
namelen db ?
namerec db maxnl dup(' ') ;entered name
pwdpar label byte ;password parameter list
db maxpl
pwdlen db ?
pwdrec db maxpl dup(' ') ;entered password
buf db maxnl+maxpl dup(' '),0ah,0dh ;读取一个记录的缓冲
newone db 0 ;是否创建新账号
handle dw ? ;文件句柄
pathnam db 'd:/users.dat',0 ;文件存取目录
row db 01 ;光标所在的行
id db 0 ;当前用户名的序号,修改密码时用
msgname db 'please enter login name:(enter <new> to create a new account)','$'
msgpwd db 'please enter password:','$'
newname db 'login name? ','$'
newpwd db 'passeord? ','$'
menumsg db '* * * 1:modify password * * *',0ah,0dh
db '* * * 2:list all users * * *',0ah,0dh
db '* * * 3:quit * * *','$'
crtmsg db '* * * fail to create file * * *','$'
newmsg db '* * * fail to create new account * * *','$'
opnmsg db '* * * open file error * * *','$'
wrtmsg db '* * * write file error * * *','$'
redmsg db '* * * read file error * * *','$'
clsmsg db '* * * close file error * * *','$'
logmsg db '* * * name or password is wrong * * *','$'
renmsg db '* * * this name is used,please enter again * * *','$'
gdbmsg db 0ah,0dh,'Goodbye!!!','$'
tilmsg db 'username password','$'
modmsg db '* * * success! * * *','$'
mermsg db '* * * fail,retry! * * *','$'
errcde db 0 ;0:正常, 1:出错, 2:测试打开
;3:用户名重复 4:已读到文件末尾
data ends
;-------------------------------------------------
code segment
main proc far
assume cs:code,ds:data,ss:stack,es:data
start:
push ds
sub ax,ax
push ax
mov ax,data
mov ds,ax
mov es,ax
goback: mov row,01
mov ax,0600h
call scren ;clear screen
call curs ;set cursor
gb1: mov errcde,0
call inname ;input name
cmp errcde,01
jz done3
call isinnew ;检查输入密码时输入的是否是new,是则创建新账号
cmp newone,1
je co
lea dx,msgpwd
mov ah,09
int 21h
call inpwd ;input password
call login ;检查用户名和密码是否正确
cmp errcde,0
jz conti1
lea dx,logmsg
mov ah,09
int 21h
call scrl
jmp gb1
conti1: call showmenu ;显示选择菜单
jmp done3
co: call createone ;添加新账号
cmp errcde,0
jz goback
done3: ret
main endp
;-------------------------------------------------
inname proc near ;输入的用户名存在namerec里
lea dx,msgname ;显示输入用户名提示
mov ah,09
int 21h
call scrl
lea dx,namepar
mov ah,10
int 21h
call scrl
cmp namelen,0
jne don
mov errcde,01
don: ret
inname endp
;-------------------------------------------------
inpwd proc near ;输入的密码存在pwdrec里
lea bx,pwdrec
mov cl,maxpl
lp0: mov ah,07
int 21h
cmp al,0dh ;回车结束
je done0
cmp al,08 ;backspace
je backspace0
mov [bx],al
mov dl,'*'
mov ah,02h
int 21h
inc bx
dec cl
jnz lp0
jmp done0
backspace0:
cmp cl,maxpl ;如果没有输入字符或已经退到顶,则不执行一下代码
je lp0
mov dl,08h ;先退格
mov ah,02h
int 21h
mov dl,00h ;输出NUL
int 21h
mov dl,08h ;再退格,达到键盘上Backspace的效果
int 21h
inc cl
dec bx
mov byte ptr [bx],' '
jmp lp0
done0: mov ch,maxpl
sub ch,cl
mov pwdlen,ch
call scrl
ret
inpwd endp
;-------------------------------------------------
isinnew proc near ;检查namerec里输入的是否是new
cmp namelen,03
jne not0
lea bx,namerec
cmp byte ptr [bx],'n'
jne not0
inc bx
cmp byte ptr [bx],'e'
jne not0
inc bx
cmp byte ptr [bx],'w'
jne not0
mov newone,1
jmp done2
not0: mov newone,0
done2: ret
isinnew endp
;-------------------------------------------------
createone proc near ;创建新账号
rein: lea dx,newname
mov ah,09
int 21h
lea dx,namepar ;输入新的用户名
mov ah,10
int 21h
cmp namelen,0
jne continue2
ret
continue2:
call scrl
mov errcde,02 ;用户测试打开
call openf
cmp errcde,0 ;打开失败,无须检查用户名是否重复
jnz continue1
call findnam
mov id,0
call closef
cmp errcde,03 ;用户名重复
jnz continue1
lea dx,renmsg
mov ah,09
int 21h
call scrl
jmp rein
continue1:
mov errcde,0
lea dx,newpwd
mov ah,09
int 21h
call inpwd
call scrl
call tranc
mov errcde,02 ;用户测试打开
call openf
cmp errcde,0 ;打开失败,尝试创建新文件
jz addone
mov errcde,0
call createf
cmp errcde,0 ;创建失败
jnz done4
call writef
jmp done4
addone: mov ah,42h ;把文件指针移到末尾
mov al,2 ;绝对倒移方式2
mov bx,handle
mov cx,0 ;offset
mov dx,0
int 21h ;将文件指针移到文件尾,返回dx:ax=文件长度
jc err
call writef
jmp done4
err: lea dx,newmsg
call error
done4: call closef
ret
createone endp
;-------------------------------------------------
tranc proc near
mov al,20h ;blank for storing
sub ch,ch
mov cl,namelen ;length
lea di,namerec
add di,cx ;address+length
neg cx ;calculate remaining
add cx,20 ;length
rep stosb ;set to blank
mov al,20h
sub ch,ch
mov cl,pwdlen
lea di,pwdrec
add di,cx
neg cx
add cx,10
rep stosb
ret
tranc endp
;-------------------------------------------------
login proc near
mov id,0
mov errcde,0 ;清楚错误码
call openf
cmp errcde,0
jnz done5
call findnam
cmp errcde,03 ;找到名字
jnz done5
call checkpwd
cmp errcde,0 ;密码正确?
jnz done5
mov errcde,0
call closef
ret
done5: mov errcde,01
ret
login endp
;-------------------------------------------------
createf proc near
mov ah,3ch ;request create
mov cx,0 ;normal attribute
lea dx,pathnam
int 21h
jc a1 ;error
mov handle,ax ;no,save handle
ret
a1: lea dx,crtmsg ;error message
call error
ret
createf endp
;-------------------------------------------------
showmenu proc near
conti2: mov row,02
mov ax,0600h
call scren ;clear screen
call curs ;set cursor
lea dx,menumsg
mov ah,09
int 21h
call scrl
call scrl
mov dl,'?'
mov ah,02
int 21h
mov ah,01
int 21h
sub al,'0' ;ASCII to number
cmp al,1
jz mod1 ;modify password
cmp al,2
jz list1 ;list all users
lea dx,gdbmsg
mov ah,09
int 21h
call scrl
done7: ret
mod1: call modpwd
jmp conti2
list1: call lstall
jmp conti2
showmenu endp
;-------------------------------------------------
openf proc near ;用于测试文件存在而打开时,给errcde赋值2
mov ah,3dh ;request create
mov al,02 ;read and write
lea dx,pathnam
int 21h
jc b1 ;error
mov handle,ax ;no,save handle
mov errcde,0
ret
b1: cmp errcde,02 ;是测试打开
jz b2
lea dx,opnmsg ;error message
call error
jmp b3
b2: mov errcde,01
b3: ret
openf endp
;-------------------------------------------------
readf proc near
mov ah,3fh ;request read
mov bx,handle
mov cx,maxnl+maxpl ;for name,password and CR/LF
lea dx,buf
int 21h
jc c1 ;error no read?
cmp ax,0 ;end of file?读取了0字节
je c2
ret
c1: lea dx,redmsg
call error
ret
c2: mov errcde,04 ;标示已经读到文件末尾
ret
readf endp
;-------------------------------------------------
writef proc near
cld ;DF=0,增量方向
lea si,namerec ;复制namerec到buf
lea di,buf
mov cx,maxnl
rep movsb
lea si,pwdrec ;复制pwdrec到buf+maxnl
lea di,buf+maxnl
mov cx,maxpl
rep movsb
mov ah,40h ;request write
mov bx,handle
mov cx,maxnl+maxpl ;for buf
lea dx,buf
int 21h
jc d1 ;valid write?
;mov namelen,0
;mov pwdlen,0
;lea di,buf ;清空buf
;mov al,' '
;mov cx,maxnl+maxpl
;rep stosb
ret
d1: lea dx,wrtmsg ;no
call error ;call error routine
ret
writef endp
;-------------------------------------------------
closef proc near
mov ah,3eh ;request close
mov bx,handle
int 21h
ret
d2: lea dx,clsmsg ;no
call error ;call error routine
ret
closef endp
;-------------------------------------------------
findnam proc near
call tranc
next1: inc id ;用户序号加一
call readf
cmp errcde,04 ;是否已读到文件末尾
jz f1
lea si,buf
lea di,namerec
xor cx,cx
mov cl,maxnl
repe cmpsb ;相同时ZF=1,repe继续执行
jnz next1 ;CX为0,说明比较到最后都相同
mov errcde,03 ;找到相同的名字
jmp f2
f1: mov errcde,0 ;未找到相同的名字
f2: ret
findnam endp
;-------------------------------------------------
checkpwd proc near
mov errcde,0
lea si,buf+maxnl
lea di,pwdrec
xor cx,cx
mov cl,maxpl
repe cmpsb
jnz done6
mov errcde,0
ret
done6: mov errcde,01 ;密码不对
ret
checkpwd endp
;-------------------------------------------------
modpwd proc near
call scrl
lea dx,newpwd
mov ah,09
int 21h
call inpwd
call openf
mov al,maxnl+maxpl
mov cl,id
dec cl
mul cl ;计算出该用户记录在文件中的偏移量
;add cl,maxnl ;移动到保存密码的位置
mov bx,handle
mov cx,0
mov dx,ax
mov al,0 ;从文件头开始的绝对位移
mov ah,42h
int 21h
jc err4
cld
call tranc
call writef
cmp errcde,01
jz done9
lea dx,modmsg
jmp gogo
err4: lea dx,mermsg
gogo: mov ah,09
int 21h
done9: call closef
mov ah,07
int 21h
ret
modpwd endp
;-------------------------------------------------
lstall proc near
call scrl
lea dx,tilmsg
mov ah,09
int 21h
call scrl
call openf
next3: call readf
cmp errcde,04 ;已到文件末尾
jz done8
mov ah,40h ;request write
mov bx,01 ;set handle,01为标准输出设备
mov cx,32 ;for length
lea dx,buf
int 21h
jmp next3
done8: call closef
mov ah,07
int 21h
ret
lstall endp
;-------------------------------------------------
scrl proc near
cmp row,18h ;bottom of screen?
jae c3 ;yes,bypass
inc row ;no,add to row
c3: mov ax,0601h ;scroll one row
call scren
call curs ;reset cursor
ret
scrl endp
;-------------------------------------------------
scren proc near ;AX set on entry
mov bh,1eh ;set yellow no blue
mov cx,0
mov dx,184fh
int 10h ;scroll
ret
scren endp
;-------------------------------------------------
curs proc near
mov ah,02
mov bh,0
mov dh,row ;set cursor
mov dl,0
int 10h
ret
curs endp
;-------------------------------------------------
error proc near ;通过DX传递要显示的信息地址
mov ah,09
int 21h
mov errcde,01
ret
error endp
;-------------------------------------------------
code ends
end start
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -