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]
  • 相关阅读:
    Redis分布式锁服务(转)
    redis分布式锁(转)
    MySQL+InnoDB semi-consitent read原理及实现分析(转)
    MySQL加锁处理分析(转)
    实战经验丨PHP反序列化漏洞总结
    脚本语言丨Batch入门教程第四章:调用与传参
    福利狂欢已开启,请做好准备!
    脚本语言丨Batch入门教程第三章:逻辑判断
    WinRAR存在严重的安全漏洞影响5亿用户
    Batch入门教程丨第二章:认识变量相关概念
  • 原文地址:https://www.cnblogs.com/LoveFishC/p/3846987.html
Copyright © 2011-2022 走看看