【问题标题】:Why does the mov instruction have use ax instead of two segment registers directly?为什么 mov 指令直接使用 ax 而不是两个段寄存器?
【发布时间】:2010-10-30 00:13:46
【问题描述】:

我看到如下代码:

mov ax, cs
mov ds, ax
mov es, ax

为什么我不能把它压缩成:

mov ds, cs
mov es, cs

自从使用累加器寄存器以来,第一种方法是否更快?但这似乎并不直观,因为 cs 和 ds 是段寄存器。还是有一些我不知道的限制?

顺便说一句,我正在使用 nasm。

【问题讨论】:

    标签: assembly x86 nasm accumulator addressing-mode


    【解决方案1】:

    你不能将段寄存器移动到段寄存器——没有指令。

    【讨论】:

    • 当我第一次看到你的回复时我不相信你,但是在 NASM 的文档中,果然没有 mov reg_dseg, reg_cseg 指令。
    • 这不是原因,而是结果。
    • 什么?我不明白尼尔的意思。
    • 问问自己为什么 x86 没有这些特定的说明。
    • @Neil - 实际上这“为什么书籍作者不使用 mov ds,cs?”的答案。更具体地说,他的问题是“有一些我不知道的限制吗?”然而,下一个自然的问题将是“wtf,为什么不呢?”所以你的回答在那里很有帮助。
    【解决方案2】:

    处理器中用于所有指令的微码只有这么多空间。因此,对于很少使用的操作湖更改段寄存器,通常首选一条通用指令而不是几条专用指令。此外,对于某些处理器,指令的数量绝对受架构的限制——例如,最初的 8080 处理器被限制为 256 条指令,因为它们都必须将操作码编码在一个字节中。

    【讨论】:

    • 机器码中的编码空间也是8086的一个问题。想必他们想为以后的扩展留出空间。除了微码空间之外,解码器硬件也很复杂,以支持解码更多不同的操作码。 (除非 8086 解码本身是由微码完成的?IDK)。但是,是的,为一条很少使用的指令花费一个操作码(当它被使用时)只节省 1 条 2 字节指令,而替代方案是不值得的。
    【解决方案3】:

    查看Intel Manual Volume 2 Instruction Set Reference - 325383-056US September 2015“MOV 移动”列“指令”。

    寄存器的唯一 16 位 mov 编码为:

    mov r/m16, Sreg
    

    以及《3.1.1.3 操作码汇总表中的指令列》解释:

    • r/m16 — 用于指令的字通用寄存器或内存操作数,其操作数大小 属性为 16 位。通用寄存器一词有:AX、CX、DX、BX、SP、BP、SI、DI。
    • Sreg — 段寄存器。

    因此mov ds, cs 不可编码,因为没有mov Sreg, Sreg 版本。

    【讨论】:

      【解决方案4】:

      实际上阻止这些操作的不是汇编语言,而是底层机器语言。

      虽然汇编由易于阅读的单词或助记符组成,但它们实际上非常直接地表示机器代码的 1 和 0。在 x86 CPU 上,每条指令通常由一系列字节组成,其中各个字节甚至是字节中的位都有意义。某些位代表指令,其他位代表addressing mode。在诸如您的示例之类的寄存器寻址模式中,一些位表示将哪些特定寄存器用作mov 指令的源和目标。

      现在,x86 系列处理器可以追溯到 1970 年代,当时 CPU 架构更简单。在那些日子里,accumulator 的概念非常重要——ax 是 16 位 x86 累加器。所有计算都在此寄存器中建立或“累积”,因此可用于所有指令。其他通用寄存器的使用范围更有限。

      因为指令是基于字节的,您希望尽可能少的字节来表示一条指令,以保持指令解码的快速。为了使指令尽可能短,累加器的使用成为中心。

      在摩托罗拉 680x0 等更现代的 CPU 上,更多通用寄存器具有更多以前属于累加器领域的功能。在 RISC CPU 上,所有寄存器都像累加器一样灵活。我听说在 64 位模式下,当前的 x86/amd64 指令集现在受到的限制要少得多。

      【讨论】:

      • 直到 x86_64 才能像这样使用寄存器。由于 32 位 x86,大多数寄存器或多或少都可以用作通用寄存器
      • 看来我没有意识到问题是关于段寄存器和累加器的。我从来没有进入过 x86 程序集,因为内存的工作方式很糟糕,但是后来使用了段寄存器和其他东西。我相信现在有了一个很好的平面内存模型,工作起来会更好。
      • 虽然 x86 汇编我也不怎么做。但是在 x86 上仍然有段指令。 x86 的地址空间不平坦
      • 比这更复杂。几代人都添加了各种模式,各种操作系统并不总是使用当时最强大的可用模式。 x86 CPU 为向后兼容保留了大量内容。如今,在现代操作系统上,您无需担心分段。这就是我所说的“平面内存模型”。我不知道这些天段寄存器使用了多少,或者它们是否有必要,或者它们现在是否只是保留旧名称的通用寄存器......
      • 你的第一段很扎实,但其余的很粗略。 mov r/m, Sreg and mov Sreg, r/m 可以使用任何 GP 整数寄存器或寻址模式作为非 Sreg 操作数。它们不仅限于 AX。一般来说,即使是 8086 也可以使用与 add ax, cx 相同的操作码来执行 add bx, cx 之类的操作,只是在对操作数进行编码的 ModRM 字节中的不同目的地。 x86 不是累加器机器。 AX 对于 8086 上的某些操作是特殊的,但不是最基本的 ALU 东西。 (与 8080 不同,A 更特别)。 386 让 AX 变得不那么特别了
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-11-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-04
      • 1970-01-01
      • 2011-10-25
      相关资源
      最近更新 更多