四个太阳

导航

实验1 用机器指令和汇编指令编程

一、实验目的

  1. 熟练掌握使用debug工具编写和调试x86汇编命令的方法
  2. 掌握8086CPU、寄存器、内存的基础知识
  3. 理解并掌握内存中多字节数据的存放:小端法
  4. 理解并掌握「栈」内存空间的特性和使用
  5. 掌握指令mov, add, sub, jmp, push, pop的基础用法

二、实验内容

  1. 教材实验1(P35)
  2. 教材实验2(P71)
  注意,为了便于验证实验结果,对「2. 实验任务」的(1)做如下两点调整:
     ① 在使用 a 命令输入指令调试之前,先使用 e 命令将内存单元 0022:0~0022:7连续 8 个字节数据
       修改为 50H, 51H, 52H, 53H, 54H, 55H, 56H, 57H
     ② 将 P74 实验任务(1)中第1行的 mov ax, ffff → 改为 mov ax, 0022

三、实验过程以及结论

  1. 教材实验1结论

    实验任务(1):使用Debug,用 e 命令和 a 命令两种方式将下面的程序段写入内存,逐条执行,观察每条指令执行后CPU中相关寄存器中内容的变化。

        机器码      汇编指令
       b8  20  4e    mov ax, 4E20
       05  16  14    add  ax, 1416
       bb  00  20      mov ax, 2000
       01   d8       add  ax, bx
      ① 使用 e 命令写入机器码,并用 t 命令单步执行,效果如下:
      
      ② 使用 a 命令写入汇编指令,并用 t 命令单步执行,执行效果如下:
      
 
    实验任务(2):将下面三条指令写入从2000 : 0 开始的内存单元中,利用这三条指令计算 2 的 8 次方。
        mov ax, 1
        add  ax, ax
        jmp  2000 : 2003
      使用 a 命令写入汇编指令并且使用 t 命令单步调试实验结果如下图所示:
      
      
      
 
    实验任务(3):PC机主板上的 ROM 中写有一个生产日期,在内存 FFF00H~FFFFFH 的某几个单元中,请找到这个生产日期并试图改变它。
      使用 d 命令查看 FFF00H~FFFFFH 单元的数据,检查是否有生产日期,实验截图如下所示:
      
 
      从上图可以看出ROM 的生产日期为 1992 年 1 月 1 日。
      当试图改变地址是 FFF0:00F5 至 FFF0:00FC 的内存单元数据时,程序虽然不会报错,但是会发现数据并未被写入,具体内容如下图所示:
      
      以上图情况来看,我们使用了 e 命令去改写地址 FFF0:00F5 至 FFF0:00FC 内存单元的数据,之后使用 d 命令查看改写的内容。
      从中,我们可以得出改写的命令并未执行成功。究其原因,地址为 FFF0:00F5 ~ FFF0:00FC 的内存单元对于 8086 CPU而言其实是
      属于 ROM 所映射的部分地址,凡是向只读存储器(ROM)的内存单元中写入数据的操作都是无效的,因为这等于改写只读存储
      器的内容,这种操作是不被允许的,即使使用了 debug 命令修改其内存单元也会被视为无效指令。
 
    实验任务(4):向内存从 B8100H 开始的单元中填写数据,如: -e  B810:0000 01 01 02 02 03 03 04 04
      
      实验结果如上图所示,可以发现屏幕上出现了几个特殊的字符,而且还带有颜色。其会出现的原因是由于我们向内存空间始址为
      B810:0000 的内存单元连续写入了 8 字节的数据,对于 8086CPU 而言,内存地址为 A000:0000 ~ BFFF:000F 会被映射成显存
      地址的范围,向地址范围是A000:0000 ~ BFFF:000F 的内存单元写入数据,就是向显存中写入数据,而这些数据会被显示卡输出
      到显示器上,这正是在显示屏会显示输出特殊字符的原因所在。

  2. 教材实验2结论

    实验任务(1) :使用 Debug,将下面的程序段写入内存,逐条执行,根据指令执行后的实际运行情况填空。
        mov  ax, 0022
        mov  ds, ax
        mov  ax, 2200
        mov  ss,  ax
        mov  sp, 0100
        mov  ax, [0]
        add   ax, [2]
        mov  bx, [4]
        add   bx, [6]
        push  ax
        push  bx
        pop   ax
        pop   bx
        push  [4]
        push  [6] 
      ① 使用 e 命令修改内存单元0022:0~0022:f 中的数据:50  51  52  53  54  55  56  57,修改完使用 d 命令查看是否正确写入,命令
          执行结果如下图所示:
      
      ② 使用 a 命令将上述汇编指令写入内存单元中,并且使用反汇编 u 命令来查看指令是否被正确写入,实验过程如下图所示:
      
      ③ 使用 t 命令,单步调试每一行汇编指令,实验结果如下图所示:
      
      
      ④ 理论分析结果与实验结果一致,理论分析的过程如下图所示:
      
 
    实验任务(2):仔细观察 3.19 中的实验过程,然后分析:为什么 2000: 0 ~ 2000: f 的内容会发生改变?
      ① 使用 a 命令输入图 3.19 所示 7 条汇编指令,使用 e 命令修改 2000:0~2000:f 的值,以及确认是否修改成功,实验过程如下图所示:
      
      ② 使用 t 命令单步调试每一条汇编指令,同时使用 d 命令查看每一步指令执行内存空间 2000:0~2000:f 所变化的值,实验过程如下图所示:
      
       
      以文字方式陈述:
        ① 前3行汇编指令的功能,特别是,mov sp, 10意味着什么?初始时栈顶和栈底分别是?
                mov  ax, 2000   ; 将数据 2000H 写入到 ax 寄存器当中
          mov  ss, ax   ; 将 ax 中的数据写入到栈段寄存器(ss)当中,即间接将数据 2000H 写入到 ss 寄存器当中去
          mov  sp, 10   ; 将数据 10 H 写入到栈顶指针寄存器当中,即定义一个基址为 20000H 而栈长为 8 字的栈    
          前三行汇编指令的功能是:定义一个栈基址为 20000H,栈长为 8 字的栈空间。
          mov  sp, 10 ;意味着栈顶地址相对于栈基址的偏移量为 10 H
          初始化栈顶的实际物理地址为:20010 H
          初始化栈底的实际物理地址为:2000E H
 
        ② 基于单步调试观察到的变化,给出你对此的思考及可能原因分析。
          下图的内存空间是仅对于出入栈的数据变化所画的图解:
        

 

 

          但是在实验验证过程中,当Debug执行完 mov sp, 10 这条汇编指令的时候,此时使用 d 命令发现栈中存有数据,而之前使用 e 命令
          写入的数据居然被覆盖了,但是仔细观察后,发现此时栈中存放的数据全部都是 8086CPU 中某些寄存器的值,从图中可以发现栈中存
          有CS、IP、BP、AX等寄存器的值了,这说明这是设计者有意为之,考虑到栈中每一次执行指令的时候,Dos 将相关数据存储在栈中的
          数据都必会有CS、IP这两个寄存器的值,而凡是被这两个寄存器所指向的内存单元都被认为是指令,同时栈中还存有先前 AX 寄存器的
          值。由此可以推断 DOS 系统中只有一个栈,并且系统会用该栈暂存相关数据,以便执行下一条指令,而此实验中正好改变了系统中
          SS、SP 的值,由此可见系统Debug单步调试的 t 命令执行汇编指令所需的数据全部都存放在栈当中。
 

posted on 2020-10-15 23:33  四个太阳  阅读(301)  评论(3编辑  收藏  举报