将数据、代码、栈放入不同的段:把这些内容全部放在代码段中无疑会让程序显得混乱而且难以管理和操作,容易出错,所以,要把数据、代码和栈放入不同的段中,这也体现了软件工程中“分而治之”的思想。
assume cs:code, ds:data, ss:stack
data segment
dw 0123h, 0456h, 0789h, 0abch, 0defh, 0fedh, 0cbah, 0987h
data segment
dw 0123h, 0456h, 0789h, 0abch, 0defh, 0fedh, 0cbah, 0987h
;dw的意思是“define word”,即定义了已连串的字型数据(后面8个数据)
data ends
stack segmetn
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
data ends
stack segmetn
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
定义多个段的方法:定义数据段和栈段跟定义代码段一样,都是:XXX segment ; XXX ends;
对段地址的引用:如何访问到段的开始地址,寻址是按照:段地址×16 + 偏移地址来实现的。每一个段的标号就是表示段地址,比如:data segment;中data就是数据段的段地址。
mov ax, data
mov ds, data
就是使ds指向了data段中的第一个单元,那么以后:mov [0], ax; 就是把ax的内容送入到data段开始的第一个内存单元;但是,我们不能这样写:mov ds, data; data其实是一个段地址,一个值,这样写相当于把值直接送入ds,这是不允许的。
要注意,所谓的数据段,代码段,栈段都是我们自己定义的,是为了方便程序员阅读的,CPU并不知道哪些就是数据段,哪些是代码段,哪些是栈段。所以,data, code, stack只是一系列的标号而已,标号就是为了提高可读性。assume cs:code, ds:data, ss:stack;这句只是将你定义的具有一定用途的段和相关的寄存器联系起来,并不是说,CPU知道cs指向了code, ds指向了data,ss指向了stack;所以,我们仍然需要在程序中写:
mov ax, stack
mov ss, ax
mov sp, 20h
这样类似的指令来指明ss指向了stack。所以,code, data, stack完全可以换成其他名字,只是我们在定义的时候需要定义一个可读性比较强的标号。