实验3 多个段的汇编源程序编写与调试
一、实验内容
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 ;ds存储data数据段的段地址 mov ax, 0b800H ;b800段属于显存地址范围 mov es, ax ;由寄存器es存储 mov cx, 5 ;loop指令循环次数 mov si, 0 mov di, 0f00h ;显存地址的段偏移量 s: mov al, [si] ;取data数据段第一段的字节数据 and al, 0dfh ;转大写 mov es:[di], al ;将取出的数据存入到显存地址中 mov al, [5+si] ;取data数据段第二段的字节数据 mov es:[di+1], al ;存放,此次存放相对于同一次循环中的上次存放,是将数据放在了高位,用于修改输出的内容的颜色 inc si ;偏移量加1 add di, 2 ;显存的段地质偏移量增2 loop s ;实现跳转 mov ah, 4ch int 21h code ends end start
阅读源程序,从理论上分析源代码的功能,尤其是line15-25,循环实现的功能是什么,逐行理解每条指令的功能。
使用masm、link对task1.asm进行汇编、链接,得到可执行文件task1.exe,运行并观察结果。
使用debug工具对程序进行调试,执行到程序返回前,即line27之前,观察结果。
修改line4里5个字节单元的值,重新汇编、链接、运行,观察结果。
db 5 dup(2) --> 改成: db 2,3,4,5,6
基于观察,分析、猜测这里的数值作用是什么?
代码功能:从理论上分析源代码的功能是通过循环将data数据段中的字母转换为大写,同时修改颜色并在显示器上输出。(line15-25指令功能在代码注释中给出)
1、使用masm、link对task1.asm进行汇编、链接,得到可执行文件task1.exe,运行并观察结果。
(1)、编译、连接,如图:

(2)、运行task1.exe文件(在docbox中运行)

运行结果中可以发先字符串‘Nuist’被转换为大写,同时字体颜色为绿色显示在doc命令窗口上,验证了理论猜测。
2、使用debug工具对程序进行调试,执行到程序返回前,即line27之前,观察结果。

查看data数据段内容,如图:数据段data中的主句如下

3、修改line4里5个字节单元的值,重新汇编、链接、运行,观察结果。运行结果如图:

修改数据之后,运行结果发生变化,字符的颜色变化为五种不同的颜色。
4、使用debug工具调试,查看data段数据:

2、实验任务2
已知数据段data中定义字节数据如下:
data segments db 23, 50, 66, 71, 35 data ends
编写程序,在屏幕上以十进制整数形式打印输出这5个两位数。
assume cs:code data segment db 23, 50, 66, 71, 35 data ends code segment start: mov ax, cs sub ax, 01h mov ds, ax ;ds存储data数据段的段地址 mov dh, 10 ;作为除数 mov si, 0 mov cx, 5 ;循环次数 s: mov ax, [si] mov ah, 00h div dh add al, 30h ;商(低位) add ah, 30h ;余数(高位):数字与其ascii码值差48(30H) mov bl, al mov bh, ah inc si mov ah, 2 mov dl, bl ;输出十位,bl是待输出的字符,或其ASCⅡ码值 int 21h mov dl, bh ;输出个位 int 21h loop s mov ah,4ch int 21h code ends end start
(1)、编译、连接

(2)、使用debug工具调试:
1.进入debug,产看相关内容。

2.使用g命令和t命令对程序进行调试(以下为一次循环的过程)。

3.执行程序(在docbox中执行)

3、实验任务3
教材「实验5 编写、调试具有多个段的程序」(1),程序源码参见task3.asm
将下面的程序编译链接,后用debug加载,跟踪,然后回答问题
;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
①CPU执行程序,程序返回前,data数据段中的数据为多少?
data段中的数据(0~f)为:23 01 56 04 89 07 BC 0A EF 0D ED 0F BA 0C 87 09
②CPU执行程序,程序返回前,cs= ,ss= ,ds= 。
cs,ss,ds寄存器的值:cs=0B68,ss=0B67,ds=0B66;
③设程序加载后,code段的段地址为X,则data段的地址为 ,stack段的段地址为 。
data段的地址为 X - 2 ,stack段的段地址为 X-1 。
(1)对程序进行编译、连接:

(2)使用debug工具调试程序
1.使用g命令执行程序到程序退出前:

执行完g命令后可以查看cs,ss,ds寄存器的值:cs=0B68,ss=0B67,ds=0B66;
在程序中
mov ax,stack ;将stack的段地址传递给寄存器ss mov ss, ax mov ax, data ;将data数据段的地址传递给寄存器ds mov ds, ax
通过以上代码的功能可知到ss寄存器和ds寄存器的是分别是stack段和data段的段地址(程序执行到最后寄存器都未发生改变,数据段的内容少于16字节),
由stack段、data段、代码段的段地址之间的关系可知道,若cs为X,则ss为X-1,ds为X-2;
2.使用d指令查看data段中的数据:

data段中的数据(0~f)为:23 01 56 04 89 07 BC 0A EF 0D ED 0F BA 0C 87 09。
4、实验任务4
教材「实验5 编写、调试具有多个段的程序」(2),程序源码见task4.asm。
将下面的程序编译,连接,用debug加载、跟踪,然后回答问题。
assume cs:code, ds:data, ss:stack data segment dw 0123h, 0456h data ends stack segment dw 0, 0 stack ends ;task4.asm 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
①CPU执行程序,程序返回前,data数据段中的数据为多少?
data段中的数据(0~f)为:23 01 56 04 00 00 00 00 00 00 00 00 00 00 00 00
②CPU执行程序,程序返回前,cs= ,ss= ,ds= 。
cs,ss,ds寄存器的值:cs=0B68,ss=0B67,ds=0B66;
③设程序加载后,code段的段地址为X,则data段的地址为 ,stack段的段地址为 。
data段的地址为 X - 2 ,stack段的段地址为 X-1 。
④对于如下定义的段:
name segment
...
name ends
如果段中的数据占N个字节,则程序加载后,该段实际占有的空间为:⌈N/16⌉*16字节
(1)、对程序编译、连接

(2)、使用debug工具调试程序

程序执行到退出前,查看cs,ss,ds的值为:cs=0B68,ss=0B67 ,ds= 0B66 。
查看data段的数据

前四个字节为23 01 56 04 其余均为0.
(3)、在程序中增加a段
a segment
dw 0102h,3040h,0506h ;共6个字节
a ends
(因为name 的意思bai是模块定义伪操作,被系统征用了name这个名字,使用name作为段名出错)
1.编译连接后使用debug工具调试:

可发现增加一个段中后程序占用的地址空间就增加10h个字节
2.使用的指令查看data,stack以及a这三个数据段的值:

修改as段的数据:dw 0102h, 0304h, 0506h,0102h, 0304h, 0506h,0102h, 0304h, 0506h,增加为9个字数据
3.编译链接后使用debug调试,再次使用d查段中的数据:

4.第二次修改:a段的数据修改位18个字数据(36字节)
编译链接后使用debug调试,再次使用d查段中的数据:

查看寄存器cx的值发先寄存器的值又增加了10h字节
结论:从以上 结果可发现当段中的数据字节数在十六个字节(八个字数据)以内,该段占用的空间都为十六字节,
当段中的数据大于16个字节时(设为N)则占用的地址空间为:⌈N/16⌉*16
5、实验任务5
教材「实验5 编写、调试具有多个段的程序」(3),程序源码见task5.asm。
将下面的程序编译,连接,用debug加载、跟踪,然后回答问题。
;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
①CPU执行程序,程序返回前,data数据段中的数据为多少?
data段中的数据(0~f)为:23 01 56 04 00 00 00 00 00 00 00 00 00 00 00 00
②CPU执行程序,程序返回前,cs= ,ss= ,ds= 。
cs,ss,ds寄存器的值:cs=0B68,ss=0B67,ds=0B66;
③设程序加载后,code段的段地址为X,则data段的地址为 ,stack段的段地址为 。
通过debug调试发现代码段占用30h个字节,data段的地址为 X + 3 ,stack段的段地址为 X+ 4 。
(1)、对程序编译、连接

(2)、使用debug工具调试程序

使用g命令执行到程序返回前:从中可查看:cs=0B66,ss=0B6A,ds=0B69.

使用d指令查看data数据段中的数据:23 01 56 04 00 00 00 00 00 00 00 00 00 00 00 00

6、实验任务6
教材「实验5 编写、调试具有多个段的程序」(4)
如果将(1)、(2)、(3)题中的最后一条伪指令”end start“改为”end“也就是说不知名程序的入口),则哪个程序任然可以正确执行?请说明理由。
(1)修改task3.asm中的伪指令,编译、连接后使用debug指令进行调试:
进行以下操作之后发先task3.asm修改之后不能正确汇编,也不能正确执行。

(2)修改task4.asm中的伪指令,编译、连接后使用debug指令进行调试:
结果与task3.asm相同,修改后不能正确汇编,也不能正确执行。

(3)修改task5.asm中的伪指令,编译、连接后使用debug指令进行调试:

修改过后,只有task5.asm问件在编译链接之后才能进行正确的反汇编,cs寄存器的值才是指令所在段的正确段地址值。
(4)、对比task3.asm、task4.asm、task5.asm三个文件在各个段的内容:



cs的值存放的是存储所有段 的段地址,task3和task4都是指令在最后,而task5是指令在最前(第一段)所以在task5中cs的值就是指令所在段的段地址,
只有task5.asm在修改后程序仍然能够执行。
7、 实验任务7
教材「实验5 编写、调试具有多个段的程序」(5)
程序源码见task7.asm。
注*: 如果在集成软件环境下编写、汇编这个实验任务,请将段名为c的逻辑段,名称改为c1或别的标识
符。由于早期一些指令集中使用c指代寄存器,如不更正,有些汇编器在汇编时会报错。
程序如下:编写code段中的代码,将a段和b段中的数据依次相加结果存到c段中,
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 c segment ; 在集成软件环境中,请将此处的段名称由c→改为c1或其它名称 db 8 dup(0) c ends code segment start: mov ax,cs sub ax,0003h mov ds,ax mov ax,0000h mov bx,0000h mov cx,4 s: mov ax,[bx] mov dx,[bx+10h] add ax,dx mov [bx+20h],ax add bx,2 loop s mov ax,4c00h int 21h code ends end start
(1)、对程序编译、连接

(2)、使用dubug调试查看程序结果:

查看c段的内容,a段和b段的值一次相加的结果正确存放到了c段中。
8、实验任务8
教材「实验5 编写、调试具有多个段的程序」(6),程序源码见task8.asm。
程序如下:编写code段中的代码,用push指令将a段中前8个字型数据逆序存储到c段中。
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,cs sub ax,1 mov ss,ax mov sp,0010h sub ax,2 mov ds,ax mov bx,0000h mov cx,8 s: mov ax,[bx] push ax add bx,2 loop s mov ax,4c00h int 21h code ends end start
(1)、对程序进行编译、连接

(2)、使用debug工具对车光绪进行调试,并查看结果:

浙公网安备 33010602011771号