汇编语言入门-第六章包含多个段的程序
程序取得空间的方式有两种:
1、加载程序的时候为程序分配。
2、程序向操作系统申请。
我们要在加载程序的时候申请空间,必须写程序的时候声明。我们的源程序在代码中声明。
下面在一个段中存放数据,代码、栈,先体会一下不使用多个段时的情况。另一种情况,在不同的段中存放不同的数据,代码段,数据段,栈。
6.1 在代码段中使用数据
考虑这样的一个问题,编程计算以下8个数据的和,结果存在AX寄存器中:
0123H,0456H,0789H,0abch,0defh,0fedh,0cbah,0987h
具体看程序的做法:
assume cs:code
code segment
dw 0123h,0456h,0789h,0abch,0def,0fedh,0cbah,0987h
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
dw 是定义字型数据。define word 的意思。
程序在cs 开始段定义了16个数据。cs:ip 应该执行mov bx,0 第一个语句。(但实际上不是,在上面的程序中,你需要用debug,把ip 指向10h)
如何让这个程序编译后可以在系统中直接运行呢?我们可以在源程序中指明程序的入口所在,具体做法:
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.
6.2 在代码中使用栈
完成下面的程序,利用栈,将程序中定义的数据逆序存放。
assume cs:codesg
codesg segment
dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h
?
codesg ends
end
程序的大致思路:
再定义一组同样大小的数据,sp 执向栈顶,ss 指向栈底。然后把要逆序的数据放到这个堆栈,然后再pop出来原来的位置就可以了。
程序6.3
assume cs:codesg
codesg segment
dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h
dw 0,0,0,0,0,0,0,0
start : mov ax,cs
mov ss,ax
mov sp,32 ; 栈顶指向cs:32
mov bx,0
mov cx,8
s: push cs:[bx]
add bx,2
loop s
mov bx,0
mov cx,8
s0: pop cs:[bx]
add bx,2
loop s0
mov ax,4c00h
int 21h
codesg ends
end start ; 指明程序的入口在start 处
6.3 将数据、代码、栈放入不同的段中
在前面的内容中,我们在程序中用到了数据和栈,我们将数据、栈和代码都放到了一个段里边,我们在编程的时候要注意何处数据,何处是栈何处是代码。这样做显然有两个问题:
1)把他们放到一个段中使程序显得混乱;
2)前面程序中处理的数据很少,用到的栈空间很小,加上没有多长的代码,放到一个段里面没有问题,但如果数据、栈和代码需要的空间超过64kb,就不能放在一个段中(一个段的容量不能大于64kb,8086 模式的限制,并不是所有的处理器都这样)
所以,我们应该考虑用多个段来存放数据、代码和栈。
怎么做呢?不同的数据定义在不同的段中,数据放在数据段,栈放在栈段,代码放在代码段。
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
mov bx,0
mov cx,8
s: push [bx]
add bx,2
loop s
mov bx,0
mov cx,8
s0: pop [bx]
add bx,2
loop s0
mov ax,4c00h
int 21h
code ends
end start
1)定义多个段的方法
2)对段地址的引用
3)代码段,数据段,栈段都是我们的安排
实验五 编写,调试具有多个段的程序。

答:
1)data 段的数据没有变换呢。
2)ds=cs-32 ss=ds+16
3) data 段的地址为cs-32 ,stack 段的段地址为cs-16.
这里请注意,cs ds ss 各个相差一,因为他们的地址使cs*16+ip ds*16+偏移地址,ss*16+sp.

答案:
1) cpu执行程序,程序返回前,data段中的数据为多少?这里的sp 指向的是16 ,不太理解是否会破会整个程序栈。如果没有的话data 段的数据没有变化。
2)cs = 076c
ss = 076b
ds= 076a
3) stack : x-1 ds: x-2
4) 如果段中数据占 N 个字节,则程序加载后,该段实际占用的空间为 (N + 15) / 16 * 16 字节(即向上取整为 16 的倍数)。

1)没有变化,

2)cs 为076a ss: 076e ds 076d
3) 该程序加载后,code段的段地址为X,x+3 data 段的段地址, stack 段的段地址。

4)end start 改为end ,则第三个程序可以正确执行,因为先定义的代码段。
5)mov ax,0
mov bx,0
mov dx,0
mov cx,8
s:
mov ax,a
mov ds,ax
add dx,[bx]
mov ax,b
mov ds,ax
add dx,[bx]
mov ax,c
mov ds,ax
mov [bx],dx
inc bx
loop s
mov ax,4c00h
int 21h

答:
mov ax,a
mov ds,ax
mov ax,b
mov ss,ax
mov sp ,8
mov bx,0
mov cx,8
s:
push bx
inc bx
loop s
mov ax,4c00h
int 21h
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐

所有评论(0)