实验3 多个段的汇编源程序编写与调试
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]
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

进行debug,使用r命令观察接着根据CX进行反汇编

发现反汇编的结果并不是完全正确,多了很多冗余数据,使用g命令运行到程序结束之前:

进行修改:

重新进行编译连接:

发现NUIST的IST颜色变色了,所以我猜测这里的数据作用是改变字符串的颜色信息
2.实验任务2
1、数字↔数字字符的相互转换!!!!!!
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 cx,5
s: mov ah,0
mov al,ds:[di]
mov bl,10
div bl
mov dx,ax
add dx,3030H
mov ah,2
int 21h
mov dl,dh
mov ah,2
int 21h
inc di
loop s
mov ah,4CH
int 21h
code ends
end start
进行编译连接并运行:

得到了输出结果23,50,66,71和35
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
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段中的数据为多少?
理论分析来说,不会发生变化
原来data段中存放的数据:到程序返回前,data段中存放的数据为:

运行到程序结束前的数据段:

问题2:CPU执行程序,程序返回前,cs=,ss=,ds=
根据问题1的第二张图片可得:cs=076C,ss=076B,ds=076A
问题3:设程序加载后,code段的段地址为X,则data段的段地址为,stack段的段地址为
data段的段地址为X-2,stack段的段地址为X-1,因为程序开始前data定义了16个字节空间的数据,stack定义了16个字节空间的数据,所以每一个段相差16个即10h个字节。
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段中的数据为多少?
进入程序进行反汇编到程序返回前

查看数据段中的值

由程序得,data段中的数据应为4个字节的内容即0123h,0456h
2.CPU执行程序,程序返回前,cs=,ss=,ds=?
由上图得,cs=076C,ss=076B,ds=076A
3.设程序加载后,code段的段地址为X,则data段的段地址为,stack段的段地址为
data:X-2,stack:X-1
4.首先占用的字节数最少为16个且一定为16的倍数,如果N可以整除16,那么
占有的空间就为N个字节,如果不可以,实际占有的空间为(N/16+1)*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.CPU执行程序,程序返回前,data段中的数据为多少?

data段仍旧占4个字节,为0123h,0456h
2.CPU执行程序,程序返回前,由运行结果可以看出cs=076A,ss=076E,ds=076D
3.设程序加载后,code段的段地址为X,则data段的段地址为,stack段的段地址为
data段的段地址为X+3,stack段的段地址为X+4
6.实验任务6
如果将实验任务3,4,5中的最后一条伪指令“end start”改为“end”(也就是说,不指明程序的入口),则哪个程序仍然可以正确执行?请说明原因
解:只有实验任务5的程序还可以正确执行,因为实验任务5的程序的数据段和栈段都定义在程序的code段后,u命令反汇编的情况下不会影响,而实验任务3,4都定义在code段前,前面定义的data段和栈段中的数据会当作代码进行反汇编,无法正确执行。
7.实验任务7
编写code段中的代码,将a段和b段中的数据依次相加,将结果保存到c段中
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 di,0
mov cx,8
s: mov si,a
mov ds,si
mov al,ds:[di]
mov si,b
mov ds,si
add al,ds:[di]
mov si,c1
mov ds,si
mov ds:[di],al
inc di
loop s
mov ax,4c00h
int 21h
code ends
end start
运行到程序结束前,用d命令查看现在DS存放的内容

发现结果为02 04 06 08 0A 0C 0E 10,完成了要求
8.实验任务8
编写code段中的代码,用push指令将a段中的前8个字型数据,逆序存储到b段中
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 di,0
mov cx,8
s: mov si,a
mov ds,si
push ds:[di]
inc di
inc di
loop s
mov di,0
mov cx,8
s1: mov si,b
mov ds,si
pop ds:[di]
inc di
inc di
loop s1
mov ax,4c00h
int 21h
code ends
end start

一开始想着逆序输出到b段中就在第二个循环中将bi的初始值设成16,然后dec两次,
尝试了几次发现还是正序,才想到栈的pop函数本身就是先入后出的逆序过程,
我相当于逆序的逆序还是正序了,接着直接进行同样的步骤运行得到了结果
三、实验总结
总体来说这次的实验让我很清晰的理解了段的分配机制,data段和栈段,定义段的位置
都会对结果产生莫大的影响,最后一个实验任务还让我对栈的知识回顾了一下,实验任务2
让我重新看了书本上div指令的部分,商默认存储在al中,ah默认存储余数,int 21h的二号子命令
是输出dl中的内容

浙公网安备 33010602011771号