1.题目:查找电话号码phone
2.实验要求:
(1)建立一个可存放50项的电话号码表,每项包括任命(20个字符)及电话号码(8个字符)两部分;
(2)程序可接收输入人名及相应的电话号码,并把它们加入电话号码表中;
(3)凡有新的输入后,程序应按照人名对电话号码表重新排序;
(4)程序可接收需要查找电话号码的人名,并从电话号码表中查出其电话号码,再在屏幕上以如下格式显示出来。
name tel.
××× ×××
3.提示:程序采用子程序结构。主程序的部分主要如下:
显示提示符‘Input name’
调用子程序’input_name’接收人名
调用子程序stor_name把人名存入电话号码表tel_tab中
显示提示符’Input a telephone number:’
调用子程序inphone接收电话号码,并把它存入电话号码表tel_tab中
如果输入已经结束,则调用name_sort子程序对电话号码表按人名排序
显示提示符’Do you want a telephone number?’
回答N则退出程序
回答Y则再显示提示符‘name?’
调用子程序input_name接收人名
调用子程序name_search再电话号码表中查询所需的电话号码
调用子程序printline按要求格式显示人名和电话号码
重复查号提示符直至用户不再要求查找为止
思路
大致画了以下流程图,并指明了主程序和子程序相互传递参数之间的方式
程序较为复杂,设计到了串转移和串查找指令,程序的核心功能是name_sort排序和name_search查找功能。name_sort使用了冒泡排序,但又不是经典的冒泡排序,为了程序简单,每次都从头到尾开始比较,把原本的比较次数(N)*(N-1)变为了N * N,并设置交换位swapped来判断是否结束排序。name_search要用到cmpsw指令,找到后把他放入temp临时变量中之后传递给Printline,没找到通过cx=-1传递给print_line。
以下是name_sort 和 name_search的空间地址结构:
还有一个坑就是在定义缓冲区长度时应该把回车的长度加进去,否则可能造成覆盖的错误。
总体来说,程序极为麻烦,调试极其不易。
代码
;--------数据段开始----------
datasg segment
namepar label byte ;接受名字输入
maxnlen db 21
actnlen db ?
_name db 21 dup(?)
phonepar label byte ;接受电话号码输入
maxplen db 9
actplen db ?
phone db 9 dup(?)
crlf db 13,10,'$'
;回车换行
endaddr dw ?
mess1 db 'Input name:','$'
mess2 db 'Input a telephone number:','$'
mess3 db 'Do you want a telephone number:','$'
mess4 db 'name?','$'
mess5 db 'name',16 dup(' '),'tel',0dh,0ah,'$'
mess6 db 'Not in the table.',0dh,0ah,'$'
mess7 db 'Invalid input!',0dh,0ah,'$'
count db 0
tel_tab db 50 dup(20 dup(' ')),8 dup(' ') ;电话号码表
temp db 20 dup(' '),8 dup(' '),0dh,0ah,'$' ;暂存的tel_tab项
swapped db 0
datasg ends
;--------代码段开始---------
codesg segment
main proc far
assume cs:codesg,ds:datasg,es:datasg
start:
push ds
sub ax,ax
push ax
mov ax,datasg
mov ds,ax
mov es,ax
;;;;;;;;;;;;;;;
cld
;方向标志位置0
lea di,tel_tab ;目的变址指针指向tel_tab,为了之后搬入tel_tab
inputloop:
mov ah,09h
;提示'Input name'
lea dx,mess1
int 21h
call input_name
cmp actnlen,0 ;输入长度小于1,都将直接终止输入
jz a10
cmp count,50 ;如果超过50个号码
je a10
call stor_name
mov ah,09h ;提示'Input a telephone number'
lea dx,mess2
int 21h
call inphone
jmp inputloop
a10:
cmp count,1
jbe searchloop ;count<=1 直接跳去查找
call name_sort ;否则就要排序
searchloop:
lea dx,mess3 ;提示‘Do you want a telephone number:’
mov ah,09
int 21h
mov ah,01h ;输入字符判断y or n
int 21h
cmp al,'N'
je exit
cmp al,'n'
je exit
cmp al,'Y'
je showname
cmp al,'y'
je showname
mov ah,09
;回车换行
lea dx,crlf
int 21h
lea dx,mess7 ;如果不是Yes or No 否则提示'Invalid input!''
mov ah,09
int 21h
jmp searchloop ;反复询问
showname:
mov ah,09
;回车换行
lea dx,crlf
int 21h
lea dx,mess4 ;提示'name?''
mov ah,09
int 21h
call input_name
call name_search
call printline
jmp searchloop ;反复询问
exit:
ret
main endp
;-------input_name子程序开始-----
;这里不需要保护寄存器,采用直接地址法传递参数
input_name proc near
mov ah,0ah ;调用0a号中断输入到缓冲区
lea dx,namepar ;ds:dx 为缓冲区首地址
int 21h
mov ah,02h ;换行
mov dl,0ah
int 21h
mov bh,0
mov bl,actnlen ;bx存放name的长度
mov cx,20
sub cx,bx
;cx剩余长度
i20:
;填充空格字段
mov _name[bx],20h
inc bx
loop i20
ret
input_name endp
;---------stor_name子程序开始-------
;这里不需要保护寄存器,采用直接地址法传递参数
stor_name proc near
inc count
cld
lea si,_name ;将20个字节的name搬入tel_phone
mov cx,10
rep movsw
ret
stor_name endp
;----------inphone子程序开始--------
;这里不需要保护寄存器,采用直接地址法传递参数
inphone proc near
mov ah,0ah ;调用0a号中断输入到缓冲区
lea dx,phonepar ;ds:dx 为缓冲区首地址
int 21h
mov ah,02h ;换行
mov dl,0ah
int 21h
mov bh,0
mov bl,actplen
mov cx,9
sub cx,bx
is20:
;填充空格字段
mov phone[bx],20h
inc bx
loop is20
cld ;清理方向标志位
lea si,phone ;将8位phone搬入tel_phone
mov cx,4
rep movsw
ret
inphone endp
;--------name_sort子程序开始--------
;这里不需要保护寄存器,采用直接地址法传递参数
;冒泡排序
name_sort proc near
sub di,56 ;tel_lab 20 + 8
mov endaddr,di ;endaddr指向最后第二个tel_lab项的首地址
ns10:
mov swapped,0 ;没有交换过
lea si,tel_tab ;si指向tel_lab的首地址
ns20:
mov cx,20
;20个长度的name
mov di,si
add di,28
mov ax,di
mov bx,si
repe cmpsb
jbe ns30
;如果tel_tab[i]<tel_tab[i+1] 不用交换
call npxchg
ns30:
mov si,ax
cmp si,endaddr ;一轮比较后,最大的已经排到了最后面
jbe ns20
cmp swapped,0 ;如果交换过,则需要再次比较
; mov di,endaddr ;endaddr - 28 代表最后一个已经比较完成
; sub di,28
; mov endaddr,di
jnz ns10
ret
name_sort endp
;;;;;;;;;;;;;;;;;;;;
;bx 和 ax 寄存器传递参数u
;tel_tab[i]和tel_tab[i+1]交换
npxchg proc near
mov cx,14
;temp = a[i]
lea di,temp
mov si,bx
rep movsw
mov cx,14
;a[i+1] = a[i]
mov di,bx
rep movsw
mov cx,14
;a[i] = temp
lea si,temp
rep movsw
mov swapped,1 ;swapped
ret
npxchg endp
;--------name_search子程序开始-----
name_search proc near
lea si,tel_tab ;源变址指针si ->tel_tab
mov bx,si
add endaddr,28
nase10:
lea di,_name
;目的变址指针di ->_name
mov cx,10
;name长度20 db
repe cmpsw
jcxz nase_exit ;如果找到
add bx,28
;si+28 ,并用bx暂存
mov si,bx
cmp si,endaddr ;比较是否查到末尾了
jbe nase10
;还未到最后一个则继续查找
notintab:
mov cx,-1
;没有找到让cx=-1
ret
nase_exit:
mov si,bx
;则搬入temp
lea di,temp
mov cx,14
rep movsw
ret
name_search endp
;-------printline子程序开始----
printline proc near
cmp
cx,-1
je
norecord ;没有找到
mov
ah,09h
;提示'name',16 dup(' '),'tel',0dh,0ah,'$' 标题栏
lea
dx,mess5
int
21h
mov
ah,09h
lea
dx,temp ;输入暂存temp的tel_tab项
int
21h
ret
norecord:
mov
ah,09h ;提示'Not in the table.'
lea
dx,mess6
int
21h
ret
printline endp
codesg ends
end start
结果