实验五
1、将下面的程序编译、连接,用Debug加载、跟踪,然后回答问题
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
CPU执行程序,程序返回前,data段中的数据为多少? 不变
CPU执行程序,程序返回前,cs=076C、ss=076B、ds=076A
程序刚加载时,ds=075A,因为psp的存在,data段段地址为076A,赋值以后ds=076A,而data段占16个字节076A:10=076B:0,cs段同理,虽然在物理地址上这三个段是连续的,但由于被分为三个段,那么段地址必定要不同
设程序加载后,code段的段地址为X,则data段的段地址为X-2,stack段的段地址为X-1
2、将下面的程序编译、连接,用Debug加载、跟踪,然后回答问题
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段和stack段都不足16个字节,而汇编中会自动分配16个字节的空间,不足的用0补全
CPU执行程序,程序返回前,data段中的数据为多少? 不变
CPU执行程序,程序返回前,cs=076C、ss=076B、ds=076A
设程序加载后,code段的段地址为X,则data段的段地址为X-2,stack段的段地址为X-1
总结:定义了一个名为xx的段后,其中数据占n个字节,则为其分配的空间是16的倍数并大于等于段中数据的字节数(n/16+1)*16(/为整数除法),假设xx中有17字节的数据,则会为其分配32个字节的空间
3、将下面的程序编译、连接,用Debug加载、跟踪,然后回答问题
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
CPU执行程序,程序返回前,data段中的数据为多少? 不变
CPU执行程序,程序返回前,cs=076A、ss=076E、ds=076D
设程序加载后,code段的段地址为X,则data段的段地址为X+3,stack段的段地址为X+4
用R命令发现cx的值为44H(程序长度),data段和stack段不足16个字节,补0,所以这两个段实际占20H个字节,所以cs段中可执行的字节数为(44H-20H=24H),不是10H的整数呗,所以补0(这些0并不算在程序长度中,至于为什么栈段和数据段补的0算在程序长度中,可能因为这些是程序执行时实际可用的数据和栈空间,而那些00机器码并不能执行),cs段一共占据30H个字节
程序长度=代码段中的代码长度+数据段长度+栈段长度(后两个都是16的整数倍)
4、如果将(1)、(2)、(3)题中的最后一条伪指令“end start”改为“end”(也就是说不指明程序的入口),则那个程序仍然可以正确执行?请说明原因。
都能运行,但3的程序可用正确执行
如果不指明程序的入口,那么从加载入内存的第一个单元开始执行,尽管前两题的代码是数据段放在最前,但也可以被翻译成汇编指令(毕竟最终都是机器码),但不是我们真正想要执行的,而第三题恰好程序段放在最先,CPU在执行真正的机器码时,遇到中断指令后返回,所以如果程序段不在最前,必须指定程序入口
5、编写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
c segment
db 0,0,0,0,0,0,0,0
c ends
code segment
start: mov ax,a
mov ds,ax ;ds指向a段
mov ax,b
mov es,ax ;es指向b段
mov bx,0
mov cx,8 ;计算8次
s:mov dl, [bx] ;将ds:[bx]内存单元按字节送入dl
add dl, es:[bx] ;将ds:[bx]与es:[bx]内存单元值相加
push ds ;保护ds值,因为下面用到ds了
mov ax,c
mov ds,ax ;将ds指向c段
mov [bx],dl ;将dl(a和b相对应内存单元内容之和)写入c中
pop ds ;将ds恢复
inc bx ;bx递增
loop s
mov ax,4c00h
int 21h
code ends
end start
合理利用系统分配的栈来暂存ds的值
6、编写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 0,0,0,0,0,0,0,0
e ends
code sgement
start: mov ax,a
mov ds,ax
mov ax,b ;将b段设置为栈段
mov ss,ax
mov sp,16
mov bx,0
mov cx,8
s:push ds:[bx]
add bx,2
loop s
mov ax,4c00h
int 21h
code ends
end start
注意a段中的1、2、3、4、5其实都是字型数据,即0001H、0002H、0003H,而push、pop操作也恰好以字为单位
若为db 1,2,3,4,5,6,7,8,则均为字节型数据
来源:CSDN
作者:tmhhh
链接:https://blog.csdn.net/weixin_43569916/article/details/104575241