【问题标题】:Storing data in segments with assembly使用程序集将数据存储在段中
【发布时间】:2010-12-09 09:17:05
【问题描述】:

我正在学习 x86 汇编语言,我了解段的用途和用法。分段保存重要数据,也可用于存储额外数据(即内存分段模型)。这是我的问题。如果段可用于存储额外数据,我如何确保我在其中存储的数据不会覆盖任何现有数据?

例如,CS 寄存器指向代码段。代码段包含程序的代码。如果我使用带有偏移量的 CS 寄存器来存储一些数据,我怎么知道将数据放在哪里以免覆盖它正在存储的代码?

请告诉我。我使用 Intel 语法汇编和 NASM 汇编。

谢谢

【问题讨论】:

    标签: assembly x86 segments


    【解决方案1】:

    Segments 从不存储任何数据。段寄存器只是“基”地址指针,用于仅使用 16 位寄存器创建 20 位指针。例如:

    MOV DS, 0001
    MOV DI, 0013
    MOV AL, DS:[DI]  ' this reads from address x00023 in memory
    
    MOV DS, 0002
    MOV DI, 0003
    MOV AL, DS:[DI]  ' this too reads from address x00023 in memory
    
    MOV DS, 0000
    MOV DI, 0023
    MOV AL, DS:[DI]  ' this too reads from address x00023 in memory
    

    至于你的问题,如何确保你不会用数据覆盖代码:这完全取决于你确保你确切地知道你在内存中存储代码和数据的位置!

    【讨论】:

    • 好的,感谢您的澄清。但是我怎么知道我的代码和数据在内存中的什么位置呢?
    • 我很抱歉,但我意识到当我输入这个时,一个完整的解释会太冗长了...... :-( 我只能说:继续学习。你可能会有一个深入研究这个概念的绝佳经验!
    • 顺便说一下,没有将立即值移动到段寄存器的指令。而不是 MOV DS, 1 您需要通过另一个寄存器,如 MOV AX、1 MOV DS、AX 或堆栈,如 PUSH 1 POP DS
    【解决方案2】:

    这是组装,所以你要对一切负责。将代码和数据分开就像分开两个数字一样简单。最多只使用每个内存位置一次。

    【讨论】:

      【解决方案3】:

      除了已经说过的,我想补充一点,您通常不希望在代码段中存储任何“数据”。这就是为什么你有一个数据段(由 DS 指向的基础)甚至是一个“额外的”数据段(-> ES)。显然,由于您的基本假设必须是代码段中的任何内容都将被执行,因此在此处写入随机数据值是非常不明智的。

      如果您必须在代码段中存储数据,请确保它永远不会被执行,如下所示:

      
      ..some code here..
      jmp AfterDataDeclaration
        db 12  ; declare some data here
      AfterDataDeclaration:
      ..some more code here..
      

      [edit:] 如果你想访问任何特定的数据,你总是需要一个参考点,你通常最方便地用一个标签来声明它。汇编器会让你象征性地访问它,而不必知道它的实际地址。

      您可能希望在代码段中写入内容的一种情况是,如果您想在其中修补机器代码(即自修改代码)。

      【讨论】:

      • 那么当你组装软件的时候,ES 里面是不是装满了东西,还是空着让我们乱来?
      • @QAH:设置段寄存器以指向任何有用的东西是您自己的责任。我不了解 NASM,而且我已经很久没有进行 16 位 MASM 汇编了。 IIRC,MASM 有“ASSUME”指令,它告诉汇编器为你设置段寄存器。
      【解决方案4】:

      正如他们已经提到的,段寄存器只保存一个 16 位指针。该指针在内部乘以 16,以便 CPU 可以寻址 20 位大地址存储空间。

      1) 如果您有足够的内存,您可以选择 64Kb 的 RAM 用于堆栈,64Kb 用于数据存储器,其余用于代码存储器。假设 SS(堆栈段寄存器)为 0x0400,DS(数据段寄存器)为 0x0800,CS(代码段寄存器)为 0x1B00。在这种情况下,您的代码不能覆盖任何其他内存段。如果您需要另外 64K 的数据内存,则可以使用 ES 段和 ES 前缀进行简单扩展。

      2) 如果您没有足够的内存空间(紧凑程序),则必须预测内存边界。

      3) 如果您的程序使用带有内存指针的外部调用,那么您必须检查边界。为此,在 x86 助记符中存在 BOUND 指令。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-12-26
        • 1970-01-01
        • 2019-01-17
        • 2012-06-04
        • 2014-12-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多