汇编课程实验二 多个逻辑段的汇编源程序编写与调试

2021/11/6 14:10:28

本文主要是介绍汇编课程实验二 多个逻辑段的汇编源程序编写与调试,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

一、实验目的

  1. 理解和掌握8086多个逻辑段的汇编源程序
  2. 理解和熟练应用灵活的寻址方式
  3. 通过汇编指令loop的使用理解编程语言中循环的本质,掌握其在嵌套循环中的正确使用
  4. 掌握使用debug调试8086汇编程序的方法

二、实验准备

复习王爽《汇编语言》5-8章:

  • 包含多个逻辑段的汇编源程序结构
  • 寻址方式
  • 汇编指令loop, div用法

三、实验内容

实验任务1

此实验任务中,包含4个子任务。逐一实践,结合实践观察、验证,回答问题。

  • 1.1
    对程序task1_1.asm进行汇编、连接,用debug加载、跟踪调试,基于结果,回答问题。
assume ds:data, cs:code, ss:stack
data segment
db 16 dup(0) ; 预留16个字节单元,初始值均为0
data ends
stack segment
db 16 dup(0) ;预留16个字节单元,初始值均为0
stack ends
code segment
start:
mov ax, data
mov ds, ax
mov ax, stack
mov ss, ax
mov sp, 16 ; 设置栈顶
mov ah, 4ch
int 21h
code ends
end start

① 在debug中将执行到line17结束、line19之前,记录此时:寄存器(DS) =076a, 寄存器(SS) =076B, 寄存器(CS) =076C
② 假设程序加载后,code段的段地址是X,则,data段的段地址是 X-2, stack的段地址是 X-1

内存按照代码中数据、代码段书写顺序自上而下分配,故先分配data段再分配stack段最后分配code段,一个段地址长度为16字节,故两个数据段各分配1个段地址长度,为X-2和X-1。以下子任务类似。

  • 1.2
    对程序task1_2.asm进行汇编、连接,用debug加载、跟踪调试,基于结果,回答问题。
assume ds:data, cs:code, ss:stack
data segment
db 4 dup(0) ; 预留4个字节单元,初始值均为0
data ends
stack segment
db 8 dup(0) ; 预留8个字节单元,初始值均为0
stack ends
code segment
start:
mov ax, data
mov ds, ax
mov ax, stack
mov ss, ax
mov sp, 8 ; 设置栈顶
mov ah, 4ch
int 21h
code ends
end start

① 在debug中将执行到line17结束、line19之前,记录此时:寄存器(DS) =076a, 寄存器(SS) =076B, 寄存器(CS) =076C
② 假设程序加载后,code段的段地址是X,则,data段的段地址是 X-2, stack的段地址是 X-1

数据段不足16字节也分配满16字节。8086内存分配一般以16字节为单位。

  • 1.3
    对程序task1_3.asm进行汇编、连接,用debug加载、跟踪调试,基于结果,回答问题
assume ds:data, cs:code, ss:stack
data segment
db 20 dup(0) ; 预留20个字节单元,初始值均为0
data ends
stack segment
db 20 dup(0) ; 预留20个字节单元,初始值均为0
stack ends
code segment
start:
mov ax, data
mov ds, ax
mov ax, stack
mov ss, ax
mov sp, 20 ; 设置初始栈顶
mov ah, 4ch
int 21h
code ends
end start

① 在debug中将执行到line17结束、line19之前,记录此时:寄存器(DS) =076a, 寄存器(SS) =076C, 寄存器(CS) =076E
② 假设程序加载后,code段的段地址是X,则,data段的段地址是 X-4, stack的段地址是 X-2

  • 1.4
    对程序task1_4.asm进行汇编、连接,用debug加载、跟踪调试,基于结果,回答问题。
assume ds:data, cs:code, ss:stack
code segment
start:
mov ax, data
mov ds, ax
mov ax, stack
mov ss, ax
mov sp, 20
mov ah, 4ch
int 21h
code ends
data segment
db 20 dup(0)
data ends
stack segment
db 20 dup(0)
stack ends
end start

① 在debug中将执行到line17结束、line19之前,记录此时:寄存器(DS) =076C, 寄存器(SS) =076E, 寄存器(CS) =076A
② 假设程序加载后,code段的段地址是X,则,data段的段地址是 X+2, stack的段地址是 X+4

该任务code段位于开头故data段和stack段地址在后。

  • 1.5
    基于上述四个实验任务的实践、观察,总结并回答:

① 对于如下定义的段,程序加载后,实际分配给该段的内存空间大小是[N/16]*16 (中括号是向上取整)

