zoukankan      html  css  js  c++  java
  • 汇编——实验5

    实验5——编写、调试具有多个段的程序

    一、实验内容

    (1)将下面的程序编译、连接,用debug加载、跟踪,然后回答问题。

    assume cs:code, ds:data, ss:stack
    data segment
      dw 0123h, 0456h, 0789h, 0abch, 0defh, 0fedh, 0cbah, 0987h
    data ends
    
    stack segment
      dw 0, 0, 0, 0, 0, 0, 0, 0
    stack ends
    
    code segment
    start:  mov ax,stack
            mov ss, ax
            mov sp,16
            
            mov ax, data
            mov ds, ax
            
            push ds:[0]
            push ds:[2]
            pop ds:[2]
            pop ds:[0]
            
            mov ax,4c00h
            int 21h
    
    code ends
    end start

    ① CPU执行程序,程序返回前,data段中的数据为多少?

    答: data中的数据为:0123h 0456h 0789h 0abch 0defh 0fedh 0cbah 0987h。与执行程序前data数据段中的数据一致。

    ②CPU执行程序,程序返回前,cs=076ch,ss=076bh,ds=076ah

    ③设程序加载后,code段的段地址为X,则data段的段地址为 X-2,stack段的段地址为 X-1

    (2)将下面的程序编译、连接,用debug加载、跟踪,然后回答问题。

    assume cs:code, ds:data, ss:stack
    data segment
      dw 0123h, 0456h
    data ends
    
    stack segment
      dw 0, 0
    stack ends
    
    code segment
    start:  mov ax,stack
            mov ss, ax
            mov sp,16
            
            mov ax, data
            mov ds, ax
            
            push ds:[0]
            push ds:[2]
            pop ds:[2]
            pop ds:[0]
            
            mov ax,4c00h
            int 21h
    
    code ends
    end start

    ① CPU执行程序,程序返回前,data段中的数据为多少?

    答: data中的数据为:0123h 0456h 。与执行程序前data数据段中的数据一致。

    ②CPU执行程序,程序返回前,cs=076ch,ss=076bh,ds=076ah

    ③设程序加载后,code段的段地址为X,则data段的段地址为 X-2,stack段的段地址为 X-1

    ④对于如下定义的段:

    name segment
    ...
    name ends

    如果段中的数据占N个字节,则程序加载后,该段实际占有的空间为N——N为16的倍数时 ②(N/16+1)*16——N不为16的倍数。

    (3)将下面的程序编译、连接,用debug加载、跟踪,然后回答问题。

    assume cs:code, ds:data, ss:stack
    
    code segment
    start:  mov ax,stack
            mov ss, ax
            mov sp,16
            
            mov ax, data
            mov ds, ax
            
            push ds:[0]
            push ds:[2]
            pop ds:[2]
            pop ds:[0]
            
            mov ax,4c00h
            int 21h
    
    code ends
    data segment
      dw 0123h, 0456h
    data ends
    
    stack segment
      dw 0,0
    stack ends
    end start

    ① CPU执行程序,程序返回前,data段中的数据为多少?

    答: data中的数据为:0123h 0456h 。与执行程序前data数据段中的数据一致。

    ②CPU执行程序,程序返回前,cs=076ah,ss=076eh,ds=076dh

    ③设程序加载后,code段的段地址为X,则data段的段地址为 X+3,stack段的段地址为 X+4

    (4)如果将(1)、(2)、(3)题中的最后一条伪指令"end start"改为"end"(也就是说,不指明程序的入口),则哪个程序仍然可以正确执行?请说明原因。

    答:只有(3)中的程序可以正确执行。因为(3)中的程序在逻辑段的一开始就是代码段,即相应的汇编指令,而其余两个一开始为数据段,如果不指明程序入口,则计算机内部会把数据段即栈段中的信息也当做是相应的汇编指令,从而不能正确执行。不过在该实验中,(1)、(2)、(3)如果去掉start,最后data数据段中的结果同正确执行后一样,但这并不能说明未指明程序入口的程序都能如此,在这里,可能是由于data数据段即之后的栈段中的数据被当做汇编指令后不影响执行结果,倘若出现比如jmp bx等发生跳转的指令后,结果就会大变样了。

    (5)程序如下,编写code段中的代码,将a段和b段中的数据依次相加,将结果存到c段中。

    assume cs:code
    a segment
      db 1,2,3,4,5,6,7,8
    a ends
    
    b segment
      db 1,2,3,4,5,6,7,8
    b ends
    
    c1 segment   
      db 8 dup(0)
    c1 ends        
    code segment
    start:mov ax,a
          mov ds,ax
       
          mov ax,c1
          mov es,ax
       
          mov bx,0
          mov cx,8
    s:    mov al,[bx]
          mov es:[bx],al  ;将a段中的数据放入c段中
          inc bx
          loop s
    
          mov ax,b
          mov ds,ax
    
          mov bx,0
          mov cx,8
    s1:   mov al,[bx]
          add es:[bx],al   ;此时再将b段与c段相加
          inc bx
          loop s1
       
          mov ax,4c00h
          int 21h    
       
    code ends
    end start

    利用debug调试结果如下:

    由debug调试可得:该程序可以正确实现数据相加。

    (6)程序如下,编写code段中的代码,用push指令将a段中的前8个字型数据,逆序存储到b段中。

    assume cs:code
    a segment
      dw 1,2,3,4,5,6,7,8,9,0ah,0bh,0ch,0dh,0eh,0fh,0ffh
    a ends
    
    b segment
      dw 8 dup(0)
    b ends
    
    code segment
    start:mov ax,b
          mov ss,ax
          mov sp,11h  ;定义栈
          mov ax,a
          mov ds,ax
          
          mov bx,0
          mov cx,8
    
    s:    mov ax,[bx]
          push ax
          add bx,2
          loop s
          
          mov ax,4c00h
          int 21h
           
    code ends
    end start

    利用debug调试如下:

    由debug调试可得:a段中的前8个字型数据已逆序存储到b段中。

    在该实验的debug调试中,在一个比较愚蠢的问题上纠结了好久,决定记录下来。一开始在b段中定义了8个字型数据,全为0,然后在执行push ax这一指令之前,我用d命令查看此时b段中的数据为多少,我理所当然的认为此时应该是16个字节全为0,结果却我和想的有所差异,一开始百思不得其解......后来在和同学讨论中发现,此时并没有入栈的操作,故此时栈中的数据全是初始时的数值,并不一定16个字节全为0,而之所以在b段中要定义8个全为0 的字单元,是因为要分配一块内存空间为接下来入栈等操作做准备,而这并不意味这此时栈中全为0。

    为此,我还另写了一小段程序来验证是否正确。

    assume cs:code
    a segment
        dw 8 dup(0)
    a ends
    
    code segment
    start:mov ax,a
          mov ss,ax
          mov sp,10h
          mov bx,0
          mov cx,8
    s:    push bx   ;将0压入栈
          loop s
        
          mov ax,4c00h
          int 21h
    
    code ends
    end start

    二、总结与体会

    在本次试验中,主要收获有以下几点:

    (1)掌握了用u命令准确地反汇编到int 21h结束。其中要用到试验(2)中的结论,不管段中的数据是否占满16个字节,或是否是16的倍数,该段实际占有的空间都是16的倍数,根据该结论将代码段之前的数据段占有的空间算出,再用 [(CX)-1] 减去该值即可得到u反汇编的结束地址。

    (2)巩固了之前第3章所学的栈中的相关知识。当把一段内存空间当作栈段来使用时,初始状态栈是空的,SS的值比较好确定,SP的值需要具体分析,该段内存空间的大小及偏移地址的情况。

    例如:

    assume cs:code,ss:stack,ds:data
    ...
    stack segment
        dw 16 dup(0)
    stack ends
    code segment
    start:mov ax,stack
            mov ss,ax
            mov sp,20h  ;20h=1e+2
    ...
            mov ax,4c00h
            int 21h
    code ends
    end start
    assume cs:code 
    code segment
        dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h
        dw 16 dup(0)
    start:mov ax,cs
            mov ss,ax
            mov sp,30h  ;30h=2e+2
    ...
            mov ax,4c00h
            int 21h
    code ends
    end start

    这两段代码都是书上的原代码,用于区分。第一个将数据与代码放入不同的段中,每一个段的偏移地址都是从0开始,而第二个则不然,数据和代码都是在code段中的,故而在计算偏移地址时需要注意叠加。

    (3)关于 dw 8 dup(0) 指令,经过查阅资料知道了dup 在汇编中是一条伪指令,用来重复初始化数据。

  • 相关阅读:
    第六篇:python高级之网络编程
    第五篇:python高级之面向对象高级
    sublime插件开发教程
    Metatable In Lua 浅尝辄止
    cocos2dx-lua绑定之代码编辑器
    sublime入门文章
    Sublime Text快捷键
    lua中文教程【高级知识】
    lua基本语法
    Lua 不是 C++
  • 原文地址:https://www.cnblogs.com/zjybel/p/10017230.html
Copyright © 2011-2022 走看看