zoukankan      html  css  js  c++  java
  • 包含多个段的程序02 零基础入门学习汇编语言30

    第六章:包含多个段的程序02

     

    让编程改变世界

    Change the world by program


     

    在代码段中使用栈

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

    assume cs:codesg

    codesg segment

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

    ?

    code ends

    end

     

    程序思路

    程序的思路大致如下: 程序运行时,定义的数据存放在cs:0~cs:15单元中,共8个字单元。依次将这8个字单元中的数据入栈,然后再依次出栈到这8个字单元中,从而实现数据的逆序存放。 问题是,我们首先要有一段可当作栈的内存空间。如前所述,这段空间应该由系统来分配。 我们可以在程序中通过定义数据来取得一段空间,然后将这段空间当作栈空间来用。  

    程序6.3源码

    [codesyntax lang="asm"]
    assume cs:codesg
    codesg segment
            dw 0123H,0456H,0789H,0abcH,0defH,0fedH,0cbaH,0987H
            dw 0,0,0,0,0,0,0,0  ;用dw定义8个字型数据,在程序加载后,将取得8个字的
                                ;内存空间,存放这8个数据。我们在后面的程序中将这段
                                ;空间当作栈来使用。
    start:  mov ax,cs		
            mov ss,ax
            mov sp,32		    ;设置栈顶ss:sp指向cs:32
            mov bx,0
            mov cx,8
    s:      push cs:[bx]
            add bx,2
            loop s			    ;以上将代码段0~16单元中的8个字型数据依次入栈
    
            mov bx,0
            mov cx,8
    s0:     pop cs:[bx]
            add bx,2
            loop s0	            ;以上依次出栈8个字型数据到代码段0~16单元中
    
            mov ax,4c00h
            int 21h
    codesg ends
    
    end start			;指明程序的入口在start处
    [/codesyntax]   注意程序6.3中的指令:

    mov ax,cs

    mov ss,ax

    mov sp,32

    我们要讲 cs:16 ~ cs:31 的内存空间当作栈来用,初始状态下栈为空,所以 ss:sp要指向栈底,则设置ss:sp指向cs:32。 如果对这点还有疑惑,建议回头认真复习一下第三章。   比如对于:dw 0123H,0456H,0789H,0abcH,0defH,0fedH,0cbaH,0987H 我们可以说,定义了8个字型数据。 也可以说,开辟了8个字的内存空间,这段空间中每个字单元中的数据依次是: 0123H,0456H,0789H,0abcH,0defH,0fedH,0cbaH,0987H。 因为它们最终的效果是一样的。  

    检测点6.1

     

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

    在前面的内容中,我们在程序中用到了数据和栈,我们将数据、栈和代码都放到了一个段里面。我们在编程的时候要注意何处是数据,何处栈,何处是代码。  

    这样做显然有两个问题:

    (1)把它们放到一个段中使程序显得混乱; (2)前面程序中处理的数据很少,用到的栈空间也小,加上没有多长的代码,放到一个段里面没有问题。 但如果数据、栈和代码需要的空间超过64KB,就不能放在一个段中(一个段的容量不能大于64 KB,是我们在学习中所用的8086模式的限制,并不是所有的处理器都这样)。所以,我们应该考虑用多个段来存放数据、代码和栈。  

    怎样做呢?

    我们用和定义代码段一样的方法来定义多个段,然后在这些段里面定义需要的数据,或通过定义数据来取得栈空间。 具体做法如程序6.4所示,这个程序实现了和程序6.3 一样的功能,不同之处在于它将数据、栈和代码放到了不同的段中。 程序6.4源码 (点击下载)   程序中“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 ds,data”中的“data”,将被编译器处理为一个表示段地址的数值。 “代码段”、“数据段”、“栈段”完全是我们的安排。 现在,我们以一个具体的程序来再次讨论一下所谓的“代码段”、“数据段”、“栈段”。看程序6.4!!   一、我们在源程序中为这三个段起了具有含义的名称,用来存放数据的段我们将其命名为“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等寄存器的设置来决定的。 我们完全可以将程序6.4写成这样,实现同样的功能。   程序6.4源码2(点击下载) [buy] 获得所有教学视频、课件、源代码等资源打包 [/buy] [Downlink href='http://kuai.xunlei.com/d/LQPZWGODVKYV']视频下载[/Downlink]
  • 相关阅读:
    Combine 框架,从0到1 —— 4.在 Combine 中使用计时器
    Combine 框架,从0到1 —— 4.在 Combine 中使用通知
    Combine 框架,从0到1 —— 3.使用 Subscriber 控制发布速度
    Combine 框架,从0到1 —— 2.通过 ConnectablePublisher 控制何时发布
    使用 Swift Package Manager 集成依赖库
    iOS 高效灵活地配置可复用视图组件的主题
    构建个人博客网站(基于Python Flask)
    Swift dynamic关键字
    Swift @objcMembers
    仅用递归函数操作逆序一个栈(Swift 4)
  • 原文地址:https://www.cnblogs.com/LoveFishC/p/3846987.html
Copyright © 2011-2022 走看看