ASM16-19 --通讯录
ASM16
通讯录
处理菜单选项
1 | cmp al,'1' |
根据用户输入的选项跳转到对应的处理代码段。如果输入无效,跳转到DEFAULT1
处理。
添加联系人
1 | mov dx, offset NEXT_LINE |
然后换行
1 | ADD1: ;增加联系人 |
提示输入联系人姓名。
09h - 显示字符串
功能描述:显示从DX寄存器指向的内存地址开始的字符串,直到遇到字符串结束符号$
为止。
输入:
DX
:指向要显示的字符串的地址AH
:09h
输出:将字符串显示在屏幕上
1 | mov dx,offset NAME_BUF |
读取用户输入的姓名,存储在NAME_BUF
中。
0Ah - 输入字符串
功能描述:从标准输入设备(通常是键盘)读取字符串并存储到由DX指向的缓冲区中。用户输入的字符串存储在缓冲区中,以回车键(Enter)结束。
输入:
DX
:指向输入缓冲区的地址AH
:0Ah
输出:输入的字符串存储在缓冲区中,第一个字节表示缓冲区的大小,第二个字节表示实际输入的字符数,后续字节存储实际输入的字符。
1 | mov bx, dx ; 将 DX 寄存器的值(缓冲区地址)移动到 BX 寄存器中 |
将姓名字符串的结尾设为$
,以便显示。
mov bx, dx
- `BX` 寄存器指向输入缓冲区。 - 输入缓冲区的结构是: - 第一个字节:缓冲区的最大长度 - 第二个字节:实际输入的字符数 - 后续字节:存储实际输入的字符 - `[bx+1]` 是实际输入的字符数的地址。将该值即实际输入的字符数移动到 `al` 寄存器中。1
2
3
4
5
- 将 `DX` 寄存器的值移动到 `BX` 寄存器。此时,`BX` 寄存器中存储的是输入缓冲区的地址。
2. ```
mov al, byte ptr [bx+1]mov byte ptr [bx+si+2], '$'
NAME_BUF db 20, 0, 20 dup(0)1
2
3
4
5
6
7
8
9
- `SI` 寄存器中存储的是实际输入的字符数。
- `[bx+si+2]` 是输入字符串末尾的下一个位置。
- 将 `$` 字符存储到 `[bx+si+2]` 位置,标志输入字符串的结束。
**示例**
假设缓冲区 `NAME_BUF` 定义如下:20, 4, 'J', 'o', 'h', 'n'1
2
3
输入 `"John"` 后,缓冲区的内容如下:20, 4, 'J', 'o', 'h', 'n', '$'1
2
3
4
5
6
7
执行这段代码后:
1. `BX` 指向缓冲区起始地址。
2. 从 `[bx+1]` 读取实际输入的字符数 `4`,存储到 `SI`。
3. 在 `[bx+4+2]` 即 `[bx+6]` 位置写入 `$`,缓冲区变为:mov dx,offset INPUT_PHONE mov ah,09h int 21h1
2
3
这使得输入的字符串以 `$` 结束,可以使用 DOS 中断 21h, 功能码 09h 显示字符串。mov dx,offset PHONE_BUF mov ah,0Ah int 21h1
2
3
提示输入电话号码。mov bx,dx mov al,byte ptr [bx+1] mov ah,0 mov si,ax mov byte ptr [bx+si+2],'$'1
2
3
读取用户输入的电话号码,存储在`PHONE_BUF`中。;保存数据 mov bx,offset ALL_DATA mov ax,ds:[DATA_COUNT] mov cx,34 mul cx add bx,ax ;ary+count*341
2
3
将电话号码字符串的结尾设为`$`,以便显示。;给标志 mov word ptr [bx],1 mov cx,8 mov si,2 mov bp,offset NAME_BUF LOOP1: mov ax,word ptr ds:[bp+si] mov word ptr [bx+si],ax add si,2 dec cx jnz LOOP11
2
3
计算新联系人在`ALL_DATA`中的存储位置。NAME_BUF db 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 1201
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
复制姓名数据到`ALL_DATA`中的对应位置。
**`mov ax, word ptr ds:[bp+si]`**:
- 从 `NAME_BUF`(`BP` 寄存器指向)加上 `SI` 偏移量的位置读取一个字(16 位)到 `AX` 寄存器。
**`mov word ptr [bx+si], ax`**:
- 将 `AX` 中的数据写入到 `BX` 指向的位置加上 `SI` 偏移量的位置。
**`add si, 2`**:
- 更新 `SI` 寄存器,将其偏移量增加 2,移动到下一个字(16 位)的位置。
**`dec cx`**:
- 将 `CX` 寄存器的值减 1,减少循环次数。
**`jnz LOOP1`**:
- 如果 `CX` 不为零,则跳回 `LOOP1` 标签,继续循环
**示例**
假设 `NAME_BUF` 的内容如下:mov cx,8 mov si,18 mov di,2 mov bp,offset PHONE_BUF LOOP2: mov ax, word ptr ds:[bp+di] mov word ptr [bx+si], ax add si, 2 add di, 2 dec cx jnz LOOP2 inc ds:[DATA_COUNT]1
2
3
执行这段代码时,`NAME_BUF` 从偏移量 `2` 开始的数据(`30 40`, `50 60`, `70 80`)将被复制到 `BX` 指向的内存位置,每次复制一个字(16 位)。这段代码假设 `NAME_BUF` 至少有 16 字节的数据。jmp SHOW_MENU1
2
3
复制电话号码数据到`ALL_DATA`中的对应位置,并增加联系人数量。MyStack segment stack db 256 dup(?) MyStack ends1
2
3
4
5
6
7
8
9
10
11
返回显示菜单。
![image-20240914211913891](../image/image-20240914211913891.png)
MyData segment
MENU1 db “1.add”, 0dh, 0ah
db “2.delete”, 0dh, 0ah
db “3.modify”, 0dh, 0ah
db “4.query”, 0dh, 0ah
db “5.exit”, 0dh, 0ah, ‘$’
INPUT_ERROR db “input error”, 0dh, 0ah, ‘$’
INPUT_NAME db “input name:”, 0dh, 0ah, ‘$’
INPUT_PHONE db “input phone:”,0dh, 0ah, ‘$’
NAME_BUF db 16, 0, 16 dup(0)
PHONE_BUF db 16, 0, 16 dup(0)
ALL_DATA db 340 dup(0) ;flag[2] name[16] phone [16]
NEXT_LINE db 0DH, 0AH, ‘$’
DATA_COUNT dw 0 ;数量
MyData ends
;代码段
MyCode segment
MAIN:
mov ax, MyData
mov ds, ax
mov es, ax ;定义数据段
SHOW_MENU:
mov dx, offset MENU1
mov ah, 09h
int 21h ;显示菜单
GET_INPUT:
mov ah, 01h ;获取用户输入
int 21h
cmp al, '1'
jz ADD1
cmp al, '2'
jz DELETE1
cmp al, '3'
jz MODIFY1
cmp al, '4'
jz QUERY1
cmp al, '5'
jz EXIT1
jmp DEFAULT1
ADD1:
mov dx, offset NEXT_LINE
mov ah, 09h
int 21h
;增加联系人
mov dx, offset INPUT_NAME
mov ah, 09h
int 21h
mov dx, offset NAME_BUF
mov ah, 0Ah
int 21h
; 获取输入的字符串长度并添加终止符
mov bx, dx
mov al, byte ptr [bx+1]
mov ah, 0
mov si, ax
mov byte ptr [bx+si+2], '$'
mov dx, offset NEXT_LINE
mov ah, 09h
int 21h
mov dx, offset INPUT_PHONE
mov ah, 09h
int 21h
mov dx, offset PHONE_BUF
mov ah, 0Ah
int 21h
; 获取输入的字符串长度并添加终止符
mov bx, dx
mov al, byte ptr [bx+1]
mov ah, 0
mov si, ax
mov byte ptr [bx+si+2], '$'
mov dx, offset NEXT_LINE
mov ah, 09h
int 21h
; 保存数据
mov bx, offset ALL_DATA
mov ax, ds:[DATA_COUNT]
mov cx, 34
mul cx
add bx, ax ; ary+count*34
; 给标志
mov word ptr [bx], 1
mov cx, 8
mov si, 2
mov bp, offset NAME_BUF
LOOP1:
mov ax, word ptr ds:[bp+si]
mov word ptr [bx+si], ax
add si, 2
dec cx
jnz LOOP1
mov cx, 8
mov si, 18
mov di, 2
mov bp, offset PHONE_BUF
LOOP2:
mov ax, word ptr ds:[bp+di]
mov word ptr [bx+si], ax
add si, 2
add di, 2
dec cx
jnz LOOP2
inc ds:[DATA_COUNT]
jmp SHOW_MENU
DELETE1:
jmp SHOW_MENU
MODIFY1:
jmp SHOW_MENU
QUERY1:
mov dx, offset NEXT_LINE
mov ah, 09h
int 21h
mov bx, offset ALL_DATA
mov cx, ds:[DATA_COUNT]
LOOP3:
cmp word ptr [bx], 0
je LABEL1
lea dx, [bx+2]
mov ah, 09h
int 21h
mov dx, offset NEXT_LINE
mov ah, 09h
int 21h
lea dx, [bx+18]
mov ah, 09h
int 21h
mov dx, offset NEXT_LINE
mov ah, 09h
int 21h
LABEL1:
add bx, 34 ; ary+count*34
dec cx
jnz LOOP3
jmp SHOW_MENU
EXIT1:
mov ax, 4c00h ;退出程序
int 21h
DEFAULT1:
mov dx, offset INPUT_ERROR
mov ah, 09h
int 21h
jmp SHOW_MENU
MyCode ends
end MAIN
1 |
|
QUERY1:
mov bx,offset ALL_DATA
mov cx,ds:[DATA_COUNT]
LOOP3:
cmp word ptr [bx],0
je LABEL1
1 |
|
lea dx,[bx+2]
mov ah,09h
int 21h
mov dx,offset NEXT_LINE
mov ah,09h
int 21h
lea dx,[bx+18]
mov ah,09h
int 21h
mov dx,offset NEXT_LINE
mov ah,09h
int 21h
1 |
|
LABEL1:
add bx,34 ;ary+count*34
dec cx
jnz LOOP3
1 |
|
jmp SHOW_MENU
1 |
|
EXIT1:
mov ax,4c00h
int 21h
1 |
|
DEFAULT1:
mov dx,offset INPUT_ERROR
mov ah,09h
int 21h
jmp SHOW_MENU
1 |
|
MyCode ends
end MAIN
结束代码段,并定义程序入口点为`MAIN`。