实验2 汇编源程序编写与汇编、调试
一、实验目的
1. 理解并掌握汇编源程序组成与结构
2. 掌握汇编语言源程序编写→汇编→链接→调试的工具和方法
3. 理解汇编源程序中地址表示、段寄存器的用法
4. 理解和掌握寄存器间接寻址方式[bx]
5. 通过汇编指令loop的使用理解编程语言中循环的本质
二、实验准备
1. 学习/复习第5章使用[bx]和loop实现循环的编程应用示例(教材5.5节,5.8节)
2. 复习第3章「栈」的知识
3. 结合第4章课件,复习完整汇编源程序编写→汇编→连接→运行→调试的方法
4. 复习8086汇编中内存单元地址的表示,以及段寄存器DS, SS, ES, CS的用途
三、实验内容
1.实验任务1
使用任意一款文本编辑器,编写8086汇编源程序ex1.asm。源代码如下:
;ex1.asm assume cs:code code segment mov ax, 0b810h mov ds, ax mov byte ptr ds:[0], 1 mov byte ptr ds:[1], 1 mov byte ptr ds:[2], 2 mov byte ptr ds:[3], 2 mov byte ptr ds:[4], 3 mov byte ptr ds:[5], 3 mov byte ptr ds:[6], 4 mov byte ptr ds:[7], 4 mov ah, 4ch int 21h code ends end
要求:使用8086汇编程序编写、汇编、链接、运行、调试方法,对ex1.asm进行汇编、链接、运行,使 用debug工具调试可执行文件。
- 使用masm、link对ex1.asm进行汇编、链接,得到可执行文件ex1.exe,运行并观察结果。
- 使用debug工具对程序进行调试
- 使用debug加载可执行文件ex1.exe后,使用d命令查看程序段前缀PSP所占的256个字节。
- 结合可执行文件中寄存器CX的值,使用u命令对ex1.exe进行精确反汇编
- 使用g命令执行到程序退出执行之前(即源码文件中line16之前),观察结果。
2.实验任务2
使用任意一款文本编辑器,编写8086汇编源程序ex2.asm。源代码如下:
; ex2.asm assume cs:code code segment mov ax, 0b810h mov ds, ax mov bx, 0 mov ax, 101H mov cx, 4 s: mov [bx], ax add bx, 2 add ax, 101H loop s mov ah, 4ch int 21h code ends end
要求:使用8086汇编程序编写、汇编、链接、运行、调试方法,对ex2.asm进行汇编、链接、运行,使 用debug工具调试可执行文件。
- 使用masm、link对ex2.asm进行汇编、链接,得到可执行文件ex2.exe,运行并观察结果。
- 使用debug工具对程序进行调试。
- 结合可执行文件中寄存器CX的值,使用u命令对ex2.exe进行精确反汇编
- 灵活使用t命令、p命令、g命令,对ex2.exe进行调试。(不一定要单步,有些地方可以用g 命令,一次执行多行汇编指令)
- 把ex2.asm中line9 mov cx, 4 改成 mov cx, 8 ,保存后重新汇编、链接、运行并观察结果。
- 结合上述实验和观察,分析、对比ex2.asm和ex1.asm,它们实现的是否是相同的功能和效果?在 具体实现上有什么不同?
3.实验任务3
综合使用loop,[bx],编写完整汇编程序,实现向内存b800:07b8开始的连续16个字单元重复填充字数据 0237H。
要求:
- 编写汇编源程序
- 给出运行结果截图
- 把填充的字数据,从0237H 改成0239H,再次保存后,汇编、链接、运行,观察结果。
- 把填充的字数据,从0237H 改成0437H,再次保存后,汇编、链接、运行,观察结果。
- 猜测并分析,这个字数据中高位字节里存放的是什么信息,低位字节里存放的是什么信息。
4.实验任务4
- 编写完整汇编源程序,实现向内存0:200~0:23F依次传送数据0~63(3FH)。
- 必做
- 综合使用[bx]和loop,编写汇编源程序 灵活使用debug的t命令、g命令、p命令调试。
- 在程序退出前,用d命令查看 0:200~0:23F,确认是否将0~3F传送至此段内存区域。
- 选做*
- 利用栈的特性,综合使用loop,push实现(限定仅使用8086中已学过指令实现),编 写源程序 灵活使用debug的t命令、g命令、p命令调试。
- 在程序退出前,用d命令查看 0:200~0:23F,确认是否将0~3F传送至此段内存区域。
- 必做
5.实验任务5
教材实验4(3)(P121)
6.实验任务6(选做*)
在linux环境下,编写、汇编、运行、调试一个32位的Intel风格的x86汇编程序。
第1步,使用vim或其它任意文本编辑器,编写一个32位的Intel风格的x86汇编源程序example.asm。
; example.asm glogal _start section .data msg db "a simple test", 0xa len equ $ - msg section .text _start: mov eax, 4 mov ebx, 1 mov ecx, msg mov edx, len int 0x80 mov eax, 1 mov ebx, 0 int 0x80
第2步,使用nasm,对example.asm进行汇编。
nasm -f elf32 example.asm
如汇编成功,会生成目标文件example.o。执行nasm命令后,可以使用 ls 命令查看。
如果希望将来使用gdb工具对可执行文件进行调试,则使用nasm汇编时还需要增加一个选项 -g ,目的 是向目标文件中增加符号和调试的相关信息。即:
nasm -f elf32 example.asm -g
第3步,使用ld,对example.o进行链接。
ld -m elf_i386 example.o -o example
如链接成功,会生成可执行文件example。
第4步,执行可执行文件example。
./example
执行后,可以在shell命令终端查看返回值:
echo $?
显示返回值0,对应源码文件中line18寄存器ebx的值。
把example.asm中line18行中寄存器ebx的值改成别的数值,比如7。重新汇编、链接、运行。再次使 用 echo $? 查看返回值,观察这次返回值是什么。
四、实验结论
1.实验任务1
a.在命令行敲“edit”命令进入编辑器,在编辑器中输入指令。保存为ex1.asm文件

