实验四 查找电话号码
一、 实验的目的与要求
(一)实验目的:学习用汇编语言设计与编写子程序,理解子程序的调用过程。
(二) 实验要求:
(1) 要求程序建立一个可存放50项的电话号码表,每项包括人名(20个字符)及电话号码(8个字符)两部分;
(2) 程序可接收输入人名及相应的电话号码,并把它们加入电话号码表中;
(3) 凡有新的输入后,程序应按人名对电话号码表重新排序;
(4) 程序可接收需要查找电话号码的人名,并从电话号码表中查出其电话号码,再在屏幕上以如下格式显示出来。
name tel.
X X X X X X X X
二、实验正文
实验分析:查找电话号码程序设计,应注意子程序的设计,合理的设计子程序,使程序思路更清晰,便于设计。实验涉及查找排序,对程序设计提出了更高的要求,数据结构采用二维数组来存储电话信息,还应设置变量用于排序以及查找等子功能的实现。核心的子功能是排序和查找功能,排序采用冒泡排序,并设置标志位,以便提高程序效率,排序时应当注意的是数据段的截止地址,以防发生越界错误。在排序时也嵌套调用子过程交换,此时应该注意,源地址寄存器和目的地址寄存器的变化。查找的功能其实是对电话本的每一项的姓名进行匹配。显示电话本内容是把电话本的每一项先放在一个变量里面,然后显示,直到全部取出为止。由于字符串的操作较多,多次使用si和di寄存器,再适当时候应注意压栈。保存必要的信息,否则会发生越界等严重错误。
三、流程图如下:
四、实验结果
附录:程序源代码如下:
;*****************************************************************8
data_seg segment
namcount dw 0 ;the number count
tel_tab db 50 dup(28 dup(' ')) ;the telbook
nameitem label byte ; store name
max1 db 21
ncurlen db ?
namefld db 21 dup(?)
phoneitem label byte;store numer
max2 db 9
pcurlen db ?
phonefld db 9 dup(?)
addend dw ? ;排序时的tel_tab尾地址指针
namtemp db 28 dup(?),13,10,'$'
swap db 0 ;排序中是否有交换的标志位
msg_count db 'Do you want to insert a item to phonebook?(Y/N)',13,10,'$'
msg_error db 'Error!Please enter the requested...',13,10,'$'
msg_inputnam db 'Input name:','$'
msg_inputnum db 'Input a telephone number:','$'
msg_inquire db 'Do you want a telephone number?(Y/N)','$'
msg_sname db 'name?',13,10,'$'
msg_outtitle db 'name tel.',13,10,'$'
msg_nomatch db 'NOt EXIT!',13,10,'$'
msg_allphone db 'print all RECORD?(Y/N)',13,10,'$'
msg_result db 'name tel.',13,10,'$'
data_seg ends
;**********************************************************************
stack_seg segment para stack 'stack' ;定义堆栈段
dw 256 dup(0)
stack_seg ends
;*********************************************************************
code_seg segment
;----------------------------------------------------------------------------
main proc far
assume cs:code_seg,ds:data_seg,es:data_seg,ss:stack_seg
start:
mov ax,data_seg
mov ds,ax ;初始化数据段
mov es,ax ;初始化附加段
xor bx,bx
cld
lea di,tel_tab ;名字表的首地址放入di
a1: lea dx,msg_count
mov ah,9
int 21h ;显示信息是否插入一项纪录?(Y/N)'
mov ah,1
int 21h
mov bl,al
call crlf
cmp bl,'n' ;判断输入
jz a2
cmp bl,'N'
jz a2
cmp bl,'y'
jz next0
cmp bl,'Y'
jz next0
mov ah,9
lea dx,msg_error
int 21h
jmp a1
next0:lea dx,msg_inputnam
mov ah,9
int 21h ;要求输入名字
call input_name ;调用input_name输入人名
call stor_name ;调用stor_name存储人名
call input_phone ;调用input_phone输入电话
call name_sort ;排序
jmp a1 ;是否继续输入?
a2: lea dx,msg_inquire
mov ah,9
int 21h ;显示是否查找电话号码
mov ah,1
int 21h
mov bl,al
call crlf
cmp bl,'n'
jz a3
cmp bl,'N'
jz a3
cmp bl,'y'
jz next1
cmp bl,'Y'
jz next1
mov ah,9
lea dx,msg_error
int 21h
jmp a2
next1:lea dx,msg_sname
mov ah,9
int 21h ;显示要查询电话的姓名
call input_name ;输入姓名
call name_search
jmp a2
a3: lea dx,msg_allphone ;显示所有电话号码
mov ah,9
int 21h
mov ah,1
int 21h
mov bl,al
call crlf ;回车换行
cmp bl,'n'
jz exit
cmp bl,'N'
jz exit
cmp bl,'y'
jz next2
cmp bl,'Y'
jz next2
mov ah,9
lea dx,msg_error
int 21h
jmp a3
next2: call printline ;调用子程序打印出所有的电话号码
exit: ret
main endp
;---------------------------------------------------------------------
input_name proc near ;子程序 接受输入字符
lea dx,nameitem
mov ah,0ah
int 21h
call crlf ;回车换行
mov bh,0
mov bl,ncurlen
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
lea si,namefld
mov cx,20
rep movsb
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
call crlf
cld
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
mov addend,di
lea si,tel_tab
s2: mov cx,20
mov di,si
add di,28
mov ax,di
mov bx,si
repe cmpsb
jbe s3
call exchange
s3: mov si,ax
cmp si,addend
jbe s2
cmp swap,0 ;如果有交换,继续下一趟
jnz s1
exit4: pop bx
pop ax
pop di
ret
name_sort endp
;--------------------------------------------------------------------
exchange proc near ;交换tel_tab中di,si所指表项的内容
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
;----------------------------------------------------------
name_search proc near ;查找输入的名字
lea di,tel_tab
push di
mov bx,namcount
loop1: lea si,namefld
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 ;没有找到输出信息
found: pop di
lea dx,msg_outtitle
mov ah,9
int 21h
mov si,di
lea di,namtemp
mov cx,28
rep movsb
lea dx,namtemp
mov ah,9
int 21h ;显示查到的姓名和电话号码
ret
name_search endp
;-------------------------------------------------------
printline proc near ;输出排序结果
push di
push namcount
call crlf ;回车换行
lea dx,msg_result
mov ah,9
int 21h ;显示升序输出姓名、电话
lea si,tel_tab
loop2: lea di,namtemp
mov cx,28
rep movsb
lea dx,namtemp
mov ah,9
int 21h ;显示姓名、电话
dec namcount
jnz loop2 ;循环输出
pop namcount
pop di
ret
printline endp
;---------------------------------------------------------
crlf proc near ;回车换行
mov dl,0dh
mov ah,2
int 21h
mov dl,0ah
mov ah,2
int 21h
ret
crlf endp
;---------------------------------------------------------
code_seg ends
;***********************************************************
end main
五、实验总结
本次实验初步了解了子程序的设计,是程序设计模块化,这对于设计较复杂的程序是非常重要的。实验对字符串的处理,要求相对较高,涉及字符串的移动和比较,此外还应该注意在定义缓冲区长度时,应把回车的长度加入进去,否则可能会造成覆盖的错误。实验过程中对于si和di的使用,由于没有及时保存发生了,越界错误,后经仔细调试才发现问题,汇编程序设计中压栈操作时十分重要的,在设计程序时应引起注意,注意一些公用寄存器的值的保存的问题。通过这次实验,我发现了使用子过程能更清晰的设计程序,相信这对我今后汇编语言的学习会起到很重要的作用。
本文来源:https://www.2haoxitong.net/k/doc/e5a8301c964bcf84b9d57bef.html
文档为doc格式