5

有人可以解释这三个指令的功能吗?

  ORG 1000H 
  MOV AX,CS
  MOV DS,AX

我知道理论上的代码、数据和额外段是什么,但是:

  1. 它们是如何在这个程序中实现的?

  2. 为什么整个段移动到另一个段?(MOV AX,CSMOV DS,AX)

这两条指令实际上是做什么的?

我可以理解这段代码中所有其他指令的含义,除了突出显示的 3 条指令。

(程序运行良好。它接受输入直到 0 被击中——有 amov ah,01h和 an int 21h,然后它比较al'0'如果al'0',它跳到last,否则它跳到back。)

    ASSUME CS:CODE        
    CODE SEGMENT 
    ORG 1000H
    MOV AX,CS
    MOV DS,AX
BACK:
    MOV AH,01H
    INT 21H
    CMP AL,'0'
    JZ LAST
    JMP BACK
LAST:
    MOV AX,4C00H
    INT 21H
    CODE ENDS

    END

(编者注:.com程序在 offset 加载100h,所有段寄存器设置为彼此相等。 org 1000h可能是错字,org 100h因为这看起来像一个.com程序。这个程序不会中断,因为它不使用任何绝对地址,只使用相对地址跳跃。)

4

3 回答 3

12

要真正解释这个概念,我们必须支持段的基本概念,以及 x86 如何使用它们(在实模式下)。

8086 有 20 位寻址,但只有 16 位寄存器。为了生成 20 位地址,它将段与偏移量组合在一起。段必须在段寄存器(CS、DS、ES 或 SS)中。然后,您生成一个偏移量(作为立即值,或另一个或两个寄存器的内容。

因此,要生成地址,需要将 16 位段寄存器左移 4 位,然后将某个其他寄存器中的 16 位偏移量添加到该地址中,然后将总和实际用作地址。大多数指令都有一个附加到它们的默认段 -push并且pop任何相关的都bp将使用ss。跳跃之类的使用cs。一些字符串指令es(例如scans)和一些使用使用两个段——例如,将movsd数据从 复制[ds:si][es:di]。大多数其他指令使用ds. 您还可以使用段覆盖来显式指定地址,例如es:bx.

在任何情况下,在您可以有意义地使用段寄存器之前,您首先必须使用您关心的数据的地址(前 16 位)加载它。一个典型的“小模型”程序会从以下内容开始:

mov ax, @Data
mov ds, ax

在微型模型中,您对数据和代码使用相同的段。为了确保它引用了正确的段,您需要从 CS 获取 16 位并将其复制到 DS。正如许多其他人所提到的,没有将 CS 直接移动到 DS 的指令。问题提到了一种可能性;另一个常见的是:

push cs
pop ds
于 2011-03-19T20:54:39.663 回答
8

ORG 1000H 告诉汇编器后面的代码应该放在代码映像中的偏移量 1000H 处。

其他两条指令将 CS 复制到 DS。它不是复制段本身,只是更新指向数据段的指针。对于小程序(<64K),静态数据(源中的字符串文字,间接跳转表)可能与代码一起放在同一段中。在访问静态数据之前,需要在 DS 中加载段基指针。加载程序(操作系统的一部分,将程序从磁盘读取到内存并开始运行)必须设置 CS 以便它可以运行程序,但可能不设置 DS,因此程序在启动时将 CS 复制到 DS。

需要这两个指令序列,因为“MOV DS,CS”不是合法的 8086 指令。

于 2011-03-19T19:24:41.183 回答
1

你不能做

MOV DS, CS

这是一个无效的操作(masm 32: error A2070: invalid instruction operands)。

MOV AX, CS
MOV DS, AX

这两条指令执行相同mov ds, cs(这是无效的)。这样,汇编程序就很高兴并且不会抱怨。但是我不能告诉你为什么程序员要数据段和代码段一样

于 2011-03-19T19:15:31.130 回答