实验任务一

实验任务1-1

代码:

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) = _076AH___, 寄存器(SS) = _076BH___, 寄存器(CS) = _076CH___

 ② 假设程序加载后,code段的段地址是X,则,data段的段地址是_X-2H___, stack的段地址是_X-1H___。

 

实验任务1-2

代码:

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-2H___, stack的段地址是_X-1H___。

 

实验任务1-3

代码:

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) =_076AH___, 寄存器(SS) = _076CH___, 寄存器(CS) = _076EH___

 ② 假设程序加载后,code段的段地址是X,则,data段的段地址是_X-4H___, stack的段地址是__X-2H__。

 

实验任务1-4

代码:

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) = _076CH___, 寄存器(SS) = _076EH___, 寄存器(CS) = _076AH___

 ② 假设程序加载后,code段的段地址是X____,则,data段的段地址是_X+2H___, stack的段地址是 _X+4H___。

 

实验任务1-5

基于上述四个实验任务的实践、观察,总结并回答: ① 对于如下定义的段,程序加载后,实际分配给该段的内存空间大小是 _INT[(N+15)/16]*16___。

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

答:task1_4.asm可以正常执行。因为end start表示程序从start处分配的内存空间开始执行,如果不写start则默认从程序最开始分配的空间开始当做代码段执行,这里只有task1_4.asm的start定义在最开头,所以不受内存空间分配的影响。

 

实验任务二

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

代码:

assume cs:codesg
codesg segment
start:

    mov ax,0b800h
    mov ds,ax
    mov bx,0f00h
    mov cx,50h
            s:
    mov word ptr [bx],0403h
    inc bx
    inc bx
    loop s

codesg 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 cx,10
    mov bx,0000h
    s:
    mov ax,data1
    mov ds,ax
    mov ax,data2
    mov es,ax
    mov al,ds:[bx]
    add es:[bx],al
    inc bx
    loop s

    mov bx,0000h
    mov cx,10

    p:
    mov ax,data3
    mov ds,ax
    mov al,es:[bx]
    mov ds:[bx],al
    inc bx
    loop p
    
    mov ax,4c00h
    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,data2
    mov ss,ax
    mov bx,0000h
    mov sp,16
    mov cx,8
    s:
    mov ax,ds:[bx]
    push ax
    add bx,2
    loop s

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

反汇编,程序执行效果:

 

 

实验任务五

代码:

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,循环实现的功能是什么,逐行理解每条指 令的功能。

答:每次从'Nuist'中取出一个字母,如果是小写就把他通过and运算变为大写,然后将它存入以b800:0f00开头的显存空间内,

再从2,3,4,5,6中取出一个数字,这些数字用来控制显示的字母的颜色,将它存入显存空间内。

之后偏移地址加二,继续每次取出一个字母和一个数字。

 

对程序进行汇编、链接,得到可执行文件,运行并观察结果。

 

使用debug工具对程序进行调试,执行到程序返回前,即line25执行之后、line27执行之前,观察 结果。

 

 源代码中line19的作用是

答:将小写的字母变成大写

修改line4里5个字节单元的值,重新汇编、链接、运行,观察结果。

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

控制字母显示的颜色。

 

实验任务六

要求:

① 补全程序,将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 bx,0000h
    mov cx,4
    s:
    mov al,ds:[bx]
    or al,00100000B
    mov ds:[bx],al
    add bx,16
    loop s

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

DEBUG:

 

 

 

 

实验任务七

 要求:

① 补全程序,实现题目要求,把年份、收入、雇员人数、人均收入,以结构化方式写入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 bx,0
    mov si,0
    mov cx,5

    s0:
    mov ax,ds:[bx]
    mov es:[si],ax    
    mov ax,ds:[bx+2]
    mov es:[si+2],ax  ;拿年份存储
    add bx,4
    add si,16
    loop s0
    
    mov bx,20
    mov cx,5
    mov si,5

    s1:
    mov ax,0
    mov es:[si+2],ax ;用0占位高地址部分
    mov ax,ds:[bx] ;拿收入存储
    mov es:[si],ax
    add bx,2
    add si,16
    loop s1

    mov bx,30
    mov cx,5
    mov si,10

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

    mov cx,5
    mov si,0

    s3:     
    mov ax, es:[si+5]  ;ax存放低16位
    mov dx, es:[si+7]    ;dx存放高16位
    div word ptr es:[si+10]
    mov es:[si+13], ax
    add si,16      ;加16进入下一行
    loop s3

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

反汇编后的代码:

 

 查看前后的table空间

 

 

实验总结:

通过本次实验,了解了如何使用汇编语言来编写简单的程序,以及如何通过debug来反汇编,执行程序并查看相应内存空间的数据,其中最重要的是对内存空间的定位把握。

对于第一题来说需要了解start和end start的作用,以及系统分配内存空间的顺序,系统分配空间是以16个字节为一组进行分配的。

第二题通过编写简单的填充复制来了解段前缀和loop的作用,三四五六题也如出一辙。

第七题是对这次实验内容的综合考察,除了对两个不同的内存空间进行复制以外,还考察了div指令的作用,因为这题题目要求给工资这个字数据四个字节的空间,所以需要用两个0来进行高位的占位,四个字节为32位,则需要用两个寄存器来存储被除数,才能满足除数是分配了一个字空间的要求,然后把商存到相应的空间中。

posted on 2021-11-06 15:06  艾尔克洛  阅读(85)  评论(3)    收藏  举报