6.3 将数据,代码,栈放入不同的段
-
注意, 当数据,代码,栈需要的空间超过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 push ds:[0] push ds:[2] pop ds:[2] pop ds:[0] mov ax, 4c00h int 21h code ends end start
-
程序中“data”段中的数据“0abch”的地址就是:data:6。
我们要将它送入bx中,就要用如下的代码:
mov ax,data mov ds,ax mov bx,ds:[6]
我们不能用下面的指令:
mov ds,data mov ax,ds:[6]
其中指令“mov ds,data” 是错误的,因为8086CPU不允许将一个数值直接送入段寄存器中。
当我看到下面这段代码
mov ax,data mov ds,ax mov bx,ds:[6]
我有一个疑问,就是assume cs:code, ds:data, ss:stack 不是已经将data和ds绑定了吗,何必再一次赋值呢?(可参考(73条消息) 汇编语言——assume的作用_汇编assume_手写的从前66的博客-CSDN博客)
-
首先要明白的是 assume 是伪代码,无法翻译成机器语言,只有由编译器运行。因此 data 是无法赋值给 ds 的,因为不存在这样一条命令。
-
换句话说,编写程序,是写给编译软件的。由编译软件,编译成机器码,再去控制CPU。但是,编译软件,对assume语句,并不生成机器码。所以,必须有mov ax,data,mov ds,ax,CPU才能受控。assume语句,是伪指令,仅仅是写给编译软件的。编译软件,并不把它生成机器码。
-
个人理解,可以把 data 看作 java 中的运行时才确定的变量,只是一种声明的段名,实际运行时才确定真正的值,其含义只是一种规范,给程序员看以知道各个段的含义。
-
assume对除了CS以外的其它段寄存器,仅仅只是关联了段名,以便在访问段内变量时程序可以知道用哪个段寄存器,并没有在程序加载时将段地址装入段寄存器。所以,将段地址装入段寄存器的工作,必须由用户在程序中自己编写代码,并在程序开始运行时执行代码完成装入工作。
仅仅对CS段寄存器,会在关联段名的同时,在程序加载时自动将段地址装入段寄存器。 -
作用:用于标识默认段前缀
解释:assume 并不能改变ds等段寄存器的值,但他能改变编译器产生的汇编代码。比如:
assume ss:stack stack segment x :db 0 stack ends
如果程序需要mov ax,[x],那么程序如何定位[x]呢?我们知道x只是一个偏移地址0,所以此时assume就相当于告诉编译器stack段的所有标号都与ss相关联,所以此时[x]就相当于ss:[0]。如果我们直接将这句改为mov ax,ss:[0],那么前面不加assume也是可以的。这也是为什么[0]被编译器强制理解为立即数,而[标号]却被理解为标号里的内容的原因,因为标号必须与段assume,否则会报错cannot address with segment register。而[0]无默认段,就只能被认为为立即数了。
-
-