汇编语言程序设计 实验2 汇编源程序编写与汇编、调试
一、实验目的
1. 理解并掌握汇编源程序组成与结构
2. 掌握汇编语言源程序编写→汇编→链接→调试的工具和方法
3. 理解汇编源程序中地址表示、段寄存器的用法
4. 理解和掌握寄存器间接寻址方式[bx]
5. 通过汇编指令loop的使用理解编程语言中循环的本质
二、实验内容及结果
(一)实验任务一
使用任意一款文本编辑器,编写8086汇编源程序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之前),观察结果。
1、首先使用masm对*.asm文件进行编译,生成包含机器代码的目标文件(*.obj)
编译后没有问题(截图中能看到提示说:0 Warning Errors和0 Severe Errors)这时候再返回到文件夹中就会发现多了一个.obj文件
对 *.obj 目标文件进行连接,得到可执行文件(.exe文件)。运行link后,首先显示一些版本信息,然后提示输入将要被连接的目标文件的名称。注意,“[.OBJ]”提示我们,默认的文件扩展名是obj,**比如要连接的目标文件名是“xxx.obj”,只要在这里输入“xxx”即可。**可如果文件不是以 obj 为扩展名,就要输入它的全名。比如目标文件名为“ xxx.bin ”,就要输入全名。
最后一行有提示信息:no stack segment,在网上查了意思,得知是:程序中没有安排堆栈段。这个警告可以忽略,程序能够运行,并且得到正确的结果。
在这里即可运行ex1.exe文件,得到结果:
2、使用debug工具对程序进行调试
首先使用d命令查看程序段前缀PSP所占的256个字节,结果如下图所示:
再使用u命令对ex1.exe进行精确反汇编,首先可以借助r命令:
故u命令应为:
-u 076A:0 30
结果如下:
由上述结果可以观察到,若要使用g命令执行到程序退出执行之前(即源码文件中line16之前),代码为:
-g 0028
结果如下所示:
(二)实验任务二
使用任意一款文本编辑器,编写8086汇编源程序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命令,一次执行多行汇编指令)
注意:单步调试时,对于循环指令loop, 中断指令int,使用t命令和p命令单步调试的区别。
把ex2.asm中line9 mov cx, 4 改成 mov cx, 8 ,保存后重新汇编、链接、运行并观察结果。
结合上述实验和观察,分析、对比ex2.asm和ex1.asm,它们实现的是否是相同的功能和效果?在具体实现上有什么不同?
1、与实验任务一中的操作步骤类似,同样可以对ex2.asm进行汇编、链接,得到可执行文件ex2.exe,结果如下:
2、使用debug工具对程序进行调试
首先可以结合可执行文件中寄存器CX的值,使用u命令对ex2.exe进行精确反汇编,和之前的操作步骤一样,先使用r命令查看相关信息:
故可以得到u命令为:
-u 076A:0 001B
运行结果如下所示:
再可以灵活使用t命令、p命令、g命令,对ex2.exe进行调试,在这里关于如何使用这些命令,想法是:大部分命令都使用t命令单步执行来调试,但是遇到INT命令或者LOOP命令的时候,使用p命令来调试,因为INT命令类似于高级语言中的函数,如果这个时候还使用t命令的话,会相当于进入到函数内部,但是内部的调试过程不是我们想看到的,故在这里可以使用p命令来调试,而LOOP命令则是循环,我们不需要看到循环的过程,故也使用p命令。调试结果如下所示:
把ex2.asm中line9 mov cx, 4 改成 mov cx, 8 ,保存后重新汇编、链接、运行并观察结果(由于前面的汇编链接运行过程存在重复内容,故这里不再赘述,只展示最后的结果)
小结:
对比ex2.asm和ex1.asm实现的是相同的功能,都是再屏幕上打印图案。但是在具体实现上有所不同。具体体现在循环次数,结果也很好的显示了这一效果,修改前是四个图案,修改后则打印输出了8个图案。
(三)实验任务三
综合使用loop,[bx],编写完整汇编程序,实现向内存b800:07b8开始的连续16个字单元重复填充字数据0237H。
要求:
编写汇编源程序
给出运行结果截图
代码为:
assume cs:code code segment mov ax, 0b800h mov ds, ax mov bx, 07b8h mov cx, 000fh s: mov [bx], 0237h inc bx inc bx loop s mov ax, 4c00h int 21h code ends end
运行过程为:
最后的运行结果为:
可以看出,与预期结果完全一致。接下来把填充的字数据,从0237H 改成0239H,运行结果为:
把填充的字数据,从0237H 改成0437H后的结果为:
由上述结果对比可以看出:bx中前两个字节控制颜色,后两个字节控制形状(不知道对不对0.0
(四)实验任务四
编写完整汇编源程序,实现向内存0:200~0:23F依次传送数据0~63(3FH)。
1、必做部分
综合使用[bx]和loop,编写汇编源程序
灵活使用debug的t命令、g命令、p命令调试。在程序退出前,用d命令查看0:200~0:23F,确认是否将0~3F传送至此段内存区域。
代码如下所示:
assume cs:code code segment mov ax, 20h mov ds, ax mov bx, 0 mov cx, 40h mov al, 0 s:mov [bx], al inc al inc bx loop s mov ax, 4c00h int 21h code ends end
运行结果如下所示:
2、选做部分
利用栈的特性,综合使用loop,push实现(限定仅使用8086中已学过指令实现),编写源程序
灵活使用debug的t命令、g命令、p命令调试。在程序退出前,用d命令查看0:200~0:23F,确认是否将0~3F传送至此段内存区域。
代码如下所示:
assume cs:code code segment mov ax,0020h mov ss,ax mov sp,0040h mov bx,3f3eh mov cx,64 s: push bx sub bh,2 sub bl,2 loop s mov ax,4c00h int 21h code ends end
运行结果如下所示:
(五)实验任务五
补全后的代码为:
assume cs:code code segment mov ax,cs mov ds,ax mov ax,0020h mov es,ax mov bx,0 mov cx,0015h s:mov al,[bx] mov es:[bx],al inc bx loop s mov ax,4c00h int 21h code ends end
运行结果如下所示:
在这里,第一个空中:cs:ip表示cpu执行指令的地址。所有,只要mov ax,cs 就能把该程序在内存里的首地址mov到ax了。
第二个空:cx的值,也就是要求loop循环执行多少次。当程序运行到第8行,也就是mov cx,__ 时,cs:ip是该指令的地址。也就是说,从程序开始IP=0,到第8行,IP的值可以用来表示该程序指令占多少字节。
(六)实验任务六
实验过程中一直出现
error: parser: instruction expected
在互联网上查了好多资料也不知道怎么解决,先放着等有时间再来看看
三、实验总结
等搞定了任务六再来一起写