📄 1.asm
字号:
DATAS SEGMENT
namcount dw 0 ;存入名字的个数
tel_tab db 50 dup(28 dup(' ')) ;表格
nameitem label byte
nmax db 21
ncurlen db ?
namefld db 21 dup(?) ;姓名缓存区
phoneitem label byte
pmax db 9
pcurlen db ?
phonefld db 9 dup(?) ;电话号码缓存区
addend dw ? ;排序时的tel_tab尾地址指针
namtemp db 28 dup(?),13,10,'$' ;临时保存表中一项
swap db 0 ;排序中是否有交换的标志位
msg_count db 'Please enter the order you want to input?',13,10,'$'
msg_illcount db 'Error:The order of your enter exceed the limit of 50! Plesae input the number again!',13,10,'$'
msg_illch db 'Error:The order of your enter is illegal! Please intput the number again!',13,10,'$'
msg_inputnam db 'Input name:','$'
msg_inputerr db 'Error:Input error!,please input a name!',13,10,'$'
msg_inputnum db 'Input a telephone number:','$'
msg_inquire db 'Do you want to find a telephone number?(Y/N)','$'
msg_sname db 'name?',13,10,'$'
msg_outtitle db 'name tel.',13,10,'$'
msg_nomatch db 'No such name!Do you want to insert this item(Y/N)?',13,10,'$'
msg_result db 'The Phone Dictionary is listed as follows:',13,10,'$'
DATAS ENDS
;-----------------------------------------------------------------------------------------------------------
STACKS SEGMENT para stack 'stack'
dw 256 dup(0)
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,ES:DATAS,SS:STACKS
main proc far ;主程序段
START:
MOV AX,DATAS
MOV DS,AX
MOV ES,AX ;初始化附加段
cld ;df=0
lea di,tel_tab ;名字表的首地址放入di
lea dx,msg_count
mov ah,9
int 21h
again:call decibin ;调用decibin
cmp dx,2
call crlf
je exit1 ;一个有效字符都没输入,跳转要求重新输入.输入的为非法字符即非数字则不等输入完就跳出
push bx
cmp bx,50 ;
ja return ;输入的个数大于50出错跳出
repeat0:
pop bx
cmp namcount,bx ;目前项数和要求输入的项数比较,名字数和bx比较
je choice ;如果所有项都输入完毕则跳到choice排序
push bx ;stor_name会用到bx,先保存
lea dx,msg_inputnam
mov ah,9
int 21h ;要求输入名字
call input_name ;调用input_name
cmp ncurlen,0 ;没有输入了则开始排序,输入名字的字符数为0跳转
je choice
call stor_name
call input_phone ;调用input_phone
jmp repeat0 ;由于tel_tab是顺序连续存储,每一次输入一项后,di即指向下一项的开始,所以无需调整
choice:cmp namcount,1
jb return1 ;表中项数小于1则要求输入
call name_sort ;不小于调用name_sort
rotate:lea dx,msg_inquire ;输出'Do you want to find a telephone number?(Y/N)'(查找)
mov ah,9
int 21h ;显示是否查找电话号码
mov ah,1
int 21h ;由键盘输入‘Y’或‘N’
cmp al,'y'
je loop0
cmp al,'Y'
jne exit ;不为‘Y'或'y'跳出转至exit
jmp loop0;为‘Y'回车、换行
loop0: call crlf
lea dx,msg_sname ;'name?'
mov ah,9
int 21h ;显示要查询电话的姓名
call input_name ;输入姓名
call name_search ;调用name_search
jmp rotate ;返回查找另一个电话
insert: call crlf
call stor_name
call input_phone
;call printline
;cmp namcount,1
;jb return1 ;表中项数小于1则要求输入
call name_sort ;不小于调用name_sort
call printline
jmp rotate
exit1: lea dx,msg_illch ;输入顺序数不合法,重新输入
mov ah,9
int 21h
jmp again
return:lea dx,msg_illcount ;输入顺序数超出号码本容量,重新输入
mov ah,9
int 21h
jmp again
return1:lea dx,msg_inputerr ;输入错误,重新输入姓名
mov ah,9
int 21h ;没有输入名字
jmp repeat0 ;出错跳转
exit: call printline ;输出排序结果
mov ah,7
int 21h
jmp main
main endp ;主程序结束
;---------------------------------------------------------------------------------------------------------------------
name_search proc near ;(子程序)在表中顺序查找输入的名字
lea di,tel_tab ;把输入的名字首地址放入di
push di ;保存名字表首址,di为指向tel_tab表项的指针
mov bx,namcount ;名字的个数放bx
loop1: lea si,namefld ;名字的缓存区首地址放入si
mov cx,20
repe cmpsb ;连续查找匹配名字
je found ;找到跳转found
pop di ;没找到di出栈
add di,28 ;把查找转到下一个名字
push di
dec bx
jnz loop1 ;循环查找
lea dx,msg_nomatch
mov ah,9
int 21h ;一直没找到则显示没有找到名字
mov ah,1
int 21h ;由键盘输入‘Y’或‘N’
cmp al,'y'
je insert
;cmp al,'Y' ;此时di应指向插入位置
jne loop0 ;不为‘Y'或'y'跳转至重新输入名字查找
;jmp insert
found: pop di
lea dx,msg_outtitle
mov ah,9
int 21h
mov si,di ;把要找到的内容暂存在namtemp中
lea di,namtemp
mov cx,28
rep movsb
lea dx,namtemp
mov ah,9
int 21h ;显示查到的姓名和电话号码
ret
name_search endp
;-------------------------------------------------------------------------------------------------------
decibin proc near ;十进制转化为2进制 ,并保存到bx中
mov bx,0 ;bx清零
mov dx,2 ;输入数的位数置2
newchar:
mov ah,1
int 21h ;一号功能调用(输入字符并回显)
sub al,30h
jb exit2 ;非数字退出
cmp al,9
ja exit2 ;大于9退出(十进位制数每位0-9)
cbw ;字节转换成字(al->ax)
xchg ax,bx ;交换ax、bx
mov cx,10
push dx
mul cx ;先保存,dx×10
xchg ax,bx ;再将ax、bx交换回
add bx,ax
pop dx
dec dx
jnz newchar ;位数不为0跳转
exit2: ret
decibin endp ;结束
;---------------------------------------------------------------------------------------------------------
input_name proc near ;子程序(输入名字)
lea dx,nameitem
mov ah,0ah
int 21h ;输入名字并送入缓存区
call crlf ;回车、换行
mov bh,0
mov bl,ncurlen ;把名字的字符个数放入bx低位
mov cx,21 ;置循环次数
sub cx,bx
repeat1:mov namefld[bx],20h
inc bx
loop repeat1 ;输入的名字为20字节,不足的用空格补足
ret
input_name endp
stor_name proc near ;子程序(传送名字的每个字母到si)
inc namcount
cld ;df=0(从小到大)
lea si,namefld
mov cx,20
rep movsb ;重复传送串名字(以字节为单位),直至送满20即cx=0 ,di指向tel_tab
ret
stor_name endp
;---------------------------------------------------------------------------------------------------------------
input_phone proc near ;子程序(输入电话号码)
lea dx,msg_inputnum
mov ah,9
int 21h ;显示要求输入电话号码
lea dx,phoneitem
mov ah,10
int 21h ;输入电话号码并送入缓存区
mov bh,0
mov bl,pcurlen
mov cx,9 ;置循环次数
sub cx,bx
repeat2:mov phonefld[bx],20h
inc bx
loop repeat2 ;输入的电话为8字节,不足的用空格补足
call crlf
cld ;df=0
lea si,phonefld
mov cx,8
rep movsb ;把输入的号码存入namtab表中,重复传送串电话号码(以字节为单位)
ret
input_phone endp
;-------------------------------------------------------------------------------------------------------------------
name_sort proc near ;子程序(进行排序)
push di
push ax
push bx
cmp namcount,1
jz exit4 ;比较名字个数(只有一个名字即退出)
s1: mov swap,0
sub di,56;di指针后移两个表项,第一次指向倒数第二项,以后每跑一趟前移一项
mov addend,di ;重新计算表尾指针
lea si,tel_tab
s2: mov cx,20 ;置循环计数值
mov di,si
add di,28 ;di->后项,si->前项
mov ax,di ;后项保存在ax
mov bx,si ;前项保存在bx
repe cmpsb ;源-目标,即前项如果大于后项,交换;
jbe s3
call exchange
s3: mov si,ax
cmp si,addend
jbe s2 ;是否已到namtab表尾,如果没到继续循环
cmp swap,0 ;如果有交换,继续下一趟
jnz s1
exit4: pop bx
pop ax
pop di
ret
name_sort endp
;---------------------------------------------------------------------------------------------------
exchange proc near ;交换tel_tab中di,si所指表项的内容,前项保存在bx
mov cx,28
lea di,namtemp
mov si,bx
rep movsb
mov cx,28
mov di,bx
rep movsb
mov cx,28
lea si,namtemp
rep movsb
mov swap,1
ret
exchange endp
;------------------------------------------------------------------------------------------------
printline proc near ;输出排序结果,不需要设置di,会改变di值
push di
push namcount ;保存namcount的值
call crlf
lea dx,msg_result ;'The result of sort is as follows:'
mov ah,9
int 21h ;显示升序输出姓名、电话
lea si,tel_tab
loop2: lea di,namtemp
mov cx,28 ;si每一次loop2会自动修正
rep movsb ;循环传送姓名、电话至输满27字节即cx=0
lea dx,namtemp
mov ah,9
int 21h ;显示姓名、电话
dec namcount ;名字数减1
jnz loop2 ;没输完则循环输出
pop namcount
pop di
ret
printline endp
;----------------------------------------------------------------------------------------------------
deciasc proc near ;把10进制数转换成相应的ASCII码,digit in bl
mov ch,10d
mov cl,10d
re: ;判断退出条件
cmp ch,0
je quit
mov al,bl;
cbw
div ch;
mov bl,ah
call printit
;a1a2a3... 递推:x=an-1*10+an
;mov dl,al;商暂存在bl中
;mov dh,ah;余数暂存在dh中
;mov bh,0d;
;mov ax,bx
;mul cl
;mov bl,al
;add bl,dl
;除数ch=ch/10
mov al,ch
cbw
div cl
mov ch,al
;dec dh
jmp re
quit:
ret
deciasc endp
;------------------------------------------------------------------------------------------------
printit proc near ;输出1位数字对应的ASCII码,binary number in al
add al,30h
mov dl,al
mov ah,2
int 21h
ret
printit endp
;---------------------------------------------------------------------------------------------------
crlf proc near
mov dl,0dh
mov ah,2
int 21h
mov dl,0ah
mov ah,2
int 21h
ret
crlf endp
CODES ENDS
END START
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -