【汇编语言/底层开发】6、程序中包含多个segment

时间:2021-12-02 03:21:54

众所周知的是,我们所开发的应用程序需依赖于操作系统运行,因此应用程序所使用的内存空间必须是安全的,不能与操作系统和其他应用程序相重合。因此,应用程序所需要的空间应当通过操作系统申请。对于我们使用汇编语言开发的程序而言,可以通过在源程序中定义段来获取内存空间。

1、在代码段中定义数据

在编写汇编程序时,可以直接在代码段中对数据进行定义。使用dw可以定义若干个字型数据,每个数据占据两个字节。但是由此带来的问题就是,代码段中的所有数据在运行时都会当做指令代码进行处理,因此我们使用dw定义的数据不会被正确识别。为了解决这个问题,我们可以在程序真正的起始位置前和伪指令end后面加上起始标号start:,通过这种方式通知编译器程序正确的起始位置。这样程序的框架就像下面这个样子。

assume cs:code
code segment
//数据
//......
//......
start:
//代码
//......
//......
code ends
end start

下面就是一个采用这种框架的程序:

assume cs:code
code segment
dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h
start:
mov bx,0
mov ax,0
mov cs,8
s: add ax, cs:[bx]
add bx, 2
loop s

mov ax, 4c00h
int 21h
code ends
end start

2、使用多个段进行数据、代码和栈的分离

如前一节所叙述的使用起始标号来分隔代码和数据的方法存在一些问题。主要由:(1)使得程序显得混乱、可读性差;(2)如果数据、栈和代码占用了超过64k的空间,那么将无法放入一个段中。为了解决这个问题,我们可以定义多个段,分别来保存数据、栈元素和代码。

代码段、数据段和栈段寄存器可以分别在伪指令assume中定义相应的别名,通过这些别名定义代码段、数据段和栈段。具体的实现过程可参考以下程序段:

//assume是只在源程序中存在的伪指令,由编译器执行,并不会自动绑定寄存器和segment名称,因此还是要手动对各个寄存器赋值
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
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