一、实验目的
1. 理解和掌握将数据、代码、栈放入不同逻辑段的程序的编写和调试 2. 理解具有多个段的汇编源程序对应的目标程序执行时,内存分配方式 3. 掌握大小写字符的转换方法、数字字符和数值之间的转换方法4. 理解并掌握各种寻址方式的灵活应用
5. 掌握汇编指令loop, and, or,div, mul的用法
二、实验准备
复习教材chapter 6-8章。- chapter 6 包含多个段的程序
- chapter 7 更灵活的定位内存地址的方法
- chapter 8 数据处理的两个基本问题
三、实验内容
1. 实验任务1
使用任意文本编译器,录入汇编源程序task1.asm。
1 assume cs:code, ds:data 2 data segment 3 db 'Nuist' 4 db 5 dup(2) 5 data ends 6 7 code segment 8 start: 9 mov ax, data 10 mov ds, ax 11 12 mov ax, 0b800H 13 mov es, ax 14 15 mov cx, 5 16 mov si, 0 17 mov di, 0f00h 18 s: mov al, [si] 19 and al, 0dfh 20 mov es:[di], al 21 mov al, [5+si] 22 mov es:[di+1], al 23 inc si 24 add di, 2 25 loop s 26 27 mov ah, 4ch 28 int 21h 29 code ends 30 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 d1,xx ;xx是待输出的字符,或其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:
1 assume cs:code, ds:data 2 data segment 3 db 'Nuist' 4 db 5 dup(2) 5 data ends 6 7 code segment 8 start: 9 mov ax, data 10 mov ds, ax 11 12 mov ax, 0b800H 13 mov es, ax 14 15 mov cx, 5 16 mov si, 0 17 mov di, 0f00h 18 s: mov al, [si] 19 and al, 0dfh 20 mov es:[di], al 21 mov al, [5+si] 22 mov es:[di+1], al 23 inc si 24 add di, 2 25 loop s 26 27 mov ah, 4ch 28 int 21h 29 code ends 30 end start
使用masm,link对task1.asm进行汇编,链接,得到可执行文件,运行并观察结果:
使用debug工具对程序进行调试:
修改line4里5个字节单元的值,重新汇编、链接、运行,观察结果。
1 db 5 dup(2) 2 --> 改成: 3 db 2,3,4,5,6
猜想:修改之后字符颜色发生了变化,内容没有变化。通过分析可以得到: db 5 dup(2) 表示分配5个字节内存空间并初始化为2, db 2,3,4,5,6 表示分配5个字节内存空间并相应的赋值为2,3,4,5,6。通过上面的结果观察可知,修改的数值对应着字符的颜色,对内容并无影响。
2. 实验任务2
1 assume cs:code,ds:data 2 data segment 3 db 23,50,66,71,35 4 data ends 5 code segment 6 start: 7 mov ax,data 8 mov ds,ax 9 mov di,0 10 mov cx,5 11 12 s1: mov ah,0 13 mov al,ds:[di] 14 mov bl,10 15 div bl 16 mov ds:[10+di],al 17 mov ds:[11+di],ah 18 19 mov ah,2 20 mov dl,ds:[10+di] 21 add dl,30h 22 int 21h 23 24 mov ah,2 25 mov dl,ds:[11+di] 26 add dl,30h 27 int 21h 28 29 mov ah,2 30 mov dl," " 31 int 21h 32 33 inc di 34 loop s1 35 36 mov ax,4c00h 37 int 21h 38 code ends 39 end start
3. 实验任务3
1 assume cs:code, ds:data, ss:stack 2 data segment 3 dw 0123h, 0456h, 0789h, 0abch, 0defh, 0fedh, 0cbah, 0987h 4 data ends 5 6 stack segment 7 dw 0, 0, 0, 0, 0, 0, 0, 0 8 stack ends 9 10 code segment 11 start: mov ax,stack 12 mov ss, ax 13 mov sp,16 14 15 mov ax, data 16 mov ds, ax 17 18 push ds:[0] 19 push ds:[2] 20 pop ds:[2] 21 pop ds:[0] 22 23 mov ax,4c00h 24 int 21h 25 26 code ends 27 end start
(1)运行之后,发现数据段的内容并没有改变:
(2)在程序返回前,cs=076C,ss=076B,ds=076A (3)设程序加载后,code段的段地址为X,则data段的段地址为X-2,stack段的段地址为X-1。4. 实验任务4
1 assume cs:code, ds:data, ss:stack 2 data segment 3 dw 0123h, 0456h 4 data ends 5 6 stack segment 7 dw 0, 0 8 stack ends 9 10 code segment 11 start: mov ax,stack 12 mov ss, ax 13 mov sp,16 14 15 mov ax, data 16 mov ds, ax 17 18 push ds:[0] 19 push ds:[2] 20 pop ds:[2] 21 pop ds:[0] 22 23 mov ax,4c00h 24 int 21h 25 26 code ends 27 end start
(1)data段数据并未发生变化:0123h,0456h
(2)在程序返回前,cs=076C,ss=076B,ds=076A
(3)设程序加载后,code段的段地址为X,则data段的段地址为X-2,stack段的段地址为X-1
(4)对于如下定义的段:
1 name segment 2 ... 3 name ends
如果段中的数据占N个字节,则程序加载后,该段实际占有的空间为 16×(N/16) 字节。
5. 实验任务5
1 assume cs:code, ds:data, ss:stack 2 3 code segment 4 start: mov ax,stack 5 mov ss, ax 6 mov sp,16 7 8 mov ax, data 9 mov ds, ax 10 11 push ds:[0] 12 push ds:[2] 13 pop ds:[2] 14 pop ds:[0] 15 16 mov ax,4c00h 17 int 21h 18 19 code ends 20 data segment 21 dw 0123h, 0456h 22 data ends 23 24 stack segment 25 dw 0,0 26 stack ends 27 end start
(1)CPU执行程序,程序返回前,data段中的数据为 0123H,0456H
(2)CPU执行程序,程序返回前,cs=076AH,ss=076EH,ds=076DH。
(3)设程序加载后,code段的段地址为X,则data段的段地址为X+3,stack段的段地址为X+4。
6. 实验任务6
如果将(1)、(2)、(3)题中的最后一条伪指令“end start”改为“end”(也就是说,不指明程序的入口),则哪个程序仍然可以运行?请说明原因。
答:只有任务5的汇编程序可以正常执行。因为任务5程序的代码段定义于数据段和栈段之前,在顺序执行的过程中会首先执行code segment,而不会因执行了data segment和stack segment导致程序出现不符合预期的情况。
7. 实验任务7
1 assume cs:code 2 a segment 3 db 1,2,3,4,5,6,7,8 4 a ends 5 6 b segment 7 db 1,2,3,4,5,6,7,8 8 b ends 9 10 c1 segment ; 在集成软件环境中,请将此处的段名称由c→改为c1或其它名称 11 db 8 dup(0) 12 c1 ends 13 14 code segment 15 start: 16 mov ax,a 17 mov ds,ax 18 mov cx,8 19 mov si,0 20 21 s: mov ax,[si] 22 add ax,[si+10H] 23 mov [si+20H],ax 24 inc si 25 loop s 26 mov ax,4c00h 27 int 21h 28 code ends 29 end start
8. 实验任务8
1 assume cs:code 2 a segment 3 dw 1,2,3,4,5,6,7,8,9,0ah,0bh,0ch,0dh,0eh,0fh,0ffh 4 a ends 5 6 b segment 7 dw 8 dup(0) 8 b ends 9 10 code segment 11 start: 12 mov ax,a 13 mov ds,ax 14 15 mov ax,b 16 mov ss,ax 17 mov sp,16 18 mov si,0 19 20 mov cx,8 21 22 s: push ds:[si] 23 add si,2 24 loop s 25 mov ax,4c00h 26 int 21h 27 code ends 28 end start