汇编实验报告-电话簿
1. 题目要求:对上周写的电话簿增加对通讯录的增加、删除、更改操作。
2. 运行环境:Windows11+MASM
3. 题目分析:
题目要求我们在上一周电话簿的基础上,增加对通讯录的增加、删除、更改操作。
首先考虑新增的问题。由于上一周的电话簿刚开始就要求录入信息,并且使用了专门的函数inputname实现name和phone的输入,因此我们可以直接复用改代码段。
再考虑通讯录的更改功能。我们的想法是借助之前查找功能里的字符串匹配代码段,先让用户输入旧的name进行匹配,若匹配上则先保存旧name在存储区的首址,要求用户输入新的name和phone,对其进行覆盖。在这个基础上,想实现删除功能也就十分简单了:我们只需借用修改功能的思路,对要删除的name和phone全部以20H替换,这样在查询name时必定不会匹配,相当于通讯录中已经不存在这一条了。
4. 流程图绘制:根据分析和题目要求绘制流程图:
![流程图](https://gitee.com/CaoZhongyang/cartographic-bed/raw/master/https://gitee.com/CaoZhongyang/cartographic-bed/202211291512157.png)
5. 各功能实现的流程图与程序:
- 增加操作
-
分析:添加操作中,我们不需要查找新增name和现有name的比较,只需要将其追加到存储区尾部即可。因此该功能实现的难点就在于对尾部的定位。之前的实验中,我们定位了endaddr作为最后一个name的首址,故我们可以直接+26获得待存储name的首址。但是原先的inputname的di并不由人为指定,因此我们每次做add的时候都需要将di定位到endadrr+26的地址位置。
-
添加操作流程图
-
添加操作代码段:只需在操作菜单函数search_or_not里加入对add操作的回应即可,以下为增加部分:
cmp al,'a'
jne contin
mov bx,endaddr;这里di指向旧串末尾
add bx,26
mov di,bx
lea dx,crlf;输出提示信息
mov ah,09h
int 21h
jmp inputname
- 修改操作
- 分析:修改操作中,我们需要首先询问用户要修改哪个name,将其与存储区中name依次匹配,匹配到就要求用户输入新name和phone,然后直接覆盖原来存储区的旧数据即可。
- 修改操作流程图
- 修改操作代码段:需另外编写启动函数、查找和覆盖函数。
name_change proc near
lea bx,table
sear2:
mov cx,15
mov di,bx
lea si,stokn1
repz cmpsb
jz do_change;匹配上了,此时bx是老name起始地址
;不匹配,就往存储区下一个name找
add bx,26
cmp bx,endaddr;看是不是到末尾了
jbe sear2
lea dx,mess5;到最后也每匹配上,结束
mov ah,09
int 21h
ret
do_change:;已经匹配到原有的name了,现在应做的是提示用户输入新的name和phone,然后放到老name后的存储
lea dx,mess1;输出提示信息
mov ah,09h
int 21h
push bx;bx是老name起始地址,先保存起来。
call input_name
lea dx,mess2;输出提示信息
mov ah,09h
int 21h
call input_phone
;此时新的name和phone已经分别存入stokn1\stokn2
pop bx
mov di,bx
mov cx,15
lea si,stokn1
rep movsb;存入新name
mov cx,11
lea si,stokn2
rep movsb;存新phone
jmp search_or_not
name_change endp
- 删除操作
- 分析:在做完修改操作后,删除就显得尤为简单了。删除操作和修改操作很类似,只是我们可以用20H来覆盖原来的name和phone,使得后续查找不可能再与其匹配。这样对用户而言,该信息就已被删除。
- 删除操作流程图
- 删除操作代码段:需另外编写启动函数、查找和覆盖函数。
name_delete proc near
lea bx,table
sear3:
mov cx,15
mov di,bx
lea si,stokn1
repz cmpsb
jz middle1;匹配上了,此时bx是老name起始地址
;不匹配,就往存储区下一个name找
add bx,26
cmp bx,endaddr;看是不是到末尾了
jbe sear3
lea dx,mess5;到最后也每匹配上,结束
mov ah,09
int 21h
ret
;已经匹配到原有的name了,现在应做的是把空格填充放到老name后的存储
;填充空格,现在BX保存着该覆盖的起始地址
middle1:
mov cx,15
push bx
sub bx,bx;归0
putspace1:
; lea dx,mess9;test
; mov ah,09
; int 21h
mov stokn1[bx],' '
inc bx
loop putspace1
mov cx,11
sub bx,bx;归0
putspace2:
mov stokn2[bx],' '
inc bx
loop putspace2
instead:;把stoken1\stoken2放入table原内存
mov cx,15
pop bx
mov di,bx;现在di指向老name起始地址
lea si,stokn1
repz movsb
mov cx,11
lea si,stokn2
repz movsb
ret
name_delete endp
. 主函数修改
-
分析:在四个功能完成后,主函数还需修改菜单,使用户输入a选择添加、输入d选择删除、输入c选择修改。
-
主函数中search_or_not代码段修改:
search_or_not:
lea dx,mess3;输出提示信息
mov ah,09h
int 21h
sub al,al;准备获取order
mov ah,07h
int 21h
cmp al,'n'
je exit;不查退出
cmp al,'a'
jne contin
mov bx,endaddr;这里di指向旧串末尾
add bx,26
mov di,bx
lea dx,crlf;输出提示信息
mov ah,09h
int 21h
jmp inputname
;测试
contin:
cmp al,'t'
je test_jmp
;测试结束
cmp al,'s'
je getname
cmp al,'c'
je change
cmp al,'d'
je delete