实验三

 

实验结论:

练习一:

第一步(编写t1.asm源文件):

在路径D:\masm下创建文本文档,在其中打入如下代码:

assume cs:code

 code segment

         mov ah,2H

         mov dl,3H

         add dl,30H

         int 21H

        

         mov ah,2H

         mov dl,6H

         add dl,30H

         int 21H

 

         mov ax,4c00H

         int 21H

 code ends

end

第二步(使用dosbox对源文件进行编译、连接、执行):

此处使用一个批处理文件process.bat对源文件进行编译、连接:

编译、连接过程如下图:

生成exe文件:

清屏并执行t1.exe(如下图):

 

得到输出结果:两个数字3和6。

第二步:将 4 和9行 中寄存器 dl 的值分别修改为5和7,并重新汇编→ 连接→运行,观察结果的变化(如下):

 

 

输出结果为5和7。

第三步:用 debug 对生成的可执行文件 t1.exe 进行调试。

使用r命令查看当前状态下的各寄存器中的值(如下图):

 

 

发现cx中的值为17h,为十进制中的23,在查看所写代码的长度恰好为23个字节,ds和cs中的值分别为075A和076A,恰好满足cs=ds+10h。

第四步:查看PSP(程序段前缀)的头两个字节,验证是否为CD和20

 

 

第五步:使用 u 命令对 t1.exe 进行反汇编,观察反汇编得到的源代码:

 

 

第六步:使用 t 命令和 p 命令(遇到 int 命令时,用 p 命令)单步调试,观察结果:

 

 

 

由此可发现屏幕上显示的5和7并不是五十七,而是分次输出的5和7,原理是将需要输出的数据放入dl中,输出就是将dl中的数据通过ascll码转为对应的字符,并显示在屏幕上。

 

练习二:

第一步(编写t2.asm源文件):

在路径D:\masm下创建文本文档,在其中打入如下代码:

assume cs:code

 code segment

         mov ax,0b800H

         mov ds,ax

        

         mov bx,0H

         mov [bx],0433h

        

         mov bx,2H

         mov [bx],0436h

 

         mov ax,4c00H

         int 21H

 code ends

end

写完之后保存为asm文件。

第二步(使用dosbox对源文件进行编译、连接、执行):

此处使用一个批处理文件process.bat对源文件进行编译、连接:

编译、连接过程如下图:

编译生成obj文件:

 

 

连接生成可执行的exe文件:

 

 

清屏之后执行t2.exe:

 

 

通过对程序运行结果的观察发现在屏幕左上角出现了红色的36。

第三步:重新打开t2.asm并将7行和10行赋给[0]和[2]的值改为0432h和0439h,再次对t2.asm进编译、连接、执行:

执行结果如下图:

 

 

第四步:将t2.asm文件中的7和10行中赋给[0]和[2]的值改为0333h和0336h后,对t2.asm进行汇编、连接、执行:

结果如下图:

 

 

得到蓝色的36。

猜想:0b800h这个段地址是文本模式显示内存的段地址,通过对其中写出字型数据,就可以使屏幕上显示对应的数值并控制数值的颜色。

尝试:将t2.asm改写为以下的内容:

assume cs:code

 code segment

         mov ax,0b800H

         mov ds,ax

        

         mov bx,0H

         mov [bx],0333h

        

         mov bx,2H

         mov [bx],0436h

        

         mov bx,4H

         mov [bx],0237h

 

         mov ax,4c00H

         int 21H

 code ends

end

 

 

注:令数据段寄存器中所存储的数据为b800h之后,从偏移地址为0的地方依次向内存单元写入数据,发现低位字节用来控制输出什么字符,高位字节用来控制输出的字符的颜色。

在此基础上继续对t2.asm进行更改:更改如下:

assume cs:code

 code segment

         mov ax,0b800H

         mov ds,ax

        

         mov bx,1H

         mov [bx],0333h

        

         mov bx,3H

         mov [bx],0436h

        

         mov bx,5H

         mov [bx],0237h

 

         mov ax,4c00H

         int 21H

 code ends

end

更改后的代码与原代码的区别在于:人为的向内存中写入数据不再是从偏移地址为0处开始写的,而是从偏移地址为1处开始写,对更改过的t2.asm进行汇编、连接、执行(执行结果如下图):

 

 

 

出现问题,输出并不是不同颜色的367,而是其他字符,对修改过的t2.exe进行debug,查看b800相关偏移地址中存放的数据是什么(如下图):

 

 

执行完了t2.exe之后对b800:0到b800:6中的数据进行查看:发现对对应偏移地址的数据写入确实成功了,并且右侧确实按照ascll码显示出了3,6,7这三个数字,但是屏幕左上角出来的的字符中并没有367,显示出来的字符是从偏移地址为0处开始2个2个向后看,每看两个在屏幕上显示一个字符。

经过验证:[0]中存放的字型数据3320h(在debug对内存的查看,发现20这个字节数据并没有字符和它对应如图:

 

 

)就是蓝色块,[2]中的3603h就是出现的蓝色背景的红心图案,而[4]中存放的3704h就是背景为蓝色的灰色菱形图案,[6]中存放的0702h就是灰色笑脸图案。

另外:在尝试的过程中,给以b800位段地址的偏移地址[bx]赋值的时候,好像只可以传字型数据,如果传送字节型数据,会报severe error错误。

再次改变t2.asm中的代码如下:

assume cs:code

 code segment

         mov ax,0b800H

         mov ds,ax

        

         mov bx,2H

         mov [bx],0333h

        

         mov bx,4H

         mov [bx],0436h

        

         mov bx,6H

         mov [bx],0237h

 

         mov ax,4c00H

         int 21H

 code ends

end

结果如图:

 

 

 

成功地将367显示出来,猜想得到验证。

附:

在集成实验环境下运行t2.asm

打入代码保存运行:报错A2070

 

 

经过查阅资料发现:在使用mov指令时最规范的写法是将操作数的长度规定好(即类型的强制转换)。

原代码:

 

 

改过后的代码:

 

 

经修改,运行成功(如下):

 

 

实验感悟:

练习一:通过对d中数据的操作,了解到通过给dl赋值可以在屏幕上打印dl中所存的数据对应ascll码的字符。以及cs和ds中数据的关系、cx中存放数值的意义。

练习二:通过对t2代码的改写,了解到:b800h是文本模式显示内存的段地址,并且对字符的显示是从0偏移地址开始的,并且是按字数据读取(高位字节控制属性,低位字节控制显示字符)。

与实验一练习四的对比:

实验一中要求从b810:0处通过e命令开始向内存写入数据,练习二中使用的是改变ds寄存器中的值为b800,并通过[address]来实现向内存中写入数据,但它们本质上都是改变内存中的数据。并且还发现:b8000h和b8100h这两个物理地址位于同一个段(b800:0~b800:ffff)中。(思考:这一个地址段的作用是什么?这一个地址段是文本模式显示内存吗?从字面意思对应到实验过程,确实发现这一个地址段可以实现文本+模式+显示的作用)

 

 

posted @ 2018-11-16 19:42  yys_c  阅读(320)  评论(0编辑  收藏  举报