06.包含多个段的程序
包含多个段的程序
前言
前面的程序有一个问题,只有一个代码段。现在一个问题是,如果程序需要用到其他空间来存储数据,使用在哪呢?在上一讲中,我们讲到要使用一段安全的空间,可哪里安全呢?我们说 0:200~0:2FF是相对安全的,可这段空间只有256个字节,如果我们需要的空间超过256个字节该怎么办呢?
在操作系统中,合法的通过操作系统取得的空间都是安全的,因为操作系统不会让一个程序所用的空间和其他程序以及系统自己的空间相冲突,在操作系统允许的情况下,程序可以取得任意容量的空间
程序取得所需空间的方式有两种,一是在加载程序时为程序分配,二是在程序执行过程中向系统申请。我们不讨论第二种方式
加载程序时取得所需的空间我们前面深有体会,比如我们加载程序时,取得代码段中所有代码的存储空间
我们若要一个程序在被加载时取得所需的空间,则必须要在源程序中做出说明,我们通过源程序中定义段的方式来进行内存空间的获取
上面是从内存空间的角度,谈段的定义。我们再从程序规划的角度来读一下段的定义。大多数有用的程序,都要处理数据,使用栈空间,当然也都必须有指令,为了程序设计上的清晰与方便,我们一般定义不同的段来存放它们
在代码段中使用数据
编程计算以下8个数据的和,结果存放在ax寄存器中
0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h
assume cs:codeseg
codeseg segment
dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h
start: mov ax,0
mov bx,0
mov cx,8
s: add ax,cs:[bx]
add bx,2
loop s
mov ax, 4c00h
int 21h
codeseg ends
end start
有以下几个注意的点:
- dw 的含义是定义字型数据
- 前 8 个数据存储的位置在于 cs:0 cs:2 cs:4 cs:6 cs:8 cs:a cs:c cs:e
- 我们的 ip 指向数据,可以使用 start 标号指定我们要指定的第一条执行命令的位置,end 的作用:程序的结尾;end 标号 cpu从何处开始执行程序
于是我们可以这要安排程序的框架
assume cd:codeseg
codeseg segment
...
数据
...
start:
...
代码
...
mov ax,4c00h
int 21h
codeseg ends
end start
在代码段中使用栈
完成程序,将 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h 逆序存储
assume cd:codeseg
codeseg segment
dw 0123h, 0456h, 0789h, 0abch, 0defh, 0fedh, 0cbah, 0987h ;存放数据
dw 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;开辟32个字节当作栈空间
start: mov ax, cs
mov ss, ax
mov sp, 30h ;将bs:sp指向栈顶
mov bx, 0
mov cx, 8
s0: push cs:[bx] ;循环进栈
add bx, 2
loop s0
mov bx, 0
mov cx, 8
s1: pop cs:[bx] ;循环出栈
add bx, 2
loop s1
mov ax, 4c00h
int 21H
codeseg ends
end start
有以下几个注意的点:
- 和数据定义一样我们可以通过 dw 定义一段内存空间 并将里面的值初始化为0
- 可以利用 栈 后进先出 的特性实现逆序操作
将数据 代码 栈 放入不同的段中
在前面的内容中,我们在程序中用到了数据和栈,将数据,栈和代码都放到了一个段里面。我们在编程时要注意何处是数据,何处是栈,何处是代码,这样做显然有两个问题:
- 将它们放到一个段中使得程序混乱
- 前面程序中处理的数据很少,用到的栈空间很少,加上没有多长的代码,放到一个段里没有问题。但如果数据,栈和代码的空间超过 64 kb,就不能放到同一个段里
将上面逆序的代码改造成多个段的形式:
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, 0, 0, 0, 0, 0, 0, 0, 0
stack ends
code segment
start: mov ax, stack
mov ss, ax
mov sp, 20h
mov ax, data
mov ds, ax
mov bx, 0
mov cx, 8
s0: push [bx]
add bx, 2
loop s0
mov bx, 0
mov cx, 8
s1: pop [bx]
add bx, 2
loop s1
mov ax, 4c00h
int 21h
code ends
end start
有以下几个注意的点:
- 段的定义和之前代码的定义一样,其实本质上都是段,取决于我们怎么使用它将其分为 代码段 数据段 栈段
- 段名 指代该段的起始基址
- assume 需要将段名与相应的寄存器关联起来
参考
<<汇编语言第四版>>-王爽
浙公网安备 33010602011771号