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

汇编实验2

1.实验任务1

  • 任务1-1
    对程序task1_1.asm进行汇编、连接,用debug加载、跟踪调试,基于结果,回答问题。
    task1_1.asm
assume ds:data, cs:code, ss:stack

data segment
    db 16 dup(0)
data ends

stack segment
    db 16 dup(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之前,
//使用-u进行反汇编,第19行为 mov ah, 4ch,对应地址为000D,利用指令-g 000D断点调试,得到如下内容:

此时:寄存器(DS)= 076A,寄存器(SS)= 076B,寄存器(CS)= 076C

② 假设程序加载后,code段的段地址是X,则,data段的段地址是(x-2), stack的段地址是 (x-1)。
//...

  • 任务1-2
    对程序task1_2.asm进行汇编、连接,用debug加载、跟踪调试,基于结果,回答问题。
//task1_2.asm
assume ds:data, cs:code, ss:stack
data segment
    db 4 dup(0)
data ends

stack segment
    db 8 dup(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)。

  • 任务1-3
    对程序task1_3.asm进行汇编、连接,用debug加载、跟踪调试,基于结果,回答问题。
//task1_3.asm
assume ds:data, cs:code, ss:stack
data segment
db 20 dup(0)
data ends
stack segment
db 20 dup(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加载、跟踪调试,基于结果,回答问题。
//task1_4.asm
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中将执行到line9结束、line11之前,

此时:寄存器(DS)= 076C,寄存器(SS)= 076E,寄存器(CS)= 076A
② 假设程序加载后,code段的段地址是X,则,data段的段地址是(x+2), stack的段地址是 (x+4)。

  • 任务1-5
    基于上述四个实验任务的实践、观察,总结并回答:
    ① 对于如下定义的段,程序加载后,实际分配给该段的内存空间大小是16*[N/16]
1 xxx segment
2       db N dup(0)
3 xxx ends

② 如果将程序task1_1.asm, task1_2.asm, task1_3.asm, task1_4.asm中,伪指令 end start 改成end , 哪一个程序仍然可以正确执行?结合实践观察得到的结论,分析、说明原因。
*task1_4.asm可以正确执行."end start" 指明程序入口,改为end无法找到可执行位置,task1_4.asm以程序段开始,而task1_1、2、3都以数据段开始,无法运行。

2.实验任务2

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

code segment
start:
mov ax,0b800h
mov ds,ax
mov bx,0f00h
mov cx,80

s: mov [bx],0403h
add bx,2
loop s

mov ah, 4ch
int 21h

code ends
end start
、、、

Tips:

  1. 在实验1的实验任务3中,做过达到同样效果的实验。但当时是通过debug的f命令实现填充的。这一
    次,要求编程实现。

在debug中,使用f命令,向内存单元批量填写数据。
-f b800:0f00 0f9f 03 04
把内存单元区间b800:0f00 ~ b800:0f9f连续160个字节,依次重复填充十六进制数据03 04。

  1. 编程实现时,注意进制问题、字节顺序问题。编写后,运行程序,如果与实验1的实验任务3结果不一
    致,说明程序编写有错误。

3.实验任务3

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

//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:
   ; ×××
code ends
end start

① 编程实现把逻辑段data1和逻辑段data2的数据依次相加,结果保存到逻辑段data3中(xxx)。

    mov ax,data1
    mov ds,ax

    mov bx,0
    mov cx,5
s:  mov ax,[bx]
     add ax,[bx+16]
    mov [bx+32],ax
    add bx,2
    loop s

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

相加前

相加后

4.实验任务4

补全task4.asm代码如下:
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 ax,data1
    mov ds,ax
    mov ax,data2
    mov ss,ax
    mov sp,16

    mov bx,0
    mov cx,8

s: push [bx]
    add bx,2
    loop s


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

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

在程序退出前,使用d命令查看数据段data2对应的内存空间的截图

5.实验任务5

使用任意文本编辑器,录入汇编源程序task5.asm。
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的作用是?
    与0dfh做与运算会将原数值的第三位置0,即减去32,实现小写字母转换成大写字母。
  • 修改line4里5个字节单元的值,重新汇编、链接、运行,观察结果。
db 2,3,4,5,6 --> 改成: db 5 dup(2) 或 db 5 dup(5)

db 5 dup(2) :

db 5 dup(5):

这里的数值应该用于文本颜色的修改。

6.实验任务6

补全task6.asm代码如下:
task6.asm

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 bx,0  ;偏移量
    mov cx,4  ;循环次数为4

s1: mov dx,cx ;存储外循环次数
    mov cx,4  ;设置内循环次数
    mov si,0  ;设置偏移亮
    s2: mov ax,[bx+si]
        or  ax,00100000B  ;大写字母的ASCII码减去32,小写字母不变
        mov [bx+si],ax    ;写回原来的空间
        inc si            ;自加
        loop s2
    add bx,16             ;处理下一个db
    mov cx,dx             ;恢复外循环次数记录
    loop s1

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

① 补全程序,将data段中的每行第一个单词从大写->小写。
② 在debug中加载程序,反汇编


执行到line13退出前,用d命令查看data段对应的内存空间,确认每行第一个单词已经由大写->小写。

7.实验任务7

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

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

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个字节,各项数据占据字节大小分配如下。期中,数据之间用空格间隔。

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   ;将数据段地址交给ds
    mov ax,table
    mov es,ax   ;将表格地址交给es

    mov bx,0    ;设置关于data数据区的偏移位置
    mov di,0    ;设置输入位置为table第一行的第一个
    mov cx,5    ;设置循环次数

s1: mov ax,[bx]
    mov es:[di],ax ;写入table的相应位置
    mov ax,[bx+2]
    mov es:[di+2],ax
    add bx,4    ;指向下一个年份
    add di,16   ;进入table的下一行
    loop s1

    mov di,5    ;指向table第一行的第五个位置
    mov cx,5    ;设置循环次数

s2: mov ax,[bx]
    mov es:[bx],ax
    add bx,2
    add di,16
    loop s2

    mov di,10
    mov cx,5

s3: mov ax,[bx]
    mov es:[bx],ax
    add bx,2
    add di,16
    loop s3

    mov di,5
    mov cx,5

s4: mov ax,es:[di]  ;被除数"收入"放在ax中
    mov bp,es:[di+5] ;除数"雇员数"放在bp中
    div bp
    mov es:[di+8],ax
    add di,16
    loop s4

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

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

在debug中运行到程序退出之前,使用d命令查看table段对应的内存空间的截图,确认信息是否按要求结构化地写入到指定内存

实验总结

to be continued......

posted @ 2021-11-12 08:40  少吃零食多喝水  阅读(33)  评论(4)    收藏  举报