• 汇编——实验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直接作为该单位)。

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

  • 相关阅读:
    AngularJS(三)——指令实战及自定义指令
    AngularJS(二)——常见指令以及下拉框实现
    AngularJS(一)理论篇
    【leetcode】8 integer to roman
    【leetcode】7 Roman to Integer
    【leetcode】6 Palindrome Number
    【leetcode】5 atoi
    【leetcode】4 Reverse Ingeger
    【leetcode】3 minstack
    【leetcode】2 数组元素右移
  • 原文地址:https://www.cnblogs.com/zjybel/p/9973216.html
Copyright © 2020-2023  润新知