6

我看到如下代码:

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

为什么我不能将其压缩为:

mov ds, cs
mov es, cs

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

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

4

4 回答 4

11

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

于 2009-05-29T20:52:52.223 回答
2

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

于 2009-05-29T20:54:29.757 回答
2

查看英特尔手册第 2 卷指令集参考 - 325383-056US 2015 年 9 月“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版本。

于 2015-10-31T20:19:18.110 回答
1

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

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

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

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

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

于 2011-05-09T09:00:46.537 回答