汇编:为什么某些x86操作码在x64中无效?

时间:2015-06-19 12:36:31

标签: assembly x86 x86-64 opcode opcodes

我的问题来自一个简单的好奇心:

为什么在x64中某些操作码是无效的(例如06,07),而在x86中用于相当基本的指令(06和07是推送和弹出)?我认为那些最简单的指令在两种架构中都能很好地完成。

为什么他们在x64中禁用了一些简单的指令?为什么他们不工作? 为什么他们禁用某些操作码,在操作码列表中创建漏洞,何时可以将它们分配给x64版本的指令?

参考:

http://ref.x86asm.net/coder32.html

http://ref.x86asm.net/coder64.html

2 个答案:

答案 0 :(得分:8)

32位模式下的06和07操作码是PUSH ESPOP ES指令。在64位模式下,段寄存器CS,DS,ES和SS不再用于确定存储器地址:处理器假定基址为0且没有大小限制。由于现在通常没有理由让应用程序(操作系统本身除外)访问这些寄存器,因此删除了更改和访问它们的操作码。

FS和GS段寄存器仍然可以在64位模式下设置基址,因此与它们相关的操作码尚未被删除。

答案 1 :(得分:3)

对于所有CPU,有类似于"操作码空间"。例如,如果CPU使用8位操作码,那么它就是最大值。它可能有256条指令。较大的操作码是你可以拥有的操作码越多,但是更难以快速获取和解码它们。

80x86是一个相对较旧的架构。它始于一个适度的操作码空间,主要由1字节和2字节的操作码组成。每次CPU制造商添加新功能时,操作码空间都需要更多的操作码。他们没有操作码。他们跑得很快。

为了解决这个问题,他们开始做一些事情,例如添加转义码和前缀来人为地扩展操作码空间。例如,对于最近的AVX指令,您要查看VEX前缀,后跟旧的/回收转义码(例如0xF0),然后是旧的/再循环地址/操作数大小前缀(例如0x66),然后是另一个4字节。它不漂亮。

与此同时,现在很少使用的旧指令(AAD,AAM等)和带有多个/冗余操作码(INC / DEC)的指令消耗了宝贵的" 1字节&# 34;操作码。由于向后兼容性,这些无法完全删除。

然而;当设计64位时,根本没有任何64位代码兼容 - 向后兼容性并不重要。 "消耗的1字节操作码不是很重要"说明书可以回收;使这些指令在64位代码中无效(但释放了一些有价值的1字节操作码)。

大多数这些1字节操作码(如果我没记错的话,整个1字节的INC / DEC组)立即被回收用于支持64位操作数所需的REX前缀。有些人并没有因为未来的扩展而免费使用#34; (限制扩展只能在64位代码中工作,因为这些指令在16位和32位代码中仍然有效。)