xxx segment
db N dup(0)
xxx ends

② 如果将程序task1_1.asm, task1_2.asm, task1_3.asm, task1_4.asm中,伪指令 end start 改成end , 哪一个程序仍然可以正确执行?结合实践观察得到的结论,分析、说明原因。

第四个任务依旧能够成功运行。其他三个任务再更改末尾的end start后,start伪指令失效,程序从段前缀起始依次向后执行,根据分配次序前三个任务有数据段打头,程序无法识别代码类别产生错误,第四个任务代码段最先分配规避了冲突的产生。

实验任务二

编写一个汇编源程序,实现向内存单元b800:0f00 ~ b800:0f9f连续160字节,依次重复填充十六进制数据03 04。

Tips:

  1. 在实验1的实验任务3中,做过达到同样效果的实验。但当时是通过debug的f命令实现填充的。这一次,要求编程实现。
在debug中,使用f命令,向内存单元批量填写数据。
-f b800:0f00 0f9f 03 04
把内存单元区间b800:0f00 ~ b800:0f9f连续160个字节,依次重复填充十六进制数据03 04。
  1. 编程实现时,注意进制问题、字节顺序问题。编写后,运行程序,如果与实验1的实验任务3结果不一致,说明程序编写有错误。

程序代码:

assume cs:code
code segment
start:     
    mov ax,0b800h
    mov ds,ax
    mov bx,0f00h
    mov cx,80
p:
    mov ds:[bx],0403h
    add bx,2
    loop p

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

结果如图

实验任务三

已知8086汇编源程序task3.asm代码片段如下

assume cs:code
data1 segment
db 50, 48, 50, 50, 0, 48, 49, 0, 48, 49 ; ten numbers
data1 ends
data2 segment
db 0, 0, 0, 0, 47, 0, 0, 47, 0, 0 ; ten numbers
data2 ends
data3 segment
db 16 dup(0)
data3 ends
code segment
start:
; ×××
mov ah, 4ch
int 21h
code ends
end start

要求:
① 编程实现把逻辑段data1和逻辑段data2的数据依次相加,结果保存到逻辑段data3中。
② 在debug中加载、反汇编、调试。在数据项依次相加前,和相加后,分别查看三个逻辑段data1,data2, data3对应的内存空间,确认逐一相加后,结果的确保存在了逻辑段data3中。

补全后的代码

assume cs:code
data1 segment
    db 50, 48, 50, 50, 0, 48, 49, 0, 48, 49 ; ten numbers
data1 ends

data2 segment
    db 0, 0, 0, 0, 47, 0, 0, 47, 0, 0       ; ten numbers
data2 ends

data3 segment
    db 16 dup(0)
data3 ends

code segment
start:
    mov ax,data1
    mov ds,ax
    mov cx,16
    mov bx,0
s:  
    mov al,ds:[bx]
    add al,ds:[bx+16]
    mov ds:[bx+32],al
    inc bx
    loop s

    mov ah, 4ch
    int 21h

code ends
end start

data1和data2各存有10个10进制数,为其分配16字节空间,所以data1数据段对应data2数据段的位置为data1+16,对应data3的位置为data1+32。据此写出此三步代码
mov al,ds:[bx]
add al,ds:[bx+16]
mov ds:[bx+32],al
完成对应位置数相加后的保存。

实验结果:

实验任务四

已知8086汇编源程序task4.asm代码片段如下

assume cs:code
data1 segment
dw 2, 0, 4, 9, 2, 0, 1, 9
data1 ends
data2 segment
dw 8 dup(?)
data2 ends
code segment
start:
; ×××
mov ah, 4ch
int 21h
code ends
end start

要求:
① 补全程序,实现把逻辑段data1中的8个字数据逆序存储到逻辑段b中。
② 汇编、连接后,在debug中加载程序,运行到line15程序退出前,使用d命令查看数据段data2对应的内存空间,确认是否实现题目要求。

补全后代码:

