实验2 多个逻辑段的汇编源程序编写与调试
实验结论
1、实验任务1
任务1-1
task1_1.asm源码:
1 assume ds:data, cs:code, ss:stack 2 data segment 3 db 16 dup(0) ; 预留16个字节单元,初始值均为0 4 data ends 5 stack segment 6 db 16 dup(0) ; 预留16个字节单元,初始值均为0 7 stack ends 8 code segment 9 start: 10 mov ax, data 11 mov ds, ax 12 mov ax, stack 13 mov ss, ax 14 mov sp, 16 ; 设置栈顶 15 mov ah, 4ch 16 int 21h 17 code ends 18 end start
task1_1调试到line17结束、line19之前截图

问题回答
1)在debug中将执行到line17结束、line19之前,记录此时:寄存器(DS) = _076A_, 寄存器(SS) = _076B_, 寄存器(CS) = _076C__
2)假设程序加载后,code段的段地址是X,则,data段的段地址是_ X-2h__, stack的段地址是 _ X-1h__
任务1-2
task1_2.asm源码:
1 assume ds:data, cs:code, ss:stack 2 data segment 3 db 4 dup(0) ; 预留4个字节单元,初始值均为0 4 data ends 5 stack segment 6 db 8 dup(0) ; 预留8个字节单元,初始值均为0 7 stack ends 8 code segment 9 start: 10 mov ax, data 11 mov ds, ax 12 mov ax, stack 13 mov ss, ax 14 mov sp, 8 ; 设置栈顶 15 mov ah, 4ch 16 int 21h 17 code ends 18 end start
task1_2调试到line17结束、line19之前截图

问题回答
1)在debug中将执行到line17结束、line19之前,记录此时:寄存器(DS) = _076A_, 寄存器(SS) = _076B_, 寄存器(CS) = _076C__
2)假设程序加载后,code段的段地址是X,则,data段的段地址是_ X-2h__, stack的段地址是 _ X-1h__
任务1-3
task1_3.asm源码:
assume ds:data, cs:code, ss:stack 2 data segment 3 db 20 dup(0) ; 预留20个字节单元,初始值均为0 4 data ends 5 stack segment 6 db 20 dup(0) ; 预留20个字节单元,初始值均为0 7 stack ends 8 code segment 9 start: 10 mov ax, data 11 mov ds, ax 12 mov ax, stack 13 mov ss, ax 14 mov sp, 20 ; 设置栈顶 15 mov ah, 4ch 16 int 21h 17 code ends 18 end start
task1_3调试到line17结束、line19之前截图

问题回答
1)在debug中将执行到line17结束、line19之前,记录此时:寄存器(DS) = _076A_, 寄存器(SS) = _076C_, 寄存器(CS) = _076E__
2)假设程序加载后,code段的段地址是X,则,data段的段地址是_ X-4h__, stack的段地址是 _ X-2h__
任务1-4
task1_4.asm源码:
1 assume ds:data, cs:code, ss:stack 2 code segment 3 start: 4 mov ax, data 5 mov ds, ax 6 mov ax, stack 7 mov ss, ax 8 mov sp, 20 9 mov ah, 4ch 10 int 21h 11 code ends 12 data segment 13 db 20 dup(0) 14 data ends 15 stack segment 16 db 20 dup(0) 17 stack ends 18 end start
task1_4调试到line9结束、line11之前观察寄存器DS, CS, SS值的截图

问题回答
1)在debug中将执行到line9结束、line11之前,记录此时:寄存器(DS) = _076C_, 寄存器(SS) = _076E_, 寄存器(CS) = _076A__
2)假设程序加载后,code段的段地址是X,则,data段的段地址是_ X+2h__, stack的段地址是 _ X+4h__
任务1-5
1)对于如下定义的段,程序加载后,实际分配给该段的内存空间大小是 _ [ N / 16 ] * 16 ([ ]为向上取整)___。
1 xxx segment 2 db N dup(0) 3 xxx ends
2)如果将程序task1_1.asm, task1_2.asm, task1_3.asm, task1_4.asm中,伪指令 end start 改成 end , 哪一个程序仍然可以正确执行。结合实践观察得到的结论,分析、说明原因。
task1_4.asm仍然可以运行。
2、实验任务2
汇编源代码:
code segment start: mov ax, 0b800h mov ds, ax mov bx, 0f00h mov cx, 50h ; 160字节需写入80次,对应16进制数50h mov ax, 0403h ; 低位03 高位04 s: mov ds:[bx], ax add bx, 2 loop s mov ah, 4ch int 21h code ends end start
运行结果:

3、实验任务3
补充完整的汇编源码:
1 assume ds:data1, cs:code 2 data1 segment 3 db 50, 48, 50, 50, 0, 48, 49, 0, 48, 49 ; ten numbers 4 data1 ends 5 6 data2 segment 7 db 0, 0, 0, 0, 47, 0, 0, 47, 0, 0 ; ten numbers 8 data2 ends 9 10 data3 segment 11 db 16 dup(0) 12 data3 ends 13 14 code segment 15 start: 16 mov ax, data1 17 mov ds, ax 18 mov bx, 0 19 mov cx, 0ah ; 循环10次,对应16进制数0ah 20 s: mov ax, ds:[bx] 21 add ax, ds:[bx+10h] ; 将data2中对应数据加到ax 地址相差16字节,即10h 22 mov ds:[bx+20h], ax ; 把ax数据存入data3对应位置 地址相差32字节,即20h 23 inc bx 24 loop s 25 26 mov ah, 4ch 27 int 21h 28 code ends 29 end start
反汇编

