为什么在x64中某些操作码无效(例如06、07 ),而在x86中则用于相当基本的指令(06和07是push和pop)?我认为这些最简单的指令在这两种架构中都会做得很好。
为什么他们在x64中禁用了一些简单的指令?为什么它们不起作用?当他们可以将操作码分配给x64版本的指令时,他们为什么会禁用一些操作码,在操作码列表中创建漏洞?
参考资料:
http://ref.x86asm.net/coder32.html
http://ref.x86asm.net/coder64.html
发布于 2015-06-19 12:48:14
32位模式下的06和07操作码是指令PUSH ES和POP ES.在64位模式下,段寄存器CS、DS、ES和SS不再用于确定内存地址:处理器的基址为0,没有大小限制。由于现在应用程序(操作系统本身除外)通常没有理由访问这些寄存器,因此删除了用于更改和访问这些寄存器的push/pop操作码,只留下了mov到/从Sreg (这只是两个总的操作码;寄存器号以ModRM字节而不是1字节操作码的一部分)。对于几乎从来不需要的东西来说,这是完全足够的。
FS和GS段寄存器仍然可以在64位模式下设置基本地址,因此与它们相关的push和pop操作码还没有被删除。(这些2字节0F xx操作码是在386中添加的,与旧的1字节操作码相比,对于8086段寄存器来说,它是一个不那么有价值的部分)。
然而,段寄存器的Push/pop或mov并不是OSes通常设置FS或GS段基的方式:这将需要GDT或LDT条目,并且只能在低32位内设置基。64位OSes将使用相关的MSR直接读取和写入基,而不是体系结构寄存器。(现代32位OSes也是这样做的,除非运行在不支持段基MSR的旧硬件上。)
发布于 2015-06-19 15:59:18
对于所有CPU,都有类似于“操作码空间”的东西。例如,如果一个CPU使用8位操作码,那么就会有一个最大值.它应该有256条指令。操作码越大,可以得到的操作代码就越多,但是快速获取和解码它们就越困难。
80x86是一个相对较老的体系结构。它开始于一个小的操作码空间,主要由1字节和2字节的操作码组成.每次CPU制造商添加新功能时,都会从操作码空间中获取更多的操作码。他们没有密码了。他们很快就跑出去了。
为了解决这个问题,他们开始做一些事情,比如添加转义码和前缀来人为地扩展操作码空间。例如,对于最近的AVX指令,您将看到一个VEX前缀,后面是一个旧的/回收转义代码(例如0xF0),后面是一个旧的/可回收的地址/操作数大小前缀(例如0x66),后面是另一个4个字节。不是很漂亮。
同时,现在很少使用的旧指令(AAD、AAM等)和具有多个/冗余操作码(INC/DEC)的指令正在消耗宝贵的“1字节”操作码。由于向后兼容性,这些不能/不能完全删除。
然而,当设计64位时,根本就没有任何64位代码可以兼容-向后兼容性并不重要。由“不太重要”的指令消耗的1字节操作码可以回收;使这些指令在64位代码中无效(但释放一些有价值的1字节操作码)。
这些1字节操作码中的大多数(如果我记得正确的话,整个1字节的INC/DEC组)立即被回收,用于支持64位操作数所需的REX前缀。有些是“将来的扩展是免费的”(限制是扩展只能在64位代码中工作,因为这些指令在16位和32位代码中仍然有效)。
https://stackoverflow.com/questions/30938318
复制相似问题