assume cs:code
data1 segment
dw 2, 0, 4, 9, 2, 0, 1, 9
data1 ends
data2 segment
dw 8 dup(?)
data2 ends
code segment
start:
  ` mov ax,data1
    mov ds,ax
    mov ax,stack
    mov ss,ax
    mov sp,16
    mov bx,0
    mov cx,8
s1:
    push ds:[bx]
    add bx,2
    loop s1

    mov bx,16
    mov cx,8
s2:
    pop ds:[bx]
    add bx,2
    loop s2

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

利用栈依次压入8个数再依次弹出到data2对应位置,注意弹出时bx值的设置。

实验结果:

实验任务五

使用任意文本编辑器,录入汇编源程序task5.asm

assume cs:code, ds:data
data segment
db 'Nuist'
db 2, 3, 4, 5, 6
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,循环实现的功能是什么,逐行理解每条指令的功能。

  • 对程序进行汇编、链接,得到可执行文件,运行并观察结果。
  • 使用debug工具对程序进行调试,执行到程序返回前,即line25执行之后、line27执行之前,观察结果。
  • 源代码中line19的作用是?
  • 修改line4里5个字节单元的值,重新汇编、链接、运行,观察结果。
db 2,3,4,5,6
--> 改成:
db 5 dup(2) 或 db 5 dup(5)

基于观察,分析、猜测这里的数值作用是什么。

1.运行结果

2.运行结果

3.line19的作用是将小写字母转换为大写字母,实现方式基于英文大小写字母ASCII码的特性,小写字母比对应大写字母高32,可以利用二进制数相与改变对应位的数值,相与的二进制数在想要赋0的位置填充0,其余位填充1,可以达到一种“二进制掩码”的效果。

4.运行结果

5个数值依次对应5个字母的字体颜色。

实验任务六

已知8086汇编源程序task6.asm代码片段如下

assume cs:code, ds:data
data segment
db 'Pink Floyd ' ; 16字节
db 'JOAN Baez ' ; 16字节
db 'NEIL Young ' ; 16字节
db 'Joan Lennon ' ; 16字节
data ends
code segment
start:
; ×××
mov ah, 4ch
int 21h
code ends
end start

要求:
① 补全程序,将data段中的每行第一个单词从大写->小写。
② 在debug中加载程序,反汇编,执行到line13退出前,用d命令查看data段对应的内存空间,确认每行第一个单词已经由大写->小写。

补全后的程序:

assume cs:code, ds:data

data segment
db 'Pink Floyd      '
db 'JOAN Baez       '
db 'NEIL Young      '
db 'Joan Lennon     '
data ends

code segment
start:
mov ax,data
mov ds,ax
mov cx,4
mov bx,0
s:  
mov dx,cx
mov cx,4
mov si,0
    p:
        mov al,ds:[bx+si]
        or al,00100000B
        mov ds:[bx+si],al
        inc si
    loop p
add bx,16
mov cx,dx
loop s

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

实验结果:

外层循环遍历4行单词,内存循环遍历首单词的每个字母,利用dx暂存cx值。通过or指令将单词数据与00100000B相或得到ASCII更大的小写字母。

实验任务七

问题场景描述:
Power idea公司1975年-1979年的基本情况如下:

程序task7.asm的逻辑段data中(line4-6),已经定义好了这些数据。

assume cs:code, ds:data, es:table
data segment
db '1975', '1976', '1977', '1978', '1979'
dw 16, 22, 382, 1356, 2390
dw 3, 7, 9, 13, 28
data ends
table segment
db 5 dup( 16 dup(' ') ) ;
table ends
code segment
start:
mov ah, 4ch
int 21h
code ends
end start

要求:
① 补全程序,实现题目要求,把年份、收入、雇员人数、人均收入,以结构化方式写入table段中。
表格中,每行数据,在逻辑段table中占16个字节,各项数据占据字节大小分配如下。期中,数据之间用空格间隔。

② 汇编、连接后,在debug中加载、调试程序。灵活、合理使用u命令、g命令、d命令,显示刚开始逻辑段table的数据信息,以及,结构化存入数据后,数据段table的数据信息,确认实现题目要求。

补全后的程序:

assume cs:code, ds:data, es:table

data segment
    db '1975', '1976', '1977', '1978', '1979' 
    dw  16, 22, 382, 1356, 2390
    dw  3, 7, 9, 13, 28 
data ends

table segment
    db 5 dup( 16 dup(' ') )  ;
table ends

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

    mov si,0
    mov di,0
    mov bx,0
    mov cx,5

    mov sp,0

 s: mov ax,[si]
    mov es:[di],ax
    mov ax,[si+2]
    mov es:[di+2],ax

    mov ax,[bx+20]
    mov es:[di+5],ax
    mov dx,0
    mov es:[di+7],dx

    push cx
    mov cx,[20+10+bx]
    mov es:[di+10],cx

    div cx
    pop cx

    mov es:[di+0dh],ax

    add si,4
    add di,16
    add bx,2

    loop s

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

实验结果:



这篇关于汇编课程实验二 多个逻辑段的汇编源程序编写与调试的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程