实验3 多个段的汇编源程序编写与调试
一、实验目的
4. 理解并掌握各种寻址方式的灵活应用
5. 掌握汇编指令loop, and, or,div, mul的用法
二、实验准备
复习教材chapter 6-8章。- chapter 6 包含多个段的程序
- chapter 7 更灵活的定位内存地址的方法
- chapter 8 数据处理的两个基本问题
三、实验内容
1. 实验任务1
使用任意文本编辑器,录入汇编源程序task1.asm。
assume cs:code, ds:data data segment db 'Nuist' db 5 dup(2) data ends code segment start: mov ax, data mov ds, ax mov ax, 0b800H mov es, ax mov cx, 5 mov si, 0 mov di, 0f00h s: mov al, [si] and al, 0dfh mov es:[di], al mov al, [5+si] mov es:[di+1], al inc si add di, 2 loop s mov ah, 4ch int 21h code ends end start
阅读源程序,从理论上分析源代码的功能,尤其是line15-25,循环实现的功能是什么,逐行理解每条指令的功能。
- 使用masm、link对task1.asm进行汇编、链接,得到可执行文件task1.exe,运行并观察结果。
- 使用debug工具对程序进行调试,执行到程序返回前,即line27之前,观察结果。
- 修改line4里5个字节单元的值,重新汇编、链接、运行,观察结果。
1 db 5 dup(2) 2 --> 改成: 3 db 2,3,4,5,6
基于观察,分析、猜测这里的数值作用是什么。
2. 实验任务2
已知数据段data中定义字节数据如下:
1 data segments 2 db 23, 50, 66, 71, 35 3 data ends
编写程序,在屏幕上以十进制整数形式打印输出这5个两位数。
提示:
- 1个两位数如何输出
思路如下:
- 具体处理步骤如下:
第1步,利用除法指令div,计算出每个数位上的数值。
第2步,利用数值和数字字符之间ascII码的关系,把数值→数字字符
第3步,利用系统功能调用int 21h中的2号子功能,输出单个字符。
int 21h中的2号子功能说明如下:
功能:输出单个字符
用法:
1 mov ah, 2 2 mov dl, ×× ; ××是待输出的字符,或其ASCII码值 3 int 21h
-
5个两位数如何输出
利用loop指令,以及,灵活的寻址方式。3. 实验任务3
教材「实验5 编写、调试具有多个段的程序」(1)
程序源码见task3.asm。
4. 实验任务4
教材「实验5 编写、调试具有多个段的程序」(2)
程序源码见task4.asm。
5. 实验任务5
教材「实验5 编写、调试具有多个段的程序」(3)
程序源码见task5.asm。
6. 实验任务6
教材「实验5 编写、调试具有多个段的程序」(4)
7. 实验任务7
教材「实验5 编写、调试具有多个段的程序」(5)
程序源码见task7.asm。
注*: 如果在集成软件环境下编写、汇编这个实验任务,请将段名为c的逻辑段,名称改为c1或别的标识 符。由于早期一些指令集中使用c指代寄存器,如不更正,有些汇编器在汇编时会报错。
1 c segment ; 段名称改成c1或别的合法的标识符 2 ... 3 c ends ; c1
8. 实验任务8
教材「实验5 编写、调试具有多个段的程序」(6)
程序源码见task8.asm。
四、实验结论
1. 实验任务1
源代码文件task1.asm:
assume cs:code, ds:data data segment db 'Nuist' db 5 dup(2) data ends code segment start: mov ax, data mov ds, ax mov ax, 0b800H mov es, ax mov cx, 5 mov si, 0 mov di, 0f00h s: mov al, [si] and al, 0dfh mov es:[di], al mov al, [5+si] mov es:[di+1], al inc si add di, 2 loop s mov ah, 4ch int 21h code ends end start
运行结果截图:
![]()
在debug里调试到程序返回前的截图:
![]()
执行
1 db 5 dup(2) 2 --> 改成: 3 db 2,3,4,5,6
后的运行结果截图:
由此可见,源代码中data段line4的字节数据包含了所显示字节的颜色。
源代码第15~25行的作用是将代码段中的小写字母全部转换为大写,并且为每个字母赋值使其显示相应的颜色并显示在屏幕上。
2. 实验任务2
源代码文件task2.asm:
assume cs:code, ds:data data segment db 23, 50, 66, 71, 35 data ends code segment start: mov ax, data mov ds, ax mov cx, 5 mov si, 0 s1: mov bl, 10;除数 mov ah, 0 mov al, [si] div bl mov bx, ax ;al存放的是商(两位数中的十位数),ah存放的是余数(两位数中的个位数) mov ah, 2 mov dl, 30h add dl, bl;将bl中的数值转化成ASCII码值并存入dl中输出 int 21h mov dl, 30h add dl, bh;将bh中的数值转化成ASCII码值并存入dl中输出 int 21h mov dl," ";每个两位数后输出一个空格 int 21h inc si loop s1 mov ah, 4ch int 21h code ends end start
运行结果:
![]()
3. 实验任务3
源代码文件task3.asm:
assume cs:code, ds:data, ss:stack data segment dw 0123h, 0456h, 0789h, 0abch, 0defh, 0fedh, 0cbah, 0987h data ends stack segment dw 0, 0, 0, 0, 0, 0, 0, 0 stack ends code segment start: mov ax,stack mov ss, ax mov sp,16 mov ax, data mov ds, ax push ds:[0] push ds:[2] pop ds:[2] pop ds:[0] mov ax,4c00h int 21h code ends end start
用debug加载、追踪结果:
![]()
①猜测程序返回前数据段内容为23 01 56 04 89 07 bc 0a ef 0d ed 0f ba 0c 87 09
在debug中用d命令查看数据段内容:
![]()
结果与猜测一致。
②由debug调试结果可知,程序返回前CS=076C,SS=076B,DS=076A。
③设程序加载后,code段的段地址为X,则data段的段地址为X-2,stack段的段地址为X-1。
4. 实验任务4
源代码文件task4.asm:
assume cs:code, ds:data, ss:stack data segment dw 0123h, 0456h data ends stack segment dw 0, 0 stack ends code segment start: mov ax,stack mov ss, ax mov sp,16 mov ax, data mov ds, ax push ds:[0] push ds:[2] pop ds:[2] pop ds:[0] mov ax,4c00h int 21h code ends end start
用debug加载、追踪结果:
![]()
①猜测程序返回前数据段内容为23 01 56 04 00 00 ...(共12个00)
在debug中用d命令查看数据段内容:
![]()
结果与猜测一致。
②由g命令可知,程序返回前CS=076C,SS=076B,DS=076A。
③设程序加载后,code段的段地址为X,则data段的段地址为X-2,stack段的段地址为X-1。
④对于如下定义的段:
1 name segment 2 ... 3 name ends
如果段中的数据占N个字节,则程序加载后,该段实际占有的空间为 16×⌈N/16⌉ 字节。
5. 实验任务5
源代码文件task5.asm:
assume cs:code, ds:data, ss:stack code segment start: mov ax,stack mov ss, ax mov sp,16 mov ax, data mov ds, ax push ds:[0] push ds:[2] pop ds:[2] pop ds:[0] mov ax,4c00h int 21h code ends data segment dw 0123h, 0456h data ends stack segment dw 0,0 stack ends end start
用debug加载、追踪结果:
![]()
①猜测程序返回前数据段内容为23 01 56 04 00 00 ...(共12个00)
在debug中用d命令查看数据段内容:
![]()
结果与猜测一致。
②由g命令可知,程序返回前CS=076A,SS=076E,DS=076D。
③设程序加载后,code段的段地址为X,则data段的段地址为X+3,stack段的段地址为X+4。
6. 实验任务6
如果将(1)、(2)、(3)题中的最后一条伪指令“end start”改为“end”(也就是说,不指明程序的入口),则哪个程序仍然可以运行?请说明原因。
答:task5.exe。因为如果不指明入口位置,程序就会默认以ip=0执行,而不是从start开始执行,而task5.exe的data和stack都在code之后,所以ip本来就为0。
7. 实验任务7
源代码文件task7.asm:
assume cs:code a segment db 1,2,3,4,5,6,7,8 a ends b segment db 1,2,3,4,5,6,7,8 b ends c1 segment ; 在集成软件环境中,请将此处的段名称由c→改为c1或其它名称 db 8 dup(0) c1 ends code segment start: mov ax, a mov ds, ax mov cx,8 mov si,0 s: mov ax,[si] add ax,[si+10H] mov [si+20H],ax inc si loop s mov ax,4c00H int 21H code ends end start
用debug调试结果如下:
![]()
由数据段结果可知,代码正确实现了数据依次相加并存储的功能。
8. 实验任务8
源代码文件task8.asm:
assume cs:code a segment dw 1,2,3,4,5,6,7,8,9,0ah,0bh,0ch,0dh,0eh,0fh,0ffh a ends b segment dw 8 dup(0) b ends code segment start: mov ax,a mov ds,ax mov ax,b mov ss,ax mov si,0 mov cx,8 mov sp,10H s: push [si] add si,2 loop s mov ax,4c00h int 21h code ends end start
用debug调试结果如下:
![]()
由数据段结果可知,代码正确实现了用push逆序存储数据的功能。












浙公网安备 33010602011771号