汇编——实验3

该实验主要是对于汇编语言源程序的编写以及调试运行。终于写了第一个汇编程序啦!

一、实验内容

(在调试之前,根据老师之前在课上的演示,通过dir命令查看是否有相关文件。)

练习1:编写汇编源程序t1.asm,对源程序 t1.asm 进行汇编、连接、运行、调试 。

1.在记事本里写入t1.asm的内容,并将txt后缀名修改为asm。

2.通过masm,link等命令进行汇编,连接,运行。如图,程序的运行结果在屏幕上出现了36。

(同时,在c:\masm5 中出现了相关的t1.obj,t1.exe文件:)

3.将 line4和line9种寄存器dl 的值分别修改为 0~9 中任何一个数字,重新汇编→ 连接→运行,观察结果的变化。

结果如图,修改line4和line9中寄存器的值后,屏幕上输出28。

4.用debug对生成的可执行文件 t1.exe 进行调试。

显然,如图,CS中的值为15DF,DS的值为15CF,它们之间满足(CS)=(DS)+10H的关系。CX中的值为16H,即程序的长度为16H。同时查看PSP的头两个字节为CD 20,在这里用d命令查看内存中程序段前缀的内容,从ds:0到ds:f,这是由于PSP在内存中占256个字节,故而偏移地址从0h-fh。

接下来使用u命令对该可执行文件进行反汇编。注意此时反汇编的地址范围根据CX寄存器的值来确定。在该实验中CX中的值为16H,即程序的长度为16H。

接下来使用t命令和p命令单步调试。

练习2:1.编写汇编源程序t2.asm,对源程序 t2.asm 进行汇编、连接、运行、调试 。

对t2.asm进行汇编、连接后,得到t2.exe可执行文件。在清屏之后执行t2.exe,屏幕左上方出现如图所示的house数字36!

2.重新打开t2.asm,尝试将源代码中line7的0433h→0432h, line10 的 0436h→0439h, 然后重新汇编、连接,得到可执行文件 t2.exe。使用 cls 命令清 屏后,再次观察程序运行结果。

如上图所示,在屏幕的左上方出现了蓝色的数字36!

二、延伸思考与分析

1、练习2和实验1的实验任务4有着相似的结果,输出的字符有颜色,还可以做相应的改变。在实验1的任务4中,修改的是段地址从B810H开始的内存单元的内容。在这里段地址是从B800H开始的内存单元。它们都是8086CPU机内存地址空间分配中的显存地址空间部分。所以直接在屏幕上会有所显示结果。

assume cs:code
code segment
             mov ax,0b800h
             mov ds,ax     //将b800h送入ds寄存器中,作为接下来要操作的内存单元的段地址
             
             mov bx,0
             mov [bx],word ptr 0433h  //将0433h依次写入b800:0内存单元中

             add bx,2
             mov [bx],word ptr 0436h  //将0436h依次写入b800:2内存单元中

             mov ax,4c00h   
             int 21h  //实现程序返回功能
code ends
end

在执行完t2.exe文件后,b800:0-b800:3内存单元中的值本应变为 33h,04h,36h,04h,可是由于修改的是显存地址空间,如实验1的任务4,会在屏幕上出现一些很神奇的变化。所以我做了以下尝试,在debug环境下,直接修改b800:0-b800:3内存单元的值为33h,04h,36h,04h,观察是否会发生变化。

经过实验,我的想法是偏移地址为0,2,4等的内存单元中的是值(是显示出字符的ASCII码值)的作用是在屏幕上显示相应的字符。偏移地址为1,3,5等的内存单元中的值是修改字符的颜色。

2.比较练习1和练习2,结果同样是在屏幕上显示相关字符,两者的方式却不同。练习1中是通过调用相关的函数去实现完成它,而练习2则是巧妙地在显存的内存单元中写入相应字符。

三、总结与体会

1.通过课上的学习以及多次实验,掌握了如何在屏幕上输出字符的源程序的几种方式。(其实就是将该字符的ASCII码送入相应的寄存器中的过程)

assume cs:code
code segment
              mov ah,2
              mov dl,3
              add dl,30h   //在屏幕上显示'3'这一字符
              int 21h

              mov ah,4ch
              int 21h
code ends
end

(其中line4和line5的作用是将dl中的数据修改为51,即3的ASCII码。)

 或者

assume cs:code
code segment
             mov ah,2
             mov dl,'3'  //在屏幕上显示'3'这一字符
             int 21h

             mov ah,4ch
             int 21h
code ends
end

若在line4后面加一行add dl 30h,则dl的值变为99,即在屏幕上显示ASCII码为99的字符即'c',经过上机实验得以验证。

或者

如练习2中代码一样,向显存中写入相应数据。

2.在练习1的单步调试时,发现在第一次用p命令调试int 21h后,al中的值发生了变化,变为33h,同样的,在第二次调试完int 21h后,al的值变为36h,发现两次al中的值和当时dl中的值一样,很神奇!同时通过查阅资料还发现,int 21h指令有一系列的使用方法和相关说明(https://blog.csdn.net/RichieVoe/article/details/8235873)。

3.在练习2中,将0433h送入内存单元地址为b800:0中时,发现刚开始直接写 mov [bx],0433h会出现error,一开始还以为不能直接将常数送入内存单元中,可是查了相关资料发现并没有这一规定,再次翻阅课件时才发现问题所在,原来将常数送入内存单元时,由于是常数,无法确定是以字节还是字还是双字等为单位,故而内存单元无法分配空间,所以必须明确指出常数是以什么为单位。应写为 mov [bx],word ptr 0433h(由于0433h是2个字节,故而不能用Byte直接作为该单位)。

总之,每次实验虽然中途会出各种各样的小错误,但是每次都有所收获。我会努力学习更多知识,来慢慢揭开汇编的神奇面纱~

猜你喜欢

转载自www.cnblogs.com/zjybel/p/9973216.html