实验3 多个段的汇编源程序编写与调试
实验3 多个段的汇编源程序编写与调试
一、实验目的
- 理解和掌握将数据、代码、栈放入不同逻辑段的程序的编写和调试
- 理解具有多个段的汇编源程序对应的目标程序执行时,内存分配方式
- 掌握大小写字符的转换方法、数字字符和数值之间的转换方法
- 理解并掌握各种寻址方式的灵活应用
- 掌握汇编指令loop, and, or,div, mul的用法
二、实验准备
复习教材chapter 6-8章。
三、实验结论
任务1
该段代码实际上实现了对指定显存的控制,将“2N”“2U”等组合存入显存,经过以前的实验我们可以知道,低位控制字符,高位控制显示格式,这里2就是以绿色显示。
具体分析如下:
assume cs:code, ds:data
data segment
db 'Nuist'
db 5 dup(2)
data ends
code segment
start:
mov ax, data
mov ds, ax ;将ds设为data段
mov ax, 0b800H
mov es, ax ;将es段设为0b800h,为显存段
mov cx, 5 ;循环5次
mov si, 0
mov di, 0f00h
s: mov al, [si] ;ds:0(N)存入al,即data段的字节依次存入al
and al, 0dfh ;统统转为大写
mov es:[di], al ;al存入0b800:0f00,实际上是设置显示的字符
mov al, [5+si]
mov es:[di+1], al ;ds:5(2)存入0b800:0f01,实际上是设置显示字符的颜色
inc si ;si+1,指向下一个字符
add di, 2 ;di+2,指向下一个显存字
loop s
mov ah, 4ch
int 21h
code ends
end start
task1.exe执行结果如图,可以看到在左下角显示绿色的NUIST

使用debug工具对程序进行调试,执行到程序返回前,可以看到NUIST出现且随着屏幕滚动上移

修改line4里5个字节单元的值,NUIST分别变成了不同的颜色,印证了开头的分析,数字控制显示模式

任务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,ds:[si]
mov bl,10
div bl
mov bh,ah ;ah后面会用于输出被覆盖,先暂存至bh
add al,30h ;al存放商,为高位,加30h变为对应字符
mov ah,2
mov dl,al ;输出高位
int 21h
;此前ah已经设定好,后面输出就不用重复设置
add bh,30h
mov dl,bh ;输出低位
int 21h
mov dl,32 ;32为空格ASCII码(10进制)
int 21h
inc si
loop s
mov ah, 4ch
int 21h
code ends
end start
运行结果如图:可以看到数字依次输出

任务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
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
- data段中的数据是:23 01 56 04 89 07 bc 0a ef 0d ed 0f ba 0c 87 09,观察到的结果和理论分析一致。
![]()
- cs=0770,ss=076f,ds=076e
![]()
- 程序加载后,code段的段地址为X,则data段的段地址为X-2,stack段的段地址为X-1。
任务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

- data段中的数据是:23 01 56 04 00 00 00 00 00 00 00 00 00 00 00 00,观察到的结果和理论分析一致。
- cs=0770,ss=076f,ds=076e
- 程序加载后,code段的段地址为X,则data段的段地址为X-2,stack段的段地址为X-1。
- 对于任意一个段,其大小为16的倍数,即数据占N个字节,加载后实际空间为16*ceil(N/16)
任务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

- data段中的数据是:23 01 56 04 00 00 00 00 00 00 00 00 00 00 00 00,观察到的结果和理论分析一致。
- cs=076e,ss=0772,ds=0771
- 程序加载后,code段的段地址为X,则data段的段地址为X+3,stack段的段地址为X+4。
这里可以发现一个奇妙的现象,明明代码只是将数据、栈段与代码段交换了顺序,程序大小(CX)却变为44,增加了2,查看(初始ds+10)后的50h个字节

可以看出,40开始为栈段,但44后缺没有分配给栈段,反而代码结束,22后到数据段30前都空给了代码段,可以得到推论若程序有n个段,前n-1个段以16为单位分配,第n个段分配实际大小
任务6
如果将(1)、(2)、(3)题中的最后一条伪指令“end start”改为“end”(也就是说不指明程序的入口),则哪个程序仍然可以正确执行?请说明原因。
(3)仍然可以正确执行,因为没有指明程序入口时,cs设定为ds+10,即PSP后的位置作为程序入口,而(3)的代码段放在了最前面,刚好对应上
任务7
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
c1 segment ; 在集成软件环境中,请将此处的段名称由c→改为c1或其它名称
db 8 dup(0)
c1 ends
code segment
start:
mov ax,a
mov ds,ax ;a设为ds段
mov ax,b
mov es,ax ;b设为es段
mov ax,c1
mov ss,ax ;c设为栈段
mov sp,8 ;栈底设为c:8
mov cx,4 ;由于入栈只能为字数据,因此一次运算两个字,一并入栈,循环8/2次
mov bx,6
s: mov al,ds:[bx] ;低位计算靠前的数
add al, es:[bx] ;高位计算靠后的数
mov ah,ds:[bx+1]
add ah,es:[bx+1]
push ax
sub bx,2
loop s
mov ax,4c00h
int 21h
code ends
end start
执行代码,观察c段,可以看到求解成功

任务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,a
mov ds,ax ;a设为ds段
mov ax,b
mov ss,ax ;b设为栈段
mov sp,16 ;栈底设为b:16
mov cx,8 ;循环8次
mov bx,0
s: push [bx] ;从0开始依次入栈,即为逆序
add bx,2
loop s
mov ax,4c00h
int 21h
code ends
end start
执行代码,观察b段,可以看到求解成功

四、实验总结
- 在分配段空间时,以16字节为一个单位,不足的部分以0填充,但是若程序有n个段,前n-1个段以16为单位分配,第n个段分配实际大小
- 80806中,栈寄存器有CS, SS, DS, ES,其中DS、ES可以相对随意使用,如果操作需要3个段,如果是顺序操作考虑利用栈段,不过需要注意栈段的操作顺序是从高到低,超出3个段据就需要考虑在循环中更改ds了



浙公网安备 33010602011771号