汇编语言实验 2 多个逻辑段的汇编源程序编写与调试
实验任务一
任务1-1
对程序task1_1.asm进行汇编、连接,用 debug加载、跟踪调试,基于结果,回答问题。
- 以下为task1_1.asm源码内容:
//task1_1.asm assume ds:data, cs:code, ss:stack data segment db 16 dup(0) data ends stack segment db 16 dup(0) stack ends code segment start: mov ax, data mov ds, ax mov ax, stack mov ss, ax mov sp, 16 mov ah, 4ch int 21h code ends end start
- 调试到line17结束,line19之前,
输入指令-g 000D
跳转到19行代码前,查看结果:
- 问题回答:记录此时:寄存器(DS)= 076A,寄存器(SS)= 076B,寄存器(CS)= 076C 。假设程序加载后,code段的段地址是X,则,data段的段地址是(x-2), stack的段地址是 (x-1)。
任务1-2
对程序task1_2.asm进行汇编、连接,用debug加载、跟踪调试,基于结果,回答问题。
- 以下为task1_2.asm源码内容:
1 //task1_2.asm 2 assume ds:data, cs:code, ss:stack 3 data segment 4 db 4 dup(0) 5 data ends 6 7 stack segment 8 db 8 dup(0) 9 stack ends 10 code segment 11 start: 12 mov ax, data 13 mov ds, ax 14 15 mov ax, stack 16 mov ss, ax 17 mov sp, 8 18 19 mov ah, 4ch 20 int 21h 21 code ends 22 end start
调试到line17结束,line19之前,输入指令
-g 000D
跳转到19行代码前,查看结果
- 问题回答:记录此时:寄存器(DS) = 076A, 寄存器(SS) = 076B, 寄存器(CS) = 076C 。假设程序加载后,code段的段地址是X,则data段的段地址是(x-2), stack的段地址是 (x-1)。
任务1-3
对程序task1_3.asm进行汇编、连接,用debug加载、跟踪调试,基于结果,回答问题。
- 以下为task1_3.asm源码内容:
1 //task1_3.asm 2 assume ds:data, cs:code, ss:stack 3 data segment 4 db 20 dup(0) 5 data ends 6 stack segment 7 db 20 dup(0) 8 stack ends 9 code segment 10 start: 11 mov ax, data 12 mov ds, ax 13 14 mov ax, stack 15 mov ss, ax 16 mov sp, 20 17 18 mov ah, 4ch 19 int 21h 20 code ends 21 end start
调试到line17结束,line19之前,输入指令
-
-g 000D
跳转到19行代码前,查看结果:
- 问题回答:记录此时:寄存器(DS) = 076A, 寄存器(SS) = 076C, 寄存器(CS) = 076E 。假设程序加载后,code段的段地址是X,则data段的段地址是(x-4), stack的段地址是 (x-2)。
任务1-4
对程序task1_4.asm进行汇编、连接,用 debug加载、跟踪调试,基于结果,回答问题。
- 以下为task1_4.asm源码内容:
1 //task1_4.asm 2 assume ds:data, cs:code, ss:stack 3 code segment 4 start: 5 mov ax, data 6 mov ds, ax 7 8 mov ax, stack 9 mov ss, ax 10 mov sp, 20 11 12 mov ah, 4ch 13 int 21h 14 code ends 15 16 data segment 17 db 20 dup(0) 18 data ends 19 20 stack segment 21 db 20 dup(0) 22 stack ends 23 24 end start
- 调试到line17结束,line19之前,输入指令
-g 000D
跳转到19行代码前,查看结果:
- 问题回答:记录此时:寄存器(DS)= 076C,寄存器(SS)= 076E,寄存器(CS)= 076A 。假设程序加载后,code段的段地址是X,则,data段的段地址是(x+2), stack的段地址是 (x+4)。
任务1-5
基于上述四个实验任务的实践、观察,总结并回答:
- 对于如下定义的段,程序加载后,实际分配给该段的内存空间大小是:max{16,N}b 。
1 xxx segment 2 db N dup(0) 3 xxx ends
- 如果将程序task1_1.asm, task1_2.asm, task1_3.asm, task1_4.asm中,伪指令 end start 改成 end , 发现task1_4.asm可以正确执行,task1_1.asm, task1_2.asm, task1_3.asm 则不能正确执行。分析:task1_4.asm可以正确执行,task1_1.asm, task1_2.asm, task1_3.asm 不能正确执行,因为end start改为end,程序没有标出程序段结束位置,因此无法配对开始位置,task1_4.asm以程序段开始,可以正常运行,task1_1.asm, task1_2.asm, task1_3.asm 以数据段开始,无法识别是否为程序段,因此无法运行。
实验任务二
编写一个汇编源程序,实现向内存单元b800:0f00——b800:0f9f
连续160字节,依次重复填充十六进制数据03 04。
- 以下为实验任务二设计代码 task2.asm:
1 //task2.asm 2 assume cs:code 3 4 code segment 5 start: 6 mov ax,0b800h 7 mov ds,ax 8 mov bx,0f00h 9 mov cx,80 10 11 s: mov [bx],0403h 12 add bx,2 13 loop s 14 15 mov ah, 4ch 16 int 21h 17 code ends 18 end start
- 生成exe文件,测试运行结果如下:
一排❤
实验任务三
已知8086汇编源程序task3.asm代码片段如下:
1 //task3.asm 2 assume cs:code 3 data1 segment 4 db 50, 48, 50, 50, 0, 48, 49, 0, 48, 49 ; ten numbers 5 data1 ends 6 7 data2 segment 8 db 0, 0, 0, 0, 47, 0, 0, 47, 0, 0 ; ten numbers 9 data2 ends 10 11 data3 segment 12 db 16 dup(0) 13 data3 ends 14 15 code segment 16 start: 17 ; ××× 18 code ends 19 end start
要求:
- 编程实现把逻辑段data1和逻辑段data2的数据依次相加,结果保存到逻辑段data3中。
1 //补充代码 2 code segment 3 start: 4 mov ax,data1 5 mov ds,ax 6 7 mov bx,0 8 mov cx,5 9 s: mov ax,[bx] 10 add ax,[bx+16] 11 mov [bx+32],ax 12 add bx,2 13 loop s
- 在debug中加载、反汇编、调试。在数据项依次相加前,和相加后,分别查看三个逻辑段data1,data2, data3对应的内存空间,确认逐一相加后,结果的确保存在了逻辑段data3中。查看逻辑段data1,data2,data3对应的内存空间数据原始值的debug命令和截图:
以下为相加前data1、2、3逻辑段对应的内存空间截图:运行命令:
1 -g 0018
再次查看相加后逻辑段data1,data2,data3对应的内存空间数据,确认逐一相加后结果的确保存在了逻辑段data3中。
实验任务四
已知8086汇编源程序task4.asm代码片段如下:
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 stack segment 11 db 16 dup(0) 12 stack ends 13 code segment 14 start: 15 16 ; xxx 17 mov ah, 4ch 18 int 21h 19 code ends 20 end start
- 补全程序:
1 code segment 2 start: 3 mov ax, data1 4 mov ds, ax 5 mov ax, data2 6 mov ss, ax ; 7 mov sp, 10h ; 8 mov bx, 0 9 mov cx, 8 10 s: push [bx] 11 add bx, 2 12 loop s 13 14 mov ah, 4ch 15 int 21h 16 code ends 17 end start
在debug中加载、反汇编、调试:
- 程序退出前,使用d命令查看数据段data2对应的内存空间:
实验任务五
录入源代码:
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
- 运行源程序,得到如下结果:
左下角显示彩色“NUIST”字样。
- 使用debug工具对程序进行调试,使用g命令一次性执行到程序返回前(即ine25执行之后、line27 执行之前):
阅读源程序,从理论上分析源代码的功能,可以得出:
- 源代码中19行:and al,0dfh命令,将任何数与0dfh(11011111)做与运算,将从高到低第3位置0,实现的是将小写字母的二进制表示转换成与之对应的大写字母二进制表示,即小写转换大写的功能。
- 源代码第4行里5个字节单元的值控制字母的颜色,对其稍作修改
db 2,3,4,5,6 --> 改成: db 5 dup(2) 或 db 5 dup(5)
重新汇编,链接,运行,观察结果:
改成 db 5 dup(2):绿色“NUIST”
改成 db 5 dup(5):品红色“NUIST”
实验任务六
已知8086汇编源程序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 ; xxx 13 mov ah, 4ch 14 int 21h 15 code ends 16 end start
- 补全程序,实现将data段中的每行第一个单词从大写->小写,代码如下:
1 code segment 2 start: 3 mov ax,data 4 mov ds,ax 5 mov cx,4 6 mov bx,0 7 s: 8 mov dx,cx 9 mov cx,4 10 mov si,0 11 s0: 12 mov al,ds:[bx+si] 13 or al,00100000B 14 mov ds:[bx+si],al 15 inc si 16 loop s0 17 add bx,16 18 mov cx,dx 19 loop s 20 21 mov ah, 4ch 22 int 21h 23 code ends
- 补全并测试运行程序,用d命令查看data段对应的内存空间:每行第一个单词已经转换为小写。
实验任务七
问题场景描述:Power idea公司1975年-1979年的基本情况如下:
程序task7.asm的逻辑段data中(line4-6),已经定义好了这些数据。task7.asm如下:
1 assume cs:code, ds:data, es:table 2 3 data segment 4 db '1975', '1976', '1977', '1978', '1979' 5 dw 16, 22, 382, 1356, 2390 6 dw 3, 7, 9, 13, 28 7 data ends 8 9 table segment 10 db 5 dup( 16 dup(' ') ) ; 11 table ends 12 13 code segment 14 start: 15 16 mov ah,4ch 17 int 21h 18 code ends 19 end start
- 补全程序,实现题目要求:把年份、收入、雇员人数、人均收入以结构化的方式写入table中,表格中每行数据,在逻辑段 table中占16个字节,各项数据占据字节大小分配如下。期中,数据之间用空格间隔。
assume cs:code, ds:data, es:table data segment db '1975', '1976', '1977', '1978', '1979' dw 16, 22, 382, 1356, 2390 dw 3, 7, 9, 13, 28 data ends table segment db 5 dup( 16 dup(' ') ) ; table ends code segment start: mov ax, data mov ds, ax mov ax, table mov es, ax mov bx, 0 mov bp, 0 mov cx, 5 col1: mov ax, [bx] mov es:[bp], ax mov ax, [bx+2] mov es:[bp+2], ax add bx, 4 add bp, 10h loop col1 mov bp, 5 mov cx, 5 col2: mov ax, [bx] mov es:[bp], ax add bx, 2 add bp, 10h loop col2 mov cx, 5 mov bp, 10 col3: mov ax, [bx] mov es:[bp], ax add bx, 2 add bp, 10h loop col3 mov cx, 5 mov bp, 5 col4: mov ax, es:[bp] mov bl, es:[bp+5] div bl mov es:[bp+8], al add bp,10h loop col4 mov ah, 4ch int 21h code ends end start
- 查看table段的原始信息:
- 使用d命令查看table段对应的内存空间,确认信息已经按要求写入到指定内存: