实验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
反汇编

运行结果

总结
实验中涉及到的知识点有:
- 输出时颜色与字符的控制
- 如何输出数字及div指令的使用
- 多个段的程序的地址分配方式
- 依次顺序分配
- 每个段分配的空间为16的倍数,不满16照样分配16字节
end start程序的入口
- 栈的push/pop操作

浙公网安备 33010602011771号