Live2d Test Env

汇编语言实验三

汇编语言实验三

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] #把data字段中的第si个字节送入al之中;
    and al, 0dfh   #and操作获取大写字母ASCII码
    mov es:[di], al #送入显存的缓冲区
    mov al, [5+si]#把data字段中第si+5个字节送入al,这是用来控制颜色的字节
    mov es:[di+1], al#将其送入显存
    inc si #选取下一个控制的字符
    add di, 2 #控制选择下一个显存缓冲区
    loop s
    mov ah, 4ch
    int 21h
code ends
end start

第二次实验中我们知道控制显存的输出需要两个字节的数据,高位字节控制的是颜色,低位字节控制的是内容,因此可以很好的理解本题的意思,采用ds,es两个段寄存器分别来表示字符和颜色值的段地址,and 11011111操作是将字母转换成大写的操作,因为对于一个字符的输出需要更改高位的颜色以及低位的数字,因此又借助了两个寄存器si和di来分别进行选择颜色的db 5中的数据并且赋值给相应的显存区域;

汇编、链接后运行结果如下:
h1

使用g命令跳转到循环结束:

h2

发现已经将nuist的5个字符全部变成大写的形式;

将db 5 dup(2)修改为db 2,3,4,5,6;

汇编链接得到结果:

h3

由上述分析可以很容易的知道这是因为改变了存储代表颜色的数据所导致的;

实验任务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 si,0
	mov cx,5
	
s1: mov ah,0
    mov al,[si]
	mov bl,0ah
	div bl
	mov [si+5h],al#商放在al,余数放在ah
	mov [si+6h],ah
	
	mov ah,2
	mov dl,[si+5h]
	add dl,30h
	int 21h
	
	mov ah,2
	mov dl,[si+6h]
	add dl,30h
	int 21h
	
	mov ah,2
	mov dl," "
	int 21h
	
	inc si
	loop s1
	
	mov ax,4c00h
	int 21h
	
code ends
end start
	

结果:

h4

实验任务3

教材「实验5 编写、调试具有多个段的程序」(1) 程序源码见task3.asm。

task.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


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

    使用g命令跳转到程序退出之前,使用d命令查看data段中的数据:
    h5

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

执行带程序返回之前各个寄存器的数据见上图;

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

实验任务4

教材[实验5 编写、调试具有多个段的程序](2)

源代码:

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段中的数据为多少?

先使用g命令跳转到程序返回前,然后适用d命令查看data段的数据:

h6

CPU

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

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

(此处有一个小知识点:数据段和栈段在程序加载之后实际占据的空间都是以16个字节为单位的,不足的补0?(不确定));

4.对于如下定义的段:

name segment
.
.
.
name  ends

如果段中的数据占N个字节,则程序加载后,改段实际占有的空间为[(N+15)/16]*16;(计算机中字节必须以16位作为储存空间的单位)

实验任务5

教材[实验5 编写、调试具有多个段的程序] (3)

源代码:

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

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

经过g命令跳转到程序返回之前,然后适用d命令来查看data段中的数据:

h7

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

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

从cx作为程序计数器我们可以看到程序大小为44,因此段地址应该处于3-4之间,因此data段的地质为X+3,stack段地址应该为X+4;

实验任务6

教材[实验5 编写、调试具有多个段的程序] (4)

如果将(1)、(2)、(3)题中最后一条伪指令"end start"改为"end"(也就是说不指名程序的入口),则那个程序仍然可以正确执行?请说明原因。

(3)可以正确执行,因为(1)、(2)的数据段都放在了代码段的前面,不指定程序入口,这些数据段会被当成指令进行编译,(3)的数据段位于代码段的后面,所以不会存在这样的错误。

实验任务7

教材[实验5 编写、调试具有多个段的程序] (5)

源代码如下:

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 0,0,0,0,0,0,0,0
c ends
code segment
start:mov ax,a
mov ds,ax
mov ax,b
mov es,ax
mov ax,c
mov ss,ax
mov bx,0
mov cx,8
s:mov al,[bx]
add al,es:[bx]
mov ss:[bx],al
inc bx
loop s
mov ax,4c00h
int 21h
code ends
end start

编译连接之后使用g命令跳转到程序执行结束之前,使用d命令查看内存:
h8

可以看出顺利的完成了加法的操作。

实验任务8

教材[实验5 编写、调试具有多个段的程序] (6)

源代码如下:

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 0,0,0,0,0,0,0,0
b ends

code segment
start: 
    mov ax,a
    mov ds,ax
    mov ax,b
    mov bx,0
    mov ss,ax
    mov sp,16
    mov cx,8
s:     push [bx]
    add bx,2
    loop s
    mov ax,4c00h
    int 21h
code ends
end start

编译连接之后使用g命令跳转到程序执行结束之前,使用d命令查看b逻辑段的内存:

h9

发现成功将a段中的前8个字型数据,逆序存储到b段中去,满足题目的要求。

实验结论

  1. 对常用的汇编debug指令有了更清楚的认识。
  2. 对于字符、数字在编程语言中的存储于表示有了更深层次的理解。
  3. 包含多个段的程序数据段、栈段、代码段的放置顺序及其影响。
  4. 能够综合利用栈以及常用的寄存器完成简单的综合任务。
posted @ 2020-11-22 16:44  lszz  阅读(426)  评论(4编辑  收藏  举报