实验1 8086汇编指令编码和调试

实验结论

1.实验任务2

  ①查看ROM生产日期,命令为:-d ffff:0 ff ,截图如下:

实验1 8086汇编指令编码和调试

   可以看到生产日期在FFFF0~FFFFF这个地址中,日期为01/01/92。

  ②尝试用e命令修改这个生产日期,截图如下:

实验1 8086汇编指令编码和调试

   发现这个生产日期无法随意修改,可以推断出地址FFFF0~FFFFF的内存单元为只读存储器,写入数据操作是无效的。

2.实验任务3

  ①使用e命令,向内存单元填写数据,命令为:-e b800:0 03 04 03 04 03 04 03 04 03 04 ,结果如下图:

实验1 8086汇编指令编码和调试

   ②使用f命令,向内存单元批量填写数据,命令为:-f b800:0f00 0f9f 03 04 ,结果如下图:

实验1 8086汇编指令编码和调试

   ③对b800:0进行数据修改,命令为-e b800:0 03 03 03 03 03 03 03 03 03 03 ,结果如下图:

实验1 8086汇编指令编码和调试

   发现内存数据修改成功,图案由红色变为蓝色。

3.实验任务4

  在dos中输入下面命令:

-a
mov ax, 20
mov ds, ax
mov ss, ax
mov sp, 30
push [0] ; 执行后,寄存器(sp) = 002E
push [2] ; 执行后,寄存器(sp) = 002C
push [4] ; 执行后,寄存器(sp) = 002A
push [6] ; 执行后,寄存器(sp) = 0028
pop [6] ; 执行后,寄存器(sp) = 002A
pop [4] ; 执行后,寄存器(sp) = 002C
pop [2] ; 执行后,寄存器(sp) = 002E
pop [0] ; 执行后,寄存器(sp) = 0030

  问题1:答:逻辑地址为:230H,物理地址为:0022fH。

       问题2:答:push [6] 执行结束, pop [6] 执行之前,使用 d 20:20 2f 查看此 时栈空间数据,截图如下:

实验1 8086汇编指令编码和调试

   问题3:答:pop [0] 指令执行结束后,使用d命令 d 20:0 7 查看此时数据空间内的数据,截图如下:

实验1 8086汇编指令编码和调试

      可以发现数据空间内的数据没有变化。

  问题4:答:把最后四条指令改成截图中的顺序, pop [6] 指令执行结束后,使用d命令 d 20:0 7 查看此时数据空间内的数据,截图如下:

实验1 8086汇编指令编码和调试

      可以发现随着最后出栈顺序的不同,数据空间内的数据发生了变化。

4.实验任务5

  问题1:答:使用t命令单步执行 mov ss,ax 时,不是单步执行完这一条指令就暂停了。在用t命令执行 mov ss, ax 时,后面的下一条指令 mov sp, 30 紧跟着执行了。

实验1 8086汇编指令编码和调试

    从图中可以看出,执行完 mov ss,ax后一条待执行的指令跳到了 mov ax,2021,而sp由00FD变成了0030,而能将sp设为30的指令只有mov sp,30,由此得到在用t命令执行 mov ss, ax 时,后面的下一条指令 mov sp, 30 紧跟着执行了。

 

  问题2:答:图中的073F对应cs寄存器内的值,0180对应ip寄存器内的值,继续执行接下来几条指令可以发现同一现象。因此可以推断出:栈空间内存单元值发生变化的原因是在用t指令执行命令时会产生中断,cpu为了保护现场,会先将IP、CS两个寄存器的值入栈。

实验1 8086汇编指令编码和调试 

5.实验任务6

  程序源码为:

assume cs:code
code segment
start:
    mov cx, 10
    mov dl, '0'
s: mov ah, 2
    int 21h
    add dl, 1
    loop s

    mov ah, 4ch
    int 21h
code ends
end start

   用命令 masm task6.asm; 对程序进行编译,如下图:

实验1 8086汇编指令编码和调试

   用命令 link task6.obj; 进行连接,如下图:

实验1 8086汇编指令编码和调试

   由于psp存放于内存区的前256个字节中,所以进入debug模式后用命令 d 075a:0 ff 来查看psp中的内容,如下图所示:

实验1 8086汇编指令编码和调试

   可以看到psp的前两个字节正是CD 20。

6.实验任务7

  程序补全后代码为:

assume cs:code
code segment
    mov ax, cs
    mov ds, ax
    mov ax, 0020h
    mov es, ax
    mov bx, 0
    mov cx, 17h
s: mov al, [bx]
    mov es:[bx], al
    inc bx
    loop s

    mov ax, 4c00h
    int 21h
code ends
end

  第一个空填cs,原因是题中要求复制 mov ax, 4c00h 之前的指令,也就是从代码段开始到 mov ax, 4c00h 的所有指令,故将代码段起始地址cs赋给数据段。

  第二个空填17h,原因是要完成复制必须要确定要复制的指令的字节数,也即循环次数cx,于是只要数出待复制指令所占的字节数即可。为了得到指令字节数,我先随便赋给cx一个值,然后编译连接后在debug中用u命令显示所有的命令,如下图,接着便可以数出待复制指令的字节数,数出来是23个字节,转换为16进制便是17h,因此将17h赋给cx。

实验1 8086汇编指令编码和调试

  对于第二个空我觉得也可以将这条指令改为 sub cx 5 ,因为cx也可以表示该程序的所有字节总数,故将cx减去不用被复制的指令的字节数就能得到需要被复制指令的字节数,不需要被复制的指令有mov ax,4c00h 和 int 21h ,占5个字节,所以应将cx-5,这样就没有必要一个个去数,更加简单。

  在debug中调试,使用g命令将程序执行到 loop s 之后、 mov ax, 4c00h 之前,用 u0:200 216 反汇编命令查看,发现已经成功复制指令,如下图:

实验1 8086汇编指令编码和调试

 

实验结论

  通过本次实验,我收获了以下知识点:

    (1)地址C0000~FFFFF的内存单元为只读存储器,写入数据操作是无效的。

    (2)地址A0000~BFFFF为显存地址空间,向其中写入数据,这些数据会被输出带显示器上。

    (3)栈底总是在地址较大的一侧,每入栈一次,sp对应减去入栈的字节数,每出栈一次,sp对应加上出栈的字节数,出栈顺序与入栈顺序相反。

    (4)程序存放的内存区域的前256个字节用作程序前缀(PSP),用作dos和程序的通信。

  在调试程序的过程中,我还有了以下几个发现:

    (1)在用t指令执行命令时会产生中断,cpu为了保护现场,会先将IP、CS两个寄存器的值入栈。

    (2)在执行了修改ss的mov指令后,后面的修改sp的mov指令会紧跟着一起执行,其原因我觉得可能是为了保护栈,控制栈段大小。

    (3)mov命令用于寄存器之间传送数据时是占2个字节,用在寄存器和数据之间时占3个字节。

上一篇:Java数组,导入包,foreach控制循环


下一篇:汇编语言实验一