在数据项依次相加之前,查看逻辑段data1, data2, data3对应的内存空间数据原始值的 debug命令
使用g 8 命令调试到循环执行前,再使用d ds:0命令查看内存空间数据原始值

使用g 16命令调试到循环执行结束,再使用d ds:0命令查看相加后内存空间数据

可见实现了把逻辑段data1和逻辑段data2的数据依次相加,结果保存到逻辑段data3中的要求。
4、实验任务4
补充完整的汇编源码:
1 assume cs:code 2 3 data1 segment 4 dw 2, 0, 4, 9, 2, 0, 1, 9 5 data1 ends 6 7 data2 segment 8 dw 8 dup(?) 9 data2 ends 10 11 ;定义栈段stack 12 stack segment 13 dw 8 dup(0) 14 stack ends 15 16 code segment 17 start: 18 ; 将data1数据入栈 19 mov ax, data1 20 mov ds, ax 21 mov sp, 9 ; 设置栈顶为9 22 mov bx, 0 23 mov cx, 8 ; 共8个元素,循环8次 24 s1: push ds:[bx] 25 add bx, 2 26 loop s1 27 28 ; 将栈内数据出栈到data2 29 mov ax, data2 30 mov ds, ax 31 mov bx, 0 32 mov cx, 8 33 s2: pop ds:[bx] 34 add bx, 2 35 loop s2 36 37 mov ah, 4ch 38 int 21h 39 code ends 40 end start
执行前数据段data1、data2内数据

执行后数据段data2内数据(即地址076A:0010开始)

可见正确实现了把逻辑段data1中的8个字数据逆序存储到逻辑段b中的要求。
5、实验任务5
task5.asm源码:
1 assume cs:code, ds:data 2 data segment 3 db 'Nuist' 4 db 2, 3, 4, 5, 6 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
运行结果截图:

使用debug工具对程序进行调试,使用g命令一次性执行到程序返回前截图:

源代码中line19的作用:
将小写字母转换为大写字母。
修改line4里5个字节单元的值(将值全部改为2),重新汇编、链接、运行,运行结果:
![]()
可见字符串颜色改变,因此猜测这里的数值作用为控制输出字符的显示颜色。
6、实验任务6
补全后的task6.asm源码:
1 assume cs:code, ds:data 2 3 data segment 4 db 'Pink Floyd ' 5 db 'JOAN Baez ' 6 db 'NEIL Young ' 7 db 'Joan Lennon ' 8 data ends 9 10 code segment 11 start: 12 mov ax, data 13 mov ds, ax 14 15 mov ax, data 16 mov es, ax 17 18 mov bx, 0 19 mov cx, 4 ; 外层4个表达式,循环4次 20 21 s0: mov si, cx 22 mov cx, 4 ; 内层转换第一个单词(4字符),循环4次 23 24 s1: mov al, es:[bx] 25 or al, 20h ; 大写->小写 or 00100000B 即or 20h 26 mov es:[bx], al; 27 inc bx 28 loop s1 29 30 mov cx, si 31 mov bx, 0 32 mov ax, es 33 inc ax 34 mov es, ax 35 loop s0 36 37 mov ah, 4ch 38 int 21h 39 code ends 40 end start
在程序退出前,使用d命令查看数据段data对应的内存空间的截图:
在debug中使用反汇编命令u观察到退出语句地址为076A:002C
使用g 002C命令后使用d ds:0命令查看数据段data对应内存空间数据

可见正确实现了将data段中的每行第一个单词从大写->小写。
7、实验任务7
补全的task7.asm源码:
1 assume cs:code, ds:data, es:table 2 3 data segment 4 db '1975', '1976', '1977', '1978', '1979' ; 起始地址0 每次偏移量4 5 dw 16, 22, 382, 1356, 2390 ; 起始地址20 每次偏移量2 6 dw 3, 7, 9, 13, 28 ; 起始地址30 每次偏移量2 7 data ends 8 9 table segment 10 db 5 dup( 16 dup(' ') ) ; 11 table ends 12 13 code segment 14 start: 15 mov ax, data 16 mov ds, ax 17 mov ax, table 18 mov es, ax 19 20 mov cx, 5 21 mov bx, 0 22 mov si, 0 23 mov di, 0 24 s: 25 mov ax, [bx+2] 26 mov es:[di+2], ax 27 mov ax, [bx] 28 mov es:[di], ax 29 mov ax, [si+20] 30 mov word ptr es:[di+5], 0 31 mov word ptr es:[di+7], ax 32 mov ax, [si+30] 33 mov word ptr es:[di+11], ax 34 mov word ptr es:[di+9], 0 35 mov ax, es:[di+7] 36 div byte ptr es:[di+11] 37 mov byte ptr es:[di+13], 0 38 mov es:[di+14], al 39 add bx, 4 40 add si, 2 41 add di, 16 42 loop s 43 44 mov ah, 4ch 45 int 21h 46 code ends 47 end start
在debug中利用u命令反汇编,并利用g命令调试到循环开始前,再利用d命令查看ds, es内原始数据

再次利用g命令调试到程序退出前,利用d命令查看es内数据

可见数据按要求存放在了表格中。
实验总结
1、将字符由大写转换为小写时,可以使用and 0DFH实现,大写转小写可以使用or 20H实现。
2、使用双层循环结构时,需要在内循环开始前保存外循环循环次数(即寄存器cx的值),内循环结束后恢复cx的值。
3、段内定义内存空间N,则程序加载后实际分配给段的内存空间大小是 [ N / 16 ] * 16 ([ ]为向上取整)。
浙公网安备 33010602011771号