程序取得空间的方式有两种:

1、加载程序的时候为程序分配。

2、程序向操作系统申请。

我们要在加载程序的时候申请空间,必须写程序的时候声明。我们的源程序在代码中声明。

下面在一个段中存放数据,代码、栈,先体会一下不使用多个段时的情况。另一种情况,在不同的段中存放不同的数据,代码段,数据段,栈。

6.1 在代码段中使用数据

考虑这样的一个问题,编程计算以下8个数据的和,结果存在AX寄存器中:

0123H,0456H,0789H,0abch,0defh,0fedh,0cbah,0987h

具体看程序的做法:

assume cs:code  
code segment
    dw 0123h,0456h,0789h,0abch,0def,0fedh,0cbah,0987h
    mov bx,0
    mov ax,0
    mov cx,8
    s: add ax,cs:[bx]
       add bx,2
       loop s
    mov ax,4c00h
    int 21h
code ends
end

dw 是定义字型数据。define word 的意思。

程序在cs 开始段定义了16个数据。cs:ip  应该执行mov bx,0 第一个语句。(但实际上不是,在上面的程序中,你需要用debug,把ip 指向10h)

如何让这个程序编译后可以在系统中直接运行呢?我们可以在源程序中指明程序的入口所在,具体做法:

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

   mov ax,4c00h
   int 21h

code ends
end start

注意这个程序和上一个程序区别,这个程序指明了程序的入口地址是start.

6.2 在代码中使用栈

完成下面的程序,利用栈,将程序中定义的数据逆序存放。

assume cs:codesg

codesg segment 

dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h

?

codesg ends

end

程序的大致思路:

再定义一组同样大小的数据,sp 执向栈顶,ss 指向栈底。然后把要逆序的数据放到这个堆栈,然后再pop出来原来的位置就可以了。

程序6.3

assume cs:codesg
codesg segment
    dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h
    dw 0,0,0,0,0,0,0,0

start : mov ax,cs
        mov ss,ax
        mov sp,32  ; 栈顶指向cs:32
        mov bx,0
        mov cx,8 
     s: push cs:[bx]
        add bx,2
        loop s
        mov bx,0
        mov cx,8
     s0: pop cs:[bx]
         add bx,2
        loop s0
        mov ax,4c00h
        int 21h
codesg ends
end start                 ; 指明程序的入口在start 处

6.3 将数据、代码、栈放入不同的段中

在前面的内容中,我们在程序中用到了数据和栈,我们将数据、栈和代码都放到了一个段里边,我们在编程的时候要注意何处数据,何处是栈何处是代码。这样做显然有两个问题:

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
stack ends
code segment

start : mov ax,stack
        mov ss,ax
        mov sp,16
        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

1)定义多个段的方法

2)对段地址的引用

3)代码段,数据段,栈段都是我们的安排

实验五 编写,调试具有多个段的程序。

答:

1)data 段的数据没有变换呢。

2)ds=cs-32 ss=ds+16

3) data 段的地址为cs-32 ,stack 段的段地址为cs-16.

这里请注意,cs ds ss 各个相差一,因为他们的地址使cs*16+ip ds*16+偏移地址,ss*16+sp.

答案:

1) cpu执行程序,程序返回前,data段中的数据为多少?这里的sp 指向的是16 ,不太理解是否会破会整个程序栈。如果没有的话data 段的数据没有变化。

2)cs = 076c

     ss = 076b

    ds= 076a

3) stack : x-1 ds: x-2

4) 如果段中数据占 N 个字节,则程序加载后,该段实际占用的空间为 (N + 15) / 16 * 16 字节(即向上取整为 16 的倍数)。

1)没有变化,

2)cs 为076a ss: 076e ds 076d

3) 该程序加载后,code段的段地址为X,x+3 data 段的段地址, stack 段的段地址。

4)end start 改为end ,则第三个程序可以正确执行,因为先定义的代码段。

5)mov ax,0

      mov bx,0

      mov dx,0

      mov cx,8

   s:

     mov ax,a

     mov ds,ax     

     add dx,[bx]

     mov ax,b

     mov ds,ax

     add dx,[bx]

     mov ax,c

    mov ds,ax

   mov [bx],dx 

    inc bx

   loop s

   mov ax,4c00h

   int 21h

答:

mov ax,a

mov ds,ax

mov ax,b

mov ss,ax

mov sp ,8

mov bx,0

mov cx,8

s:

push bx

inc bx

loop s

mov ax,4c00h

int 21h

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