35

x64 asm 代码中一条完整指令需要的最大字节数是多少?

我想像跳转到地址之类的东西可能最多占用 9 个字节:FF 00 00 00 00 11 12 3F 1F但我不知道这是否是 x64 指令可以使用的最大字节数

4

3 回答 3

45

x86 指令集(16、32 或 64 位,所有变体/模式)保证/要求指令最多为 15 个字节。除此之外的任何东西都会给出“无效的操作码”。如果不使用冗余前缀(例如,多个 0x66 或 0x67 前缀),您将无法实现这一点。

实际上将 64 位作为数据项的唯一指令是要注册的加载常量(Intel 语法:mov reg, 12345678ABCDEF00h,at&t 语法:)movabs $12345678ABCDEF00, %reg- 因此,如果您想向前/向后跳转超过 31 位,这将是目标位置到寄存器中,然后调用/跳转到寄存器。使用 32 位立即数和位移(在相对跳转和寻址模式中)在 64 位模式下的许多指令中节省了四个字节。

于 2013-02-05T01:07:05.397 回答
31

问题是,x86 指令集中最长的指令是什么?

答:你可以用无限个字节组成一条有效的 x86 指令!

没错,您可以用一条有效指令填满整个 64K ROM 映像。更具体地说,8086 条指令的长度没有限制。凉爽的!不幸的是,现代 i386 变体在尝试解码超过 15 个字节的指令时会引发一般保护错误。

那么无限长但有效的 8086 指令是什么样的呢?有点无聊,其实。您只能通过在操作码前面使用冗余前缀来形成无限长的指令。指令前缀是附加在指令开头的字节,可以修改指令使用的默认地址大小、数据大小或段寄存器。

例如,您可以采用看起来无害的指令:

89 E5              mov %sp,%bp

并把它变成一个很长的指令:

66 66 66 66 … 66 66 89 E5                mov %sp,%bp

现在那只是邪恶的。

https://web.archive.org/web/20131109063453/https://www.onlinedisassembler.com/blog/?p=23


另一个没有重复前缀的长指令

在某些情况下,可以对超过传统 15 字节长度限制的有效指令进行编码。例如:

  ; 16-bit mode
  F2 F0 36 66 67 81 84 24 disp32 imm32 =  xaquire lock add [ss:esp*1+disp32],imm32
  F3 F0 36 66 67 81 84 24 disp32 imm32 = xrelease lock add [ss:esp*1+disp32],imm32

  ; 16-bit mode
  36 67 8F EA 78 12 84 24 disp32 imm32 = lwpins eax,[ss:esp*1+disp32],imm32
  36 67 8F EA 78 12 8C 24 disp32 imm32 = lwpval eax,[ss:esp*1+disp32],imm32
  36 67 8F EA 78 10 84 24 disp32 imm32 =  bextr eax,[ss:esp*1+disp32],imm32

  ; 64-bit mode
  64 67 8F EA F8 12 84 18 disp32 imm32 = lwpins rax,[fs:eax+ebx+disp32],imm32
  64 67 8F EA F8 12 8C 18 disp32 imm32 = lwpval rax,[fs:eax+ebx+disp32],imm32
  64 67 8F EA F8 10 84 18 disp32 imm32 =  bextr rax,[fs:eax+ebx+disp32],imm32

http://www.sandpile.org/x86/opc_enc.htm

于 2013-09-24T02:27:22.957 回答
23

来自英特尔® 64 和 IA-32 架构软件开发人员手册:

2.3.11 AVX 指令长度

Intel 64 和 IA-32 指令的最大长度仍为 15 个字节。

您可以构建编码超过 15 个字节的指令,但这样的指令是非法的并且可能不会执行。

于 2013-02-05T01:05:55.433 回答