b.使用masm进行汇编

c.使用link进行链接

d.运行ex1.exe,查看结果

由图可得,命令行的右上角确实是出现了四个小图标。
e.使用debug调试ex1.exe程序,使用d命令查看ds:0的前256字节数据,因为d命令一次是查看128字节,所以连续使用两次d命令

f.先使用r查看cx寄存器的值,cx=0031,则该程序指令执行地址是从0000一直到0030,使用u命令进行精准反汇编

e.根据反汇编的结果,我们发现002D是程序执行退出之前的地址,使用g命令执行

2.实验任务2
a.编辑ex2.asm并保存

b.使用masm、link对ex2.asm进行汇编、链接,得到可执行文件ex2.exe

c.执行ex2.exe,观察结果

d.通过cx的值可得到指令结束之前的末地址,通过该地址使用u指令进行反汇编

e.灵活使用t命令、p命令、g命令,对ex2.exe进行调试。

通过图片我们可以看出,虽然t命令和p命令都是单步执行,但是p命令可以执行完子程序,可以看出执行完p命令,cx寄存器会清零。
f.将mov cx,4换成mov cx,8,再次汇编链接执行



从图片可以看出,比原来多了四个图标,即是cx从4增加到8的作用,loop增加了4次循环。
问题分析:
由实验任务1和实验任务2的结果来看,它们实现的是相同的功能和效果。
在具体实现上,实验任务1是直接寻址;而实验任务2是通过bx寄存器间接寻址。
3.实验任务3
该任务3的代码编写可以参考实验任务2的代码,实现思想是相同的。
a.编写代码,命名为ex3.asm

b.汇编、链接、观察结果


与预期结果一致
c.将数据从0237H 改成0239H,重复上面过程

修改后的ex3运行结果:

d.将数据从,从0237H 改成0437H,重复上面过程


问题分析:
三种填充数据,通过控制变量法,我们可以看出,填充数据的高位数据存放的是显示图标的颜色信息,低位数据存放的是图标的显示形状信息。
4.实验任务4
实现向0:200~0:23f依次传递数据0~63,则需要mov操作64次,每传递一次数据则偏移地址+1
a.编写代码,存为ex4.asm

因为初始偏移地址为200h,为了让起始偏移地址为0,则200h/16=20h到段地址
b.因为这次实验并没有向显存区域写入数据,所以不会有显性的结果。首先先反汇编

根据r命令中cx寄存器的值,使用u命令进行反汇编,发现指令执行确实如ex4.asm中编写的一样。
c.要看数据是否确实写入的相应的存储单元,需要将指令运行到程序退出之前,再使用d命令查看相应存储单元的内容

由图可得,0~3f确实是写入0:200~0:23f存储单元里了。
5.实验任务5
题目要求是复制退出程序之前的所有指令,而复制的本质就是复制程序段初地址开始存储单元中存储的指令的机器码,所以以指令段的段地址作为程序段段地址。
因为初始不知道退出前偏移末地址为多少,所以cx寄存器的值先设为0

a.汇编、链接ex5.asm,使用debug工具来调试,反汇编程序得到程序退出前的偏移末地址

由图可得,程序退出之前的偏移末地址为0017 所以cx的值应该是0017
b.修改ex5.asm文件中的cx值,重新编译、链接

c.使用debug调试,查看程序退出前相应存储单元中存储的值

由图可得,存储单元确实是存储了从首指令到程序退出之前所有指令的机器码。
五、实验总结
- 通过这次实验,进一步加深了asm源程序汇编、链接成可运行程序的过程。
- 对t、p、g命令有了更深的理解
- 学会了用debug来调试可运行程序,通过u命令反汇编程序,通过cx寄存器的内容来确定程序退出前偏移地址的末地址。使用d命令查看存储单元的内容来验证实验的成功进行。
浙公网安备 33010602011771号