实验3 多个段的汇编源程序编写与调试

一、实验目的

1. 理解和掌握将数据、代码、栈放入不同逻辑段的程序的编写和调试

2. 理解具有多个段的汇编源程序对应的目标程序执行时,内存分配方式

3. 掌握大小写字符的转换方法、数字字符和数值之间的转换方法

4. 理解并掌握各种寻址方式的灵活应用 5. 掌握汇编指令loop, and, or,div, mul的用法

二、实验准备

复习教材chapter 6-8章。

chapter 6 包含多个段的程序

chapter 7 更灵活的定位内存地址的方法

chapter 8 数据处理的两个基本问题

三.实验内容

实验任务1:

将以下代码写入文本编辑器:

assume cs:code, ds:data
data segment
        db 'Nuist'
        db 5 dup(2)
data ends

code segment
start:
        mov ax, data
        mov ds, ax

        mov ax, 0b800H
        mov es, ax

        mov cx, 5
        mov si, 0
        mov di, 0f00h
s:      mov al, [si]
        and al, 0dfh
        mov es:[di], al
        mov al, [5+si]
        mov es:[di+1], al
        inc si
        add di, 2
        loop s

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

 阅读源程序,从理论上分析源代码的功能,尤其是line15-25,循环实现的功能是什么,逐行理解每条指 令的功能。

   解:首先分析程序,第一步先初始化di,si,然后设置cx值为5,进行5次循环,然后将五个字母转化成大写后写入显存,然后利用高位字符控制在显存输出字符的颜色,然后再在显存输出低位字符NUIST,这里的and做的是转化字符为大写,数字段中的5个2则是将字符颜色变为绿色。

    然后进行编译,链接,执行得到结果如下:

    

 运行:

   

   然后修改 dp 5 dup(2)为dp 2,3,4,5,6,结果如下:

   

   从此实验中可以看出,高位字符代表显存低位输出字符的颜色。

实验任务2:

   已知数据段data中定义字节数据如下:

data segments
    db 23, 50, 66, 71, 35
data ends

   编写程序,在屏幕上以十进制整数形式打印输出这5个两位数。   

编写代码如下: 

assume cs:code, ds:data
data segment
        db 23,50,66,71,35
data ends

code segment
start:
        mov ax, data
        mov ds, ax

        mov di,0
        mov cx,5
  
s:      mov ah,0
        mov al,ds:[di]
        mov bl,10
        div bl
        mov ds:[di+10],al
        mov ds:[di+11],ah
        
        mov ah,2
        mov dl, ds:[di+10]  
        add dl,30h
        int 21h
   
        mov ah,2
        mov dl, ds:[di+11]  
        add dl,30h
        int 21h
  
        mov ah,2
        mov dl, " " 
        int 21h
        inc di
        loop s
       
        mov ah, 4ch
        int 21h
code ends
end start

  经过编译,链接,执行得到如下结果:

       

 实验任务3:

       将下面的程序编译、链接、用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

     经过编译,链接

     

    使用debug查看:

     

 

    

    1.cpu执行程序,程序返回前,data段中的数据为多少?

        数据可以看到为 0123 0456 0789 0ABC 0DEF 0FED 0CBA 0987

    2.CPU执行程序,程序返回前,cs=076C ss=076B ds=076A

    3.已知code地址段段地址为X,那么data段段地址为?stack段段地址为?

     data段段地址为X-2,stack段段地址为X-1

实验任务4:

    将下面的程序编译、链接、用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

     经过编译,链接:

    

 

    

   1.cpu执行程序,程序返回前,data段中的数据为多少?

        数据可以看到为 0123 0456

    2.CPU执行程序,程序返回前,cs=076C ss=076B ds=076A

    3.已知code地址段段地址为X,那么data段段地址为?stack段段地址为?

     data段段地址为X-2,stack段段地址为X-1

    4.对于如下定义的段

name segment
...
name ends

    如果段中的数据占N个字节,那么程序加载后,该段实际占有空间为:

    可以综合实验3和实验4,得到占用空间为 (int(N/16)+1)*16

实验任务5:

   将下面的程序编译、链接、用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

  编译,链接,执行:

       

 

     然后debug:

      

 

      1.cpu执行程序,程序返回前,data段中的数据为多少

        数据可以看到为 0123 0456

      2.CPU执行程序,程序返回前,cs=076A ss=076E ds=076D

      3.已知code地址段段地址为X,那么data段段地址为?stack段段地址为?

        data段段地址为X+3,stack段段地址为X+4

实验任务6:

     将前面那几题中的最后一条伪指令”end start“改为”end“,哪个程序可以正确执行?

     第三个,因为代码段定义在数据段和栈段之前,如果要反汇编数据段和栈段,也可以正确执行代码,不会改变程序开始的位置,所以可以正常的结束程序,另外两个都在代码段之前,所以需要先反汇编,那么就一定会改变代码段起始位置,无法执行。

实验任务7:

      编写code段中的代码,将a段和b段中的数据依次相加,将结果存到c1段中。

      代码如下:

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   ; 在集成软件环境中,请将此处的段名称由c→改为c1或其它名称
  db 8 dup(0)
c1 ends

code segment
start:
       mov bx,0
       mov cx,8
      
s:     mov si,a
       mov ds,si
       mov al,ds:[bx]

       mov si,b
       mov ds,si
       add al,ds:[bx]

       mov si,c1
       mov ds,si
       mov ds:[bx],al

       inc bx
       loop s
       mov ax,4c00h
       int 21h
       
code ends
end start

    编译,链接,debug如下:

    

    

    

   可以看到C段结果如下:

   

 

实验任务8:

    编写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 bx,0
mov cx,8
mov si,a
mov ds,si
s: push ds:[bx]
add bx,2
loop s
mov bx,0
mov si,b
mov cx,8
mov ds,si
c: pop ds:[bx]
add bx,2
loop c
mov ah,4ch
int 21h
code ends
end start

 

     debug:

    

   因为是dw双字节数据,所以每次bx要加2,可以看到1--8共8个数都已经全部逆序输入到b段中。

四.实验总结

   在本次实验中,我了解了内存中段的具体含义,段地址就代表了内存中某段地址用于存储数据,同时需要弄清楚段中数据的具体所占空间大小,同时要注意的是数据段的存储,弄清楚数据存储中的字节大小,至少占用16个字节,同时避免代码执行混乱,一定要加上end start,否则容易混淆,导致代码无法正确执行。此外,还有使用div除法时,需要注意ah存储商,al存储余数,同时在写代码时要注意循环的位置,同时要注意使用bx和数字段b的时候不要混淆,会导致代码异常中断。

    

    

      

 

 

  

 

posted @ 2020-11-25 22:24  月shang  阅读(145)  评论(0编辑  收藏  举报