汇编语言子程序设计
( 鉴于网友对本博文比较感兴趣,2012年5月新增了实验报告中相关内容。 )
实验2.4 查找电话号码
1:题目:查找电话号码phone
2.实验要求
1)要求建立一个可以存入50项的电话号码表,每项包括人名(20字符)和电话号码(8字符)两部分;
2)程序可以接受用户输入的人名及相应的电话号码,并把它们加入到电话号码表中;
3)凡有新的输入后,程序可以按人名对电话号码进行排序;
4)程序可接收需要查找的电话号码的人名,并从电话号码表中查出电话号码,再在屏幕上以如下格式显示
name tel
xxxxx xxxxxxxxxx
程序解决方案
一:总体设计与模块说明
总体设计(2012年5月新增)如下图所示:
模块说明:
1.main:作为主程序调用其他模块,完成程序功能。
2:menu :作为主菜单供用户选择操作所用。
3:input_name:作为输入姓名子程序块。
4: input_phone:作为输入电话号码子程序。
5: ifchar:作为判断输入姓名是否含非字母字符的子程序。
6:ifnum:作为判断输入电话号码是否含非数字字符的子程序。
7:store:存储输入姓名或者电话号码等内容的子程序。
8 name_sort:对已经输入的电话记录按姓名排序的子程序。
9:name_search:在已经输入的电话记录中查找所需号码的子程序。
10:printline:输出已经查找到的电话记录。
11:clear_screen:在菜单选择之间,适时清除屏幕冗余性息的子程序。
12:cursor :清屏后光标重定位的子程序。
13:crlf:回车换行的子程序。
程序代码清单:
***************************************************************************************
msg macro message ;输出提示符的宏
lea dx,message
mov ah,09
int 21h
endm
datasg segment
tel_tab db 2700 dup(?),'
count dw 0
count1 dw 0
count2 dw 0
count3 dw 0
count4 dw 15
count5 dw 0
result db 0
num dw 0
ifnumy dw 0
ifchary dw 0
window db ' **************************************************************************' ,13,10
db ' A Telphonenumber Store And Search System' ,13,10
db ' ' ,13,10
db ' Author:HNU Dingqiao Wang 2010-6 ' ,13,10
db ' ' ,13,10
db ' **************************************************************************',13,10,';程序相关的界面
mess1 db ' Input Name( max 14 char):','
mess2 db ' Input A Number( max 11 num):','
mess4 db ' Not In The Table ,Check Your Spelling Or Try Again! ','
mess5 db ' Result As follow : ',13,10
db 'Name***********TEL********',13,10 ,';程序相关的界面
mess6 db '-----------------------------------------------',13,10,'
mess7 db ' * Additem [Enter/Space]',13,10
db ' * Search [S]',13,10
db ' * View [V]',13,10
db ' * Exit [Esc]',13,10,13,10
db ' Make a choice ',13,10,'
mess8 db ' Check Your Inputting,It Contains None Char !',13,10,';程序相关的提示符
mess9 db ' Check Your Inputting,It Contains None Number!',13,10,'
mess10 db ' No Record , Check Your Inputting And Try Again!',13,10,'
mess11 db ' The Name You want search:','
tip db ' System Tips: ',13,10
db ' You can press A Key List In The Menu ',13,10
db ' Then System Will Work For You ',13,10,13,10,'
name1 label byte
max1 db 15
act1 db ?
str1 db 15 dup(?)
tel label byte
max2 db 12
act2 db ?
str2 db 12 dup(?)
datasg ends
;------------------------------------------------
codesg segment
assume cs:codesg,ds:datasg,es:datasg
main proc far
start:
push ds
sub ax,ax
push ax
mov ax,datasg
mov ds,ax
mov es,ax
;---------
msg window;程序相关的界面
call menu
quit: ;返回DOS系统
mov ah,4ch
int 21h
main endp
;------------------------------------------------
menu proc near ;显示选择菜单,包括输入、查看、查询、退出
msg mess7
call crlf
mov ah,07
int 21h
cmp al,0dh ;键入回车则查询相应纪录
je inputproc;输入
cmp al,20h ;键入空格则查询相应纪录
je inputproc;输入
cmp al,'s' ;键入s则查询相应纪录
je sear ;查询
cmp al,'v' ;键入v则查看所有纪录
je allrecord;查看
cmp al,1bh;Esc键退出
je quit ;退出
jmp help
allrecord:
call viewall;调用查看已有纪录子程序
jmp exitmenu
inputproc:
call input ;调用输入子程序
jmp exitmenu
sear:
cmp count,0
je promp
call clear_screen
call name_search;调用电话号码查询子程序
jmp exitmenu
promp:
msg mess10
call crlf
call menu
help:
mov dl,07
mov ah,02
int 21h
call clear_screen ;清除屏幕
msg tip
call menu
exitmenu:
ret
menu endp
;------------------------------------------------
input proc near ;输入子程序,调用输入姓名及输入电话号码子程序
mov bx,num
call input_name;调用输入姓名函数
call input_phone;调用输入号码函数
inc count
add bx,12
mov byte ptr tel_tab[bx-1],'
mov num,bx
call name_sort
call clear_screen
call menu
ret
input endp
;-------------------------------------------------
input_name proc near;存入姓名函数
push cx
lea dx,mess1
mov ah,09
int 21h
;-------
lea dx,name1 ;将输入姓名存入到缓冲区name1
mov ah,0ah
int 21h
;-------
mov cl,act1;检验输入的人名是否包含非字母的字符
mov si,0
test1:
mov al, str1[si]
call ifchar
cmp ifchary,'y'
jne error1
goon:
inc si
loop test1
;-------
move1:
mov cl,act1
lea si ,str1
lea di,tel_tab[bx]
call store;输入的电话纪录人名存入电话表
call crlf
pop cx
jmp exitname
error1:
msg mess8
call crlf
call menu
exitname:
ret
input_name endp
;------------------------------------------------
input_phone proc near;存入电话号码函数
push cx
lea dx,mess2
mov ah,09h
int 21h
;---------
lea dx,tel;将输入姓名存入到缓冲区tel
mov ah,0ah
int 21h
;-------
mov cl,act2 ;检验输入的人名是否包含非数字的字符
mov si,0
test2:
mov al, str2[si]
call ifnum
cmp ifnumy,'y'
jne error2
inc si
loop test2
;--------------
move2:
add bx,15
mov cl,act2
lea si ,str2
lea di ,tel_tab[bx]
call store;输入的电话号码存入电话表
call crlf
pop cx
jmp exitphone
error2:
msg mess9
call crlf
call menu
exitphone:
ret
input_phone endp
;-------------------------------------------------
ifchar proc near ;判断输入是否为姓名字母子程序,结果存入ifchary中
cmp al,'.'
je permit
cmp al,20h
je permit
cmp al,41h
jb error1
cmp al,5ah
jbe permit
cmp al,61
jb error3
cmp al,7ah
jnbe error3
permit:
mov ifchary,'y'
jmp exitif1
error3:
mov ifchary,'n'
exitif1:
ret
ifchar endp
;-------------------------------------------------
ifnum proc near;判断输入是否为电话号码数字子程序,结果存入ifnumy中
sub al,30h
cmp al,0h
jb error4
cmp al,9h
jnbe error4
mov ifnumy,'y'
jmp exitif2
error4:
mov ifnumy,'n'
exitif2:
ret
ifnum endp
;-------------------------------------------------
store proc near ;存储输入内容程序函数
cld
rep movsb;串传送指令,存入相应的内容到电话表
ret
store endp
;-------------------------------------------------
name_sort proc near;按名字冒泡法排序函数
mov cx,count
cmp cx,1
je exits
dec cx
lop2:
mov count1,cx
mov bx,0
lop3:
call compare
cmp result,'>'
jne continue
change:
mov count2,cx
mov cl, 26
mov di,0
exchange: ;排序时移动纪录的程序段,本来想用rep movsb,但一直应为名字长度不同而出现错误
mov al,tel_tab[bx][di]
xchg al,tel_tab[bx+27][di]
mov tel_tab[bx][di],al
inc di
loop exchange
mov cx,count2
continue:
add bx,27
loop lop3
mov cx,count1
loop lop2
exits:
ret
name_sort endp
;------------------------------------------------
compare proc near;按名字15为循环比较函数,结果存贮到result中,供name_sort函数判断
mov si,bx
comp:
mov al,tel_tab[si]
cmp al,'Z'
jnb goon2
add al,20h ;比较时不区分大小写,遇到大写转换为小写
goon2:
mov dl, tel_tab[si+27]
cmp dl,'Z'
jnb goon3
add dl,20h ;比较时不区分大小写,遇到大写转换为小写
goon3:
cmp al,dl
jl exit4;两个名字中a[i]<a[i+1],结果保存到result位'<'
jg exit5;两个名字中a[i]>a[i+1],结果保存到result位'>'
inc si
dec count4
jnz comp
exit4:
mov result ,'<'
ret
exit5:
mov result ,'>'
ret
compare endp
;------------------------------------------------
name_search proc near;按姓名查找电话号码
mov count5,0
msg window
call crlf
msg mess11
lea dx,name1
mov ah,0ah
int 21h
lea si,str1
mov cl,act1
test3: ;检验输入的姓名中是否包含非字母
mov al,[si]
call ifchar
cmp ifchary,'y'
jne error5 ;若包含非字母则提示并转到菜单重新选择
inc si
loop test3
mov bx,0
mov cx,count;根据输入的姓名,在电话表中循环查询是否有此纪录
search:
push cx
call searchresult ;调用大小写兼容查询子程序
continue2:
add bx,27
pop cx
loop search
cmp count5,0
jnz exitsear
msg mess10
msg mess6
call crlf
call menu
jmp exitsear
error5:
msg mess8
exitsear:
msg mess6
mov count5,0
call menu
ret
name_search endp
;------------------------------------------------
searchresult proc near ;搜索结果的判断子程序
call crlf
lea si,str1
mov cl,act1
mov di,0
check: ;check段的作用为大小写兼容查询状态
mov al,[si]
cmp al,tel_tab[bx][di] ;算法为假设输入为小写,先匹配,无结果则转换为大写查询,若仍然无结果,
jne onece1 ;则可以断定为输入为大写或者确实无结果,当输入为大写是先前的操作引起al值改变
je again ;此时应该将al+40h,再次判断,若在不成功,则应该为的确没有记录。
onece1:
sub al,20h
cmp al,tel_tab[bx][di]
jne onece2
je again
onece2:
add al,40h
cmp al,tel_tab[bx][di]
jne exitresult
again:
inc si
inc di
loop check
getit:
inc count5
call printline
exitresult:
ret
searchresult endp
;------------------------------------------------
viewall proc near;显示当前已存入所有经过排序的纪录
call clear_screen;清屏
cmp count ,0
je exit8 ;当前无记录时提示符
call crlf
msg mess5
call crlf
mov cx ,count
mov bx,0
view:
lea dx,tel_tab[bx]
mov ah,09
int 21h
call crlf
add bx,27
loop view
exit7:
msg mess6
call crlf
call menu
jmp exitprint
exit8:
msg mess10
call crlf
exitprint:
msg mess6
call menu
ret
viewall endp
;------------------------------------------------
printline proc near;输出查询结果
cmp count5,1
jnbe print
msg mess5
print:
lea dx,tel_tab[bx]
mov ah,09
int 21h
call crlf
ret
printline endp
;-------------------------------------------------
clear_screen proc near ;清除屏幕子程序
push ax
push bx
push cx
push dx
mov ah,6
mov al,0
mov bh,7
mov ch,0
mov cl,0
mov dh,24
mov dl,79
int 10h
mov dx,0
mov ah,2
int 10h
mov dh,0
call cursor
pop dx
pop cx
pop bx
pop ax
ret
clear_screen endp
;-------------------------------------------------
cursor proc near ;重置光标位置子程序,置光标为第零行和第零列
push ax
push bx
push cx
push dx
mov ah,02
mov bh,00
mov dl,00
mov dh,00
int 10h
xor bh,bh
mov dh,0
mov dl,0
mov ah,02
int 10h
pop dx
pop cx
pop bx
pop ax
ret
cursor endp
;-------------------------------------------------
crlf proc near ;输出回车换行
push ax
push cx
mov dl,0dh
mov ah,02h
int 21h
;----------
mov dl,0ah
mov ah,02h
int 21h
pop cx
pop ax
ret
crlf endp
;------------------------------------------------
codesg ends
end start
**************************************************************************************
运行结果: