06.包含多个段的程序

包含多个段的程序

前言

前面的程序有一个问题,只有一个代码段。现在一个问题是,如果程序需要用到其他空间来存储数据,使用在哪呢?在上一讲中,我们讲到要使用一段安全的空间,可哪里安全呢?我们说 0:200~0:2FF是相对安全的,可这段空间只有256个字节,如果我们需要的空间超过256个字节该怎么办呢?
在操作系统中,合法的通过操作系统取得的空间都是安全的,因为操作系统不会让一个程序所用的空间和其他程序以及系统自己的空间相冲突,在操作系统允许的情况下,程序可以取得任意容量的空间
程序取得所需空间的方式有两种,一是在加载程序时为程序分配,二是在程序执行过程中向系统申请。我们不讨论第二种方式
加载程序时取得所需的空间我们前面深有体会,比如我们加载程序时,取得代码段中所有代码的存储空间
我们若要一个程序在被加载时取得所需的空间,则必须要在源程序中做出说明,我们通过源程序中定义段的方式来进行内存空间的获取
上面是从内存空间的角度,谈段的定义。我们再从程序规划的角度来读一下段的定义。大多数有用的程序,都要处理数据,使用栈空间,当然也都必须有指令,为了程序设计上的清晰与方便,我们一般定义不同的段来存放它们

在代码段中使用数据

编程计算以下8个数据的和,结果存放在ax寄存器中
0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h

  assume cs:codeseg

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

  start:  mov ax,0
          mov bx,0

          mov cx,8
  s:      add ax,cs:[bx]
          add bx,2
          loop s

          mov ax, 4c00h
          int 21h
  codeseg ends

end start

有以下几个注意的点:

  1. dw 的含义是定义字型数据
  2. 前 8 个数据存储的位置在于 cs:0 cs:2 cs:4 cs:6 cs:8 cs:a cs:c cs:e
  3. 我们的 ip 指向数据,可以使用 start 标号指定我们要指定的第一条执行命令的位置,end 的作用:程序的结尾;end 标号 cpu从何处开始执行程序

于是我们可以这要安排程序的框架

assume cd:codeseg

codeseg segment
  ...
  数据
  ...
start:
  ...
  代码
  ...
  mov ax,4c00h
  int 21h
codeseg ends

end start

在代码段中使用栈

完成程序,将 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h 逆序存储

  assume cd:codeseg

  codeseg segment
          dw 0123h, 0456h, 0789h, 0abch, 0defh, 0fedh, 0cbah, 0987h   ;存放数据
          dw 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0           ;开辟32个字节当作栈空间

  start:  mov ax, cs
          mov ss, ax
          mov sp, 30h     ;将bs:sp指向栈顶

          mov bx, 0
          mov cx, 8
  s0:     push cs:[bx]    ;循环进栈
          add bx, 2
          loop s0

          mov bx, 0
          mov cx, 8
  s1:     pop cs:[bx]     ;循环出栈
          add bx, 2
          loop s1

          mov ax, 4c00h
          int 21H
  codeseg ends

  end start

有以下几个注意的点:

  1. 和数据定义一样我们可以通过 dw 定义一段内存空间 并将里面的值初始化为0
  2. 可以利用 栈 后进先出 的特性实现逆序操作

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

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

  1. 将它们放到一个段中使得程序混乱
  2. 前面程序中处理的数据很少,用到的栈空间很少,加上没有多长的代码,放到一个段里没有问题。但如果数据,栈和代码的空间超过 64 kb,就不能放到同一个段里

将上面逆序的代码改造成多个段的形式:

  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, ax
          mov sp, 20h

          mov ax, data
          mov ds, ax
          
          mov bx, 0
          mov cx, 8
  s0:     push [bx]
          add bx, 2
          loop s0

          mov bx, 0
          mov cx, 8
  s1:     pop [bx]
          add bx, 2
          loop s1

          mov ax, 4c00h
          int 21h
  code ends

  end start

有以下几个注意的点:

  1. 段的定义和之前代码的定义一样,其实本质上都是段,取决于我们怎么使用它将其分为 代码段 数据段 栈段
  2. 段名 指代该段的起始基址
  3. assume 需要将段名与相应的寄存器关联起来

参考

<<汇编语言第四版>>-王爽

posted @ 2023-08-06 18:20  异世界穿越中!.!  阅读(18)  评论(0)    收藏  举报