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

实验三


1. 实验任务1


代码及其分析

assume cs:code, ds:data
data segment        ;数据段
        db 'Nuist'    ;连续的内存单元赋值'Nuist'和22222
        db 5 dup(2)
data ends

code segment        ;代码段
start:        
        mov ax, data
        mov ds, ax        ;将数据段地址赋值给ds

        mov ax, 0b800H
        mov es, ax       ;将额外数据段赋值为0b800H(显存),即实现输出效果

        mov cx, 5        ;循环次数为5
        mov si, 0
        mov di, 0f00h
s:      mov al, [si]        ;将ds:[si]赋值给al
        and al, 0dfh        ;与0bfh做与运算,将字母变为大写
        mov es:[di], al    ;将大写字母赋值到es:[di]额外数据段(低地址字节)
        mov al, [5+si]    ;将ds:[5+si]赋值给al
        mov es:[di+1], al    ;将al赋值到es[di+1](高地址字节)
        inc si            ;si自加
        add di, 2        ;di=di+2
        loop s            ;循环跳转

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

修改代码

db 5 dup(2)
--> 改成:
db 2,3,4,5,6

根据实验二中所得结论,高地址字节控制输出颜色,低地址字节控制输出内容

预计输出结果颜色将发生改变

结论

数据用于控制输出颜色


2. 实验任务2


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
		
s:		mov ah,0
		mov al,[si]
		mov bl,10
		div bl
		add al,30h
		
		mov ah,2
		mov dl,al
		int 21h
		
		mov ah,0
		mov al,[si]
		div bl
		mov dl,ah
		add dl,30h
		
		mov ah,2
		mov dl,dl
		int 21h
		
		inc si
		loop s
		
		mov ah, 4ch
        int 21h
code ends
end start

div

8位运算时:被除数存储在ax中,除数存储在bl中,商在al中, 余数在ah中


3. 实验任务3

编译、连接以下程序

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        ;stack为栈
        mov ss, ax
        mov sp,16
        
        mov ax, data           
        mov ds, ax
        
        push ds:[0]        ;0123H入栈
        push ds:[2]        ;0456H入栈
        pop ds:[2]        ;0456H出栈,并保存到ds:[2]
        pop ds:[0]        ;0123H出栈,并保存到ds:[0]
        
        mov ax,4c00h
        int 21h

code ends
end start

运行前:

运行后:

(1) 程序返回前,data段中的数据为多少?
0123h, 0456h, 0789h, 0abch, 0defh, 0fedh, 0cbah, 0987h不变
(2)返回前,cs=076c,ss=076b,ds=076a

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

4. 实验任务4

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) 程序返回前,data段中的数据为0123 0456

(2)cs=076C ,DS=076A ,SS=076B
(3)程序加载后,code段地址为X,则data段的段地址为X-2,stack段的段地址为X-1
(4)结论:
对于如下定义的段:

name segment
...
name ends

如果段中数据占N个字节,则程序加载后实际占16*ceil(N/16)字节

5. 实验任务5

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) data:0123 0456
(2) cs=076A SS=076E DS=076D

根据反汇编结果可得,代码段结束之后,该16字节剩余内存单元进行了补0处理,数据段从下一段开始

(3) code=X;data=X+2;stack=X+3

6. 实验任务6

  • 实验任务5的代码可以执行
  • 因为任务34代码中,程序的正确的入口应该在start位置处,若去掉start标记,程序将会把data段和stack段当做代码执行,显然这会出现错误
  • 而任务5的程序入口start标记之前并没有数据段和栈段,因此不会出现上述问题

7. 实验任务7

(1) 以字节为单位:

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   ; 在集成软件环境中,请将此处的段名称由c→改为c1或其它名称
  db 8 dup(0)
c ends

code segment
start:
		mov ax,a
		mov es,ax
	
		mov ax,c
		mov ds,ax
		mov bx,0
	
		mov cx,8               ;8
s1: 	mov al,es:[bx]        ;al
		add [bx],al
		add bx,1
		loop s1
		
		mov ax,b
		mov es,ax
		
		mov cx,8
		mov bx,0
s2:		mov al,es:[bx]
		add [bx],al
		add bx,1
		loop s2
		
		mov ax,4c00h
        int 21h
code ends
end start

反汇编:

第一次循环结束:

运行结果:

(2) 以字为单位

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   ; 在集成软件环境中,请将此处的段名称由c→改为c1或其它名称
  db 8 dup(0)
c ends

code segment
start:
		mov ax,a
		mov es,ax
	
		mov ax,c
		mov ds,ax
		mov bx,0
	
		mov cx,4
s1: 	mov ax,es:[bx]
		add [bx],ax
		add bx,2
		loop s1
		
		mov ax,b
		mov es,ax
		
		mov cx,4
		mov bx,0
s2:		mov ax,es:[bx]
		add [bx],ax
		add bx,2
		loop s2
		
		mov ax,4c00h
        int 21h
code ends
end start


  • 对照:虽然两种方法都可以实现相加,但当出现进位时,以字为单位可能会影响到相邻内存单元

(3) 地址连续为线索相加

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   ; 在集成软件环境中,请将此处的段名称由c→改为c1或其它名称
  db 8 dup(0)
c ends

code segment
start:
		mov ax,a
		mov es,ax
		
		mov ax,c
		mov ds,ax
		mov bx,0
		mov cx,8
		
s:		mov ax,es:[bx]
		add ax,es:[bx+10h]
		mov [bx],ax
		inc bx
		loop s

		mov ax,4c00h
        int 21h
code ends
end start

可知a=b-1
因此可以使用es:[bx]es:[bx+10h]来表示a b段内的数据

结果:

8. 实验任务8

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            ;将b段设为栈段
	mov ss,ax
	mov sp,16
	
	mov ax,a            ;a段为数据段
	mov ds,ax
	mov bx,0
	mov cx,8
s:	push [bx]            ;向b中压入数据
	add bx,2
	loop s
	
	mov ax,4c00h
    int 21h
code ends
end start

反汇编

运行结果

总结

实验中涉及到的知识点有:

  1. 输出时颜色与字符的控制
  2. 如何输出数字及div指令的使用
  3. 多个段的程序的地址分配方式
    • 依次顺序分配
    • 每个段分配的空间为16的倍数,不满16照样分配16字节
    • end start程序的入口
  4. 栈的push/pop操作
posted @ 2020-11-26 21:15  PestLa  阅读(146)  评论(3)    收藏  举报