对具有自己的操作码的寄存器 EAX 进行操作的意义是什么?
What is the significance of operations on the register EAX having their own opcodes?
如果您查看 cmp
, test
, add
, sub
, and and
等操作的文档,您会注意到涉及寄存器 EAX
及其 16 位和 8 位变体作为第一个操作数的操作具有不同的操作码来自这些说明的“一般情况”版本。
这个单独的操作码仅仅是一种保存代码的方法吗space,它是否比一般情况下的操作码更有效,或者它只是过去的一些遗物,不值得摆脱出于兼容性原因?
这主要是过去的遗物,但也不完全是“过时的”。
早期(即,在Intel 8088), the x86 register set was actually much more specialized, like other contemporary CISC processors. (The 8088's design was itself descended directly from the Intel 8080 and Zilog Z80处理器上。)也就是说,8个寄存器并不像它们一样都是通用的(功能上) 是今天。有许多指令仅适用于硬编码寄存器。这意味着程序员经常发现自己在寄存器之间来回洗牌,以便为下一条指令正确设置。
EAX 是一个特别特殊的寄存器。好吧,实际上,在那些日子里,它被称为 AX,因为它只有 16 位并且还没有 E 扩展到 32 位。 AX 是 A 累加器,并被 lots 不同指令用作硬编码目的地。一个accumulator is the register where intermediate results are stored—it "accumulates" the results of logical and arithmetic operations. Nearly all early microprocessors had an accumulator register, and many of them forced you to use the accumulator in this way. The x86 architecture was in many cases more flexible, but it was still inspired by that design. A detailed write-up about the logic behind the x86 register set is here.
通用指令的这些特殊变体是该设计的结果。它们短(只有 1 个字节)、快速(主要是因为指令大小小,但大概在早期也有硅级别的优化)与累加器寄存器中的值交互的方式。
所以是的,这正是一种节省代码的方法 space,而且它仍然比一般情况下的编码更有效 因为 更少的字节需要对指令进行编码。当然,考虑到我们明显更大的指令高速缓存和更快的内存读取速度,小代码大小在今天并不像 8088 时那么重要,但它仍然有所作为。任何优秀的 x86 汇编程序员都知道尽可能使用这些基于累加器的短指令,许多编译器也这样做。这在内部循环中尤为重要,因为在内部循环中保持代码大小对于确保所有内容都保留在缓存中至关重要。寄存器使用甚至代码流经常被仔细地重新评估和重新安排,以尽可能多地保留累加器中的东西——即使在今天——正是为了能够使用这些简短、高效的操作码。
另请参阅:Peter Cordes's excellent "Tips for golfing in x86/x64 machine code",其中包含有关短格式编码的更多具体细节。
如果您查看 cmp
, test
, add
, sub
, and and
等操作的文档,您会注意到涉及寄存器 EAX
及其 16 位和 8 位变体作为第一个操作数的操作具有不同的操作码来自这些说明的“一般情况”版本。
这个单独的操作码仅仅是一种保存代码的方法吗space,它是否比一般情况下的操作码更有效,或者它只是过去的一些遗物,不值得摆脱出于兼容性原因?
这主要是过去的遗物,但也不完全是“过时的”。
早期(即,在Intel 8088), the x86 register set was actually much more specialized, like other contemporary CISC processors. (The 8088's design was itself descended directly from the Intel 8080 and Zilog Z80处理器上。)也就是说,8个寄存器并不像它们一样都是通用的(功能上) 是今天。有许多指令仅适用于硬编码寄存器。这意味着程序员经常发现自己在寄存器之间来回洗牌,以便为下一条指令正确设置。
EAX 是一个特别特殊的寄存器。好吧,实际上,在那些日子里,它被称为 AX,因为它只有 16 位并且还没有 E 扩展到 32 位。 AX 是 A 累加器,并被 lots 不同指令用作硬编码目的地。一个accumulator is the register where intermediate results are stored—it "accumulates" the results of logical and arithmetic operations. Nearly all early microprocessors had an accumulator register, and many of them forced you to use the accumulator in this way. The x86 architecture was in many cases more flexible, but it was still inspired by that design. A detailed write-up about the logic behind the x86 register set is here.
通用指令的这些特殊变体是该设计的结果。它们短(只有 1 个字节)、快速(主要是因为指令大小小,但大概在早期也有硅级别的优化)与累加器寄存器中的值交互的方式。
所以是的,这正是一种节省代码的方法 space,而且它仍然比一般情况下的编码更有效 因为 更少的字节需要对指令进行编码。当然,考虑到我们明显更大的指令高速缓存和更快的内存读取速度,小代码大小在今天并不像 8088 时那么重要,但它仍然有所作为。任何优秀的 x86 汇编程序员都知道尽可能使用这些基于累加器的短指令,许多编译器也这样做。这在内部循环中尤为重要,因为在内部循环中保持代码大小对于确保所有内容都保留在缓存中至关重要。寄存器使用甚至代码流经常被仔细地重新评估和重新安排,以尽可能多地保留累加器中的东西——即使在今天——正是为了能够使用这些简短、高效的操作码。
另请参阅:Peter Cordes's excellent "Tips for golfing in x86/x64 machine code",其中包含有关短格式编码的更多具体细节。