ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

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

2020-11-22 12:32:47  阅读:174  来源: 互联网

标签:汇编 ends code mov 源程序 ax data ds 调试


一、实验目的

1. 理解和掌握将数据、代码、栈放入不同逻辑段的程序的编写和调试 2. 理解具有多个段的汇编源程序对应的目标程序执行时,内存分配方式 3. 掌握大小写字符的转换方法、数字字符和数值之间的转换方法 4. 理解并掌握各种寻址方式的灵活应用 5. 掌握汇编指令loop, and, or,div, mul的用法

二、实验准备

复习教材chapter 6-8章。 chapter 6 包含多个段的程序 chapter 7 更灵活的定位内存地址的方法 chapter 8 数据处理的两个基本问题

三、实验内容

1. 实验任务1

录入汇编源程序task1.asm:

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
理论分析:
        mov cx, 5             //设置循环次数为5次(Nuist有5个字节)
        mov si, 0             //设置偏移量,这是设置数据段ds的偏移地址
        mov di, 0f00h         //设置es的偏移地址
s:      mov al, [si]          //将ds:[si]一个字节的内容存入al
        and al, 0dfh          //将字母大写
        mov es:[di], al       //将al里的数据存入附加段里面去,这里存入的是数据信息
        mov al, [5+si]        //将ds:[5+si]存入al
        mov es:[di+1], al     //再次存入到附加段里面去,这次是存在高位上面,是颜色信息
        inc si                //si自加
        add di, 2             //附加段的偏移地址加2,移动一个字的单位
        loop s                //循环

这段代码的目的是将 “Nuist”字母变成大写,再将颜色都设置成绿色。

编译,链接,执行得到结果

首先精准反汇编(根据代码可知前面16个字节是存放数据的,所以用CX-10-1得到2a,然后使用-u 0 2a进行反汇编) 使用debug工具调试到程序返回前,即-g 0027 : 修改line4里5个字节单元的值,重新汇编、链接、运行,观察结果
db 5 dup(2) --> 改成: db 2,3,4,5,6

 

 这里的数值代表的是颜色信息,因为是把这些数字都送到了字母的高位字节里去了。

我分别查看了ds和es里面的内容发现不一样,对此很有疑惑:

2. 实验任务2 

已知数据段data中定义字节数据如下:
data segments 
         db 23, 50, 66, 71, 35 
data ends
编写程序,在屏幕上以十进制整数形式打印输出这5个两位数。 编写task2.asm,代码如下:
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 cx, 5
        mov si, 0
s:      mov ah, 0        //因为这个数太小,所以并且是一个字节存储,所以高位先赋0
        mov al, [si]
        mov bl,10
        div bl
        mov ds:[8],al   //存放商,即十位上的数
        mov ds:[9],ah   //存放余数,即个位上的数
        mov ah,2        
        mov dl,ds:[8]
        add dl,30h
        int 21h
        mov ah,2
        mov dl,ds:[9]
        add dl,30h
        int 21h         //用,间隔
        mov ah,2
        mov dl,","
        int 21h
        inc si
        loop s
        mov ah, 4ch
        int 21h
code ends
end start

运行结果:

查看ds存放,前面是5个是存放的数据,ds[8],ds[9]存放的是最后一次的商和余数3,5

3. 实验任务3 

教材「实验5 编写、调试具有多个段的程序」(1)  程序源码见task3.asm:
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

反汇编,同时查询ds里存放的数据:0123h, 0456h, 0789h, 0abch, 0defh, 0fedh, 0cbah, 0987h

-g 1d   执行程序,得到 cs=076ch,ss=076bh,ds=076ah

查看ds里的数据没有发生变化,仍然是:0123h, 0456h, 0789h, 0abch, 0defh, 0fedh, 0cbah, 0987h

 

因此:

1.CPU执行程序,程序返回前,data段中的数据:0123h, 0456h, 0789h, 0abch, 0defh, 0fedh, 0cbah, 0987h

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

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

4. 实验任务4 

教材「实验5 编写、调试具有多个段的程序」(2) 程序源码见task4.asm。
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

汇编、链接后进入debug,进行反汇编(记得老师说过一个段最小是16字节,所以数据段加上栈段虽然都不满16字节,但是都按照16字节算,总共32字节)

查看data中的数据:0123h, 0456h, 0, 0, 0, 0, 0, 0

-g 1d   执行程序,得到 cs=076ch,ss=076bh,ds=076ah

查看ds里的数据没有发生变化,仍然是:0123h, 0456h, 0, 0, 0, 0, 0, 0

 

因此:

1.CPU执行程序,程序返回前,data段中的数据:0123h, 0456h, 0, 0, 0, 0, 0, 0

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

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

4.对如下定义的段:

name segment
···
name ends

如果段中的数据占 N 个字节,不是16字节的整数倍,则会补整,则程序加载后,该段实际占用的空间为:[(N+15)/16]*16([ ]为取整符号)

5. 实验任务5

教材「实验5 编写、调试具有多个段的程序」(3) 程序源码见task5.asm。 
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

反汇编,然后运行到将数据段地址赋给ds,然后查看数据段中的数据:0123h, 0456h, 0, 0, 0, 0, 0, 0

-g 1d   执行程序,得到 cs=076ah,ss=076Eh,ds=076dh

查看ds里的数据没有发生变化,仍然是:0123h, 0456h, 0, 0, 0, 0, 0, 0

 

因此:

1.CPU执行程序,程序返回前,data段中的数据:0123h, 0456h, 0, 0, 0, 0, 0, 0

2.CPU执行程序,程序返回前,cs=076ah,ss=076Eh,ds=076dh

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

6. 实验任务6

        只有教材中实验5的3 的程序能够正常运行。因为如果将 end start 改为 end,那么不指明入口,会默认从 076A:0 开始执行,而前面2个程序076A:0 都是存储的是数据段,所以不行,而第3个是将数据段和栈段放在代码段后面的,默认进入的就是代码段,所以可以正确执行。

7. 实验任务7

程序源码见task7.asm:
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

c segment 
  db 8 dup(0)
c ends

code segment
start:
        mov ax,a
        mov ds,ax
        mov si,0
        mov cx,9
s:      mov ax,0
        mov al,[si]
        add al,[si+16]
        mov [si+32],al
        inc si
        loop s
        mov ah,4ch
        int 21h
       
code ends
end start

因为a,b,c段的长度都是16,所以就直接通过加偏移量16 32来进行访问

使用-g 19执行,查看a,b,c的数据,看到最后一行的数据是由前面两行相加得到的,满足要求。

8. 实验任务8

程序源码见task8.asm:

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,10h
        mov ax,a
        mov ds,ax
        mov si,0
        mov cx,9
s:      push ds:[si]
        add si,2
        loop s
        mov ah,4ch
        int 21h
code ends
end start

反汇编后得知程序在 001ah处返回,使用 -g 001a命令

 

 因为题目要求是逆序存储,所以首先想到就是将b段当成栈段,然后将a里的数据不断地压入栈,实现逆序存储,从上图中查看的结果看出结果满足实验要求,实现了逆序存储。

四、实验总结

1.各逻辑段在内存空间中依序排列,并以 16 个字为一个单元进行分配;若 code 段前有自己设置的逻辑段,需要指明程序的入口,要加上end start。

2.在实验1中的查看大写的nuist存放的地方查看出来和自己预想的不一样,有些困惑。

 

 

 

 

标签:汇编,ends,code,mov,源程序,ax,data,ds,调试
来源: https://www.cnblogs.com/wwangzz/p/14010848.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有