欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 创投人物 > 汇编语言 第六章-包含多个段的程序

汇编语言 第六章-包含多个段的程序

2025/3/16 10:57:12 来源:https://blog.csdn.net/2302_80490510/article/details/145432077  浏览:    关键词:汇编语言 第六章-包含多个段的程序

在代码段中使用数据

问题引入

问题1

前面我们写的程序中,只有一个代码段。

现在有一个问题是:    如果程序需要用其他空间来存放数据,我们使用哪里呢?

第5章中,我们讲到要使用一段安全的空间。    我们说0:200~0:300是相对安全的;

可这段空间的容量只有256个字节,如果我们需要的空间超过256个字节该怎么办呢? 放心,系统妈妈会给的。怎么给呢?我们粗略地讲下,但这不是必须要会的,听过就行。

问题2

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

0123H,0456H,0789H,0abcH,0defH,0fedH,0cbaH,0987H。

在前面的课程中,我们都是累加某些内存单元中的数据,并不关心数据本身。 可现在我们要累加的就是已经给定了数值的数据。

解决代码

assume cs:code
code segment
dw 0123H, 0456H, 0789H, 0abcH, 0defH, 0fedH, 0cbaH, 0987Hstart:mov bx, 0mov ax, 0mov cx, 8s:  add ax, cs:[bx]add bx, 2loop smov ax, 4c00Hint 21H
code ends
end start

dw命令

上述程序第一行中的 “dw”的含义是定义字型数据。

dw即define word。 在这里,我们使用dw定义了8个字型数据(数据之间以逗号分隔),它们所占的内存空间的大小为16个字节。

程序中的指令就要对这8个数据进行累加,可这8个数据在哪里呢?

由于它们在代码段中,程序在运行的时候CS中存放代码段的段地址,所以我们可以从CS中得到它们的段地址。

这8个数据的偏移地址是多少呢?    

因为用dw定义的数据处于代码段的最开始,所以偏移地址为0,这8 个数据就在代码段的偏移0、2、4、6、8、A、C、E处。

程序的框架

从上面的程序,我们可以得到一个程序都会有的部分,也就是固定格式

assume cs:code
code segment:数据:
start::代码:
code ends
end start

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

为什么

在前面的内容中,我们在程序中用到了数据和栈,我们将数据、栈和代码都放到了一个段里面。

我们在编程的时候要注意何处是数据,何处是栈,何处是代码。

这样做显然有两个问题:

(1)把它们放到一个段中使程序显得混乱;

(2)前面程序中处理的数据很少,用到的栈空间也小,加上没有多长的代码,放到一个段里面没有问题。那如果数据很多,而一个段最大64kb,会溢出。

所以,我们应该考虑用多个段来存放数据、代码和栈

问题引入

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

assume

cs:codesg    

codesg segment      

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

?  

 code ends    end

如果将数据全部存放在一个段,如下:

assume cs:code
code segment
dw 0123H, 0456H, 0789H, 0abcH, 0defH, 0fedH, 0cbaH, 0987H
dw 0H, 0H, 0H, 0H, 0H, 0H, 0H, 0Hstart:mov ax, csmov ss, axmov bx, 0mov sp, 32mov cx, 8s1: push cs:[bx]add bx, 2loop s1mov bx, 0mov cx, 8s2: pop cs:[bx]add bx, 2loop s2mov ax, 4c00Hint 21Hcode ends
end start

怎样做

我们用和定义代码段一样的方法来定义多个段,然后在这些段里面定义需要的数据,或通过定义数据来取得栈空间。

我们重新写一版上面的代码,对其进行优化,将数据,代码,栈放入不同的段

代码:

assume cs:code, ds:data, ss:stack   ; 段寄存器定义data segmentdw 0123h, 0456h, 0789h, 0abch, 0defh, 0fedh, 0cbah, 0987h  ; 原始数据
data endsstack segmentdw 0, 0, 0, 0, 0, 0, 0, 0   ; 预留 8 个 word 的栈空间
stack endscode segment
start:mov ax, stack     ; 设置栈段mov ss, axmov sp, 16        ; 栈指针初始化,指向栈段顶端(16 = 8*2)mov ax, data      ; 设置数据段mov ds, axmov bx, 0         ; BX 用作数组索引mov cx, 8         ; 共有 8 个 word 数据; ====== 将数据依次压入栈 ======
push_loop:push ds:[bx]      ; 将 data 段中的数据压入栈add bx, 2         ; 指向下一个 wordloop push_loop    ; 循环 8 次,压入所有数据mov bx, 0         ; 重新指向 data 段起始位置mov cx, 8         ; 重新计数 8 次; ====== 从栈中依次弹出数据,存入 data 段,实现逆序 ======
pop_loop:pop ds:[bx]       ; 从栈中弹出数据,存入 data 段add bx, 2         ; 指向下一个 word 存储位置loop pop_loop     ; 继续循环直到 8 个数据全部存回; ====== 程序结束 ======mov ax, 4c00h     ; 终止程序int 21hcode ends
end start

实例解释

现在,我们以一个具体的程序来再次讨论一下所谓的“代码段”、“数据段”、“栈段”。

我们在源程序中为这三个段起了具有含义的名称,用来存放数据的段我们将其命名为“data”,用来放代码的段我们将其命名为“code”,用来作栈空间的命名为“stack”。

但CPU看的懂这些名称吗? Absolutely not!!

我们在源程序中用伪指令    “assume cs:code,ds:data,ss:stack”

将cs、ds和ss分别和code、data、stack段相连。  

 这样做了之后,CPU是否就会将 cs指向     code,ds 指向 data,ss 指向stack,从而按照我们的意图来处理这些段呢?         Absolutely not!!

若要CPU按照我们的安排行事,就要用机器指令控制它,源程序中的汇编指令是CPU要执行的内容。

那么,CPU如何知道去执行它们?    

我们在源程序的最后用“end start”说明了程序的入口,这个入口将被写入可执行文件的描述信息,可执行文件中的程序被加载入内存后,CPU的CS:IP被设置指向这个入口,从而开始执行程序中的第一条指令。

标号“start”在“code”段中,这样CPU就将code段中的内容当作指令来执行了

我们在code段中,使用指令:  

mov ax,stack       mov ss,ax       mov sp,16

设置ss指向stack,设置ss:sp指向stack:16,

CPU 执行这些指令后,将把stack段当做栈空间来用。    

CPU若要访问data段中的数据,则可用 ds 指向 data 段,用其他的寄存器(如:bx)来存放 data段中数据的偏移地址。

总之,CPU到底如何处理我们定义的段中的内容,是当作指令执行,当作数据访问,还是当作栈空间,完全是靠程序中具体的汇编指令,和汇编指令对CS:IP、SS:SP、DS等寄存器的设置来决定的

总的来说,cpu只认识cs,ds,ss等有特殊含义的寄存器,比如cs指向的段会当成代码段,ds指向的段当成数据段,等等。

而我们将对应的内容存放到对应的段中,然后将这个段名(cpu会将这个名字解析成一个物理地址)复制给相应的寄存器,那么cpu就会正确地执行我们想要的逻辑。

就像上面,我们将数据存储到了一个叫data的段中,然后将这个段赋值给ds,那么cpu就会知道这些是数据,将他们当成数据执行

笔记

6.1在代码段中使用数据
    1.dw的含义【定义字型数据:define word,16字节】
        在数据段中使用dw定义数据,则数据在数据段中
        在代码段中使用dw定义数据,则数据在代码段中
        堆栈段也是一样
    2.在程序的第一条指令前加一个标号start,并且这个标号在伪指令end后面出现
        可以通知编译器程序在什么地方结束,并且也可以通知编译器程序的入口在哪里
6.2在代码段中使用栈
    **补充:如果题目要求【逆序】存放,就要想到栈(FILO)
    使用dw向系统申请一段空间,然后把这个空间当做栈
6.3将数据、代码、栈放入不同的段
    1.在前面的6.1和6.2中,我们在程序中用到了数据和栈,我们在编程的时候要注意
        何处是数据,何处是栈、何处是代码
    2.这样做显然有两个问题
        1.把他们放在一个段中是程序显得混乱
        2.前面程序中处理的数据很少,用到的栈空间也小,放在一个段里面没有问题
            但数据、栈、代码需要的空间超过64KB,就不能放在一个段中
            (8086中一个段的容量不能大于64KB)
    3.我们可以和定义代码段一样的方法来定义多个段
        然后在这些段里面定义需要的数据,或通过定义数据来取得栈空间
    4.将数据、代码、栈放入不同的段
        1.我们可以在源程序中为这三个段起具有含义的名称
            用来存放数据的段,我们将其命名为“data”
            用来存放代码的段,我们将其命名为“code”
            用来作栈空间的段,我们将其命名为“stack”
          但是CPU看得懂吗?【不能】
        2.我们在源程序中用伪指令
            “assume cs:code,ds:data,ss:stack”将cs、ds和ss分别和code、data、stack段相连
            这样做了之后,CPU是都就会将cs指向code,ds指向data,ss指向stack
              从而按照我们的意图来处理这些段呢?【不能】
              伪指令CPU看不懂,伪指令是给编译器看的
        3.若要CPU按照我们的安排行事,就要用机器指令控制它,源程序中的汇编指令
            才是CPU要执行的内容
            需在在code段中给DS,CS、SS设置相应的值才能让CPU识别出数据段、代码段、堆栈段
            其中汇编程序开始的地方(即代码段开始的地方)由end后面的标号所指向的地方给出
    5.assume指令不可省略,至于为什么,需要以后多多体会
 

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词