汇编语言将数据、代码、栈放入不同的段

(1)把它们放到一个段中使程序显得混乱;
(2)前面程序中处理的数据很少,用到的栈空间也小,加上没有多长的代码,放到一个段里面没有问题。但如果数据、栈和代码需要的空间超过64KB,就不能放在一个段中(一个段的容量不能大于64KB,是我们在学习中所用的8086模式的限制,并不是所有的处理器都这样)。
所以,应该考虑用多个段来存放数据、代码和栈。
怎样做呢?我们用和定义代码段一样的方法来定义多个段,然后在这些段里面定义需要的数据,或通过定义数据来取得栈空间。具体做法如下面的程序所示,这个程序实现了和程序6.3一样的功能,不同之处在于它将数据、栈和代码放到不同的段中。


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,cs,不能这么写
    mov ss,ax
    mov sp,20         ;设置栈顶ss:sp指向stack:20

	mov ax,data
	mov ds,ax    ;ds指向data段


	mov bx,0     ;ds : bx指向data段中的第一个单元

    mov cx,8
	
  s:push [bx]
    add bx,2
    loop s        ;以上将data段中的0一15单元中的8个字型数据依次入栈
	
    mov bx,0
    mov cx,8
 s0:pop [bx]
    add bx,2
    loop s0    ;以上依次出栈8个字型数据到data段的0一15单元中
	
    mov ax,4c00h
    int 21h
code ends
end start

下面对程序做出说明
(1)定义多个段的方法
这点,我们从程序中可明显地看出,定义一个段的方法和前面所讲的定义代码段的方法没有区别,只是对于不同的段,要有不同的段名。
(2)对段地址的引用
现在,程序中有多个段了,如何访问段中的数据呢?当然要通过地址,而地址是分为两部分的,即段地址和偏移地址。如何指明要访问的数据的段地址呢?在程序中,段名就相当于一个标号,它代表了段地址。所以指令“mov ax,data”的含义就是将名称为"data”的段的段地址送入ax。一个段中的数据的段地址可由段名代表,偏移地址就要看它在段中的位置了。程序中“data”段中的数据“Oabch”的地址就是:data:6。要将它送入bx中,就要用如下的代码:

	mov ax,data
	mov ds,ax    
	mov bx,ds:[6]

我们不能用下面的指令:

mov ds,data
mov bx, ds:[6]

其中指令“mov ds,data”是错误的,因为8086CPU不允许将一个数值直接送入段寄存器中。程序中对段名的引用,如指令“mov ds,data”中的“data ",将被编译器处理为一个表示段地址的数值。
(3)“代码段”、“数据段”、“栈段”完全是我们的安排
现在,我们以一个具体的程序来再次讨论一下所谓的“代码段”、“数据段”、“栈段”。在汇编源程序中,可以定义许多的段,比如在程序中,定义了3个段,"code"、" data”和“stack "。我们可以分别安排它们存放代码、数据和栈。那么我们如何让CPU按照我们的这种安排来执行这个程序呢?下面来看看源程序中对这3个段所做的处理。
①为“data
我们在源程序中为这3个段起了具有含义的名称, 用来放代码的段我们将其命名为“code用来放数据的段我们将其命名 用作栈空间的段命名为“stack”。
这样命名了之后,CPU是否就去执行“code”段中的内容,处理“data”段中的数将“stack”当做栈了呢?
当然不是,我们这样命名,仅仅是为了使程序便于阅读。这些名称同“start " , "s", "s0” 等标号一样,仅在源程序中存在,CPU并不知道它们。

②我们在源程序中用伪指令“assume cs:code,ds:data,ssatack”将cs, ds和ss分别和code. data, stack段相连。这样做了之后,CPU是否就会将cs指向code ds指向data,ss指向stack,从而按照我们的意图来处理这些段昵?
当然也不是,要知道assume是伪指令,是由编译器执行的,也是仅在源程序中存在的信息,CPU并不知道它们。我们不必深究assume的作用,只要知道需要用它将你定义的具有一定用途的段和相关的寄存器联系起来就可以了。
③若要CPU按照我们的安排行事,就要用机器指令控制它,源程序中的汇编指令是CPU要执行的内容。CPU如何知道去执行它们?我们在源程序的最后用“end start”说明了程序的入口,这个入口将被写入可执行文件的描述信息,可执行文件中的程序被加载入内存后,CPU的CS:IP被设置指向这个入口,从而开始执行程序中的第一条指令。标号" start”在“code”段中,这样CPU就将code段中的内容当作指令来执行了。我们在code段中,使用指令:

    mov ax,stack       
    mov ss,ax
    mov sp,20        

设置ss指向stack设置ssap指向stack:20做栈空间来用。CPU若要访问data段中的数据,(如bx)来存放data段中数据的偏移地址。
CPU执行这些指令后,将把。tack段当则可用ds指向data段,用其他的寄存器总之,CPU到底如何处理我们定义的段中的内容,是当作指令执行,当作数据访
问,还是当作栈空间,完全是靠程序中具体的汇编指令,和汇编指令对CS:IP, SS:SP,DS等寄存器的设置来决定的。完全可以将程序6.4写成下面的样子,实现同样的功能。


assume cs:b,ds:a,ss:c

a segment
    dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h
a ends
 
c segment
    dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0    
c ends
	
b segment 
d: mov ax,c
   mov ss,ax
   mov sp,20h   ;希望用C段当作栈空间,设置SS:SP指向c:2O
    
   mov ax,a
   mov ds,ax    ;希望用ds:bx访问a段中的数据,ds指向a段

   mov bx,0     ;ds:bx指向a段中的第一个单元
   mov cx,8
s:push [bx]
  add bx,2
  loop s       ;以上将a段中的0一15单元中的8个字型数据依次入栈
 
  mov bx,0
  bov cx,8
s0:pop[bx]
  add bx,2
  loop s0      ;以上依次出栈8个字型数据到a段的15单元中

  mov ax,4c00h
  int 21h

b ends

  end d      ;d处是要执行的第一条指令,即程序的入口

发布日期:

所属分类: 编程 标签:  


没有相关文章!