第六章内容解读 包含多个段的程序
6.1 在代码段中使用数据
问题:编程计算以下8个数据的和,并且将结果放置在ax寄存器中(通过循环的方式)
0123h 0456h 0789h 0abch 0defh 0fedh 0cbah 0987h
如果希望通过循环的方式进行累加,在累加之前需要将数据存储在连续的内存单元中,内存位置由操作为
我们自动分配
assume cs:code
code segment
dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h
mov bx,0
mov ax,0
mov cx,8
s: add ax,cx:[bx] ;将内存中的数据加到ax中
add bx,2 ;每次偏移地址移动两个单元
loop s
mov ax,4c00h
int 21h
code ends
end
我们编译链接之后Debug看一下
u命令查看汇编指令之后,发现并不是我们书写的那些命令,用d命令查看程序内存(注意DS为0B2D,所以我们应该查看0B3D)
发现,内存中存储的竟然是我们引入的数据(一共16个字节),那么可能就是数据占了16字节,那么16字节之后应该是我们的汇编指令
了吧,再次用u指令查看一下
答案很明确了,我们的程序加载进入内存之后,占用内存空间16字节的数据(用dw定义的)占据了前16字节,之后才是汇编指令
那么应该如果让指令从我们的汇编指令开始呢?在源程序中用start标明一下
assume cs:code
code segment
dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h
start : mov bx,0
mov ax,0
mov cx,8
s : add ax,cs:[bx]
add bx,2
loop s
mov ax,4c00h
int 21h
code ends
end start
start
就表示了程序的开始的地址,CPU就从star指向的地址开始执行
6.2 在代码段中使用栈
解读程序6.3
首先定义了8个字型的数据(16B),然后定义了16字型的数据(32B)
因此CS:0~CS:0F存放前面的数据,CS:10到CS:2F作为栈空间,因此SP指针指向就是30H
剩下的就是将数据通过栈进行转移了
😃 😃 😃
检测点6.1
(1) mov cs:[bx],ax
(2)
分析:第一个dw一共有8个字型数据,占据了16字节(0~15)
第二个dw一共有10个字型的数据,占据了20个字节(16~35),因此栈空间的sp从36(十进制)开始
16进制的sp:24h
cs
24h
cs:[bx]
6.3 将数据、代码、栈放入不同的段
前面做法的弊端:将数据、代码、栈放入同一个段显得很冗杂并且边界的明确很麻烦、如果数据很长还有可能超出界限
因此我们考虑将他们分别存放到不同的段中
- 我们将不同的数据放到不同的段中,在引用的时候,
段的名称就代表了首地址
, - 不同段的命名是为了让程序员理解,我们在设定具体的作用时还是要用汇编代码进行设置
实验五 编写、调试具有多个段的程序
千呼万唤始出来,终于开始实验五啦!
(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
进入debug
首先查看DS=075A,因此我们查看076A:0 F的数据,确认是我们写入的数据
执行一下代码(g 001d)再次查看076A:0 F的内容,没有更改
(1)CPU执行程序,data数据段中的数据没有更改
(2)程序返回之前,cs=076C ss=076B ds=076A
(3)data段地址=X-2
stack段地址=X-1
2.编译链接debug程序
(1)data段中的数据不变
(2)cs=076C ss=076B ds=076A
(3)data段地址=X-2 stack段地址=X-1
(4)((N+15)/16)*16
3.编译链接debug回答问题
- data段的数据不变还是
076D :0000 23 01 56 04
cs=076A ss=076E ds=076D
data段地址=X+3 stack段地址=X+4
4.如果将(1)、(2)、(3)题中的最后一条伪指令“end start”改为“end”(也就是说,不指明程序的入口),则哪个程序仍然可以正确执行?请说明原因。
3是可以的,程序从所分配的空间开始执行,只有第三个开始是代码段,前两个都是数据段开始
5.编写代码
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
s: mov al,[bx]
add al,es:[bx] ;a , b的值加到al中
mov dx,c
mov ds,dx ;ds -> c
mov [bx],al
mov ax,a ;重新规定指向
mov ds,ax
inc bx
loop s
mov ax,4c00h
int 21h
code ends
end start
5.编写程序
assume cs:code
a segment
dw 1,2,3,4,5,6,7,8
a ends
b segment
dw 0,0,0,0,0,0,0,0
b ends
code segment
start : mov ax,a
mov ds,ax ;ds -> a
mov ax,b
mov ss,ax ;ss ->b
mov bx,0
mov sp,16 ;8个字型数据占据了0~15
mov cx,8
s :push [bx]
add bx,2
loop s
code ends
end start