将数据、代码、栈放入不同的段
将数据、代码、栈放入同一个段中会出现的问题:
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,0,0,0,0,0,0,0,0 //16个字
stack ends
code segment
//确定栈段段寄存器
stark: mov ax, stack //栈段的第一条数据的地址
mov ss, ax
mov sp, 020H //16个字(16个字节是0000~000F)是01f + 1 = 020
//确定数据段段寄存器
mov ax, data
mov ds, ax
mov bx, 0
mov cx, 8 //栈一次2个内存单元所以16字节只需要循环8次
s: push ds:[bx]
add bx, 2
loop s
mov bx, 0
mov cx, 8
s0: pop ds:[bx]
add bx, 2
loop s0
mov ax, 4c00H
int 21H
code ends
end stark
1) 定义多个段
定义多个段的方法和前面定义一样,只是对于不同的段,要有不同的段名。
2)对段地址的引用
在程序中,段名就相当于一个标号,他代表了段地址。所以指令“mov ax, data”的含义就是将名称为“data”的段的段地址送入 ax。一个段中的数据的段地址可由段名代表,偏移地址就要看它在段中的位置了。
3)代码段、数据段、栈段完全是我们安排的。
在汇编源程序中,可以定义许多的段。
在源程序中我们将用来放数据的段命名为data,将用来放代码的段命名为code,将用作栈的段命名为stack。这样的命名,仅仅是为了使程序便于阅读。它们仅在源程序中存在,CPU并不知道它们。
assume是伪指令,是由编译器执行的,也是仅在源程序中存在的信息,CPU并不知道它们。assume的作用就是将你定义的具有一定用途的段和相关的寄存器联系起来。
CPU把我们定义的段中的内容,是当作指令执行,当作数据访问,还是当作栈空间,完全是靠程序中具体的汇编指令,和汇编指令对CS:IP、SS:SP、DS等寄存器的设置来决定的。