x86_64 ASM - maximum bytes for an instruction?

23,495

Solution 1

The x86 instruction set (16, 32 or 64 bit, all variants/modes) guarantees / requires that instructions are at most 15 bytes. Anything beyond that will give an "invalid opcode". You can't achieve that without using redundant prefixes (e.g. multiple 0x66 or 0x67 prefixes, for example).

The only instruction that actually takes 64-bits as a data item is the load constant to register (Intel syntax: mov reg, 12345678ABCDEF00h, at&t syntax: movabs $12345678ABCDEF00, %reg) - so if you wanted to jump more than 31 bits forward/backward, it would be a move of the target location into a register, and then call/jump to the register. Using 32-bit immediates and displacements (in relative jumps and addressing modes) saves four bytes on many instructions in 64-bit mode.

Solution 2

Questions is, what’s the longest possible instruction in the x86 instruction set?

Answer: you can form a valid x86 instruction with an infinite number of bytes!

That’s right, you could fill up an entire 64K ROM image with a single valid instruction. To be more specific, there is no limit to the length of 8086 instructions. Cool! Unfortunately, modern day i386 variants throw a general protection fault when attempting to decode instructions longer than 15 bytes.

So what does an infinitely-long-but-valid 8086 instruction look like? Kinda boring, actually. You could only form an infinitely long instruction by using redundant prefixes in front on the opcodes. Instruction prefixes are bytes pre-pended to the beginning of an instruction that can modify the default address size, data size, or segment registers used by an instruction.

For example, you can take the innocuous looking instruction:

89 E5              mov %sp,%bp

And turn it into a really long instruction:

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

Now that’s just evil.

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


Another long instruction without repeating prefixes

In some cases it is possible to encode valid instructions that exceed the traditional 15-byte length limit. For example:

  ; 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

Solution 3

From the Intel® 64 and IA-32 Architectures Software Developer’s Manual:

2.3.11 AVX Instruction Length

The maximum length of an Intel 64 and IA-32 instruction remains 15 bytes.

You can construct instructions that would encode to more than 15 bytes, but such instructions would be illegal and would probably not execute.

Share:
23,495
Johnny Pauling
Author by

Johnny Pauling

Updated on September 02, 2020

Comments

  • Johnny Pauling
    Johnny Pauling over 3 years

    What is the maximum number of bytes a complete instruction would require in x64 asm code?

    Something like a jump to address might occupy up to 9 bytes I suppose: FF 00 00 00 00 11 12 3F 1F but I don't know if that's the maximum number of bytes a x64 instruction can use

  • ughoavgfhw
    ughoavgfhw about 11 years
    There are also forms of mov which can take a full 64-bit address, those which take moffs's as a operand. But they can only move to/from the accumulator, so the maximum useful length for them is still only 11 bytes (8 for the address, 1 for the opcode, 1 for a 64- or 16-bit operand size, and 1 for a fs or gs segment override).
  • phuclv
    phuclv almost 9 years
    The instruction set imposed no limit on instruction length. The limit is defined by the instruction decoder
  • Peter Cordes
    Peter Cordes over 7 years
    The ISA for 386 and later does impose a 15-byte limit. 286 imposed a 10-byte limit. The "infinite" insn length thing only works on 8086, not x86 (or x86-64), not even a modern x86 CPU in real mode. The second half of your answer should say "otherwise-valid". You left out the bottom of that footnote, which says It is up to the user to avoid these cases (and the resulting #GP exception).
  • user2284570
    user2284570 over 7 years
    @LưuVĩnhPhúc : whith which assembler dos you assemblelwpins rax,[fs:eax+ebx+disp32],imm32? gnu as doesn’t recognize this.
  • fuz
    fuz over 6 years
    @LưuVĩnhPhúc You chose a particularly bad example as lwpins never made it into silicone. Though, I don't know af any other overly long instructions; VEX mitigated this problem pretty well.
  • Olsonist
    Olsonist about 6 years
    Just as an aside Computer Architecture A Quantitative Approach has said 17 and now in the 6th edition says 18 bytes (p. 14). Intel says 15 and I'm sticking with 15.
  • Peter Cordes
    Peter Cordes about 4 years
    @Olsonist: It is possible to invent cases where an instruction without any redundant or inapplicable prefixes could require more than 15 bytes to encode. Such instructions are not encodeable and do fault (tested on Skylake, Linux delivers SIGSEGV not SIGILL); you'll have to find another way to solve your problem, e.g. lea an address or mov an immediate into a register first. It's not easy to come up with real plausible cases, e.g. fs xacquire lock add qword [r8d + edx + 1234], 0x1234 would be 16 bytes if it were valid. (NASM and YASM both unfortunately assemble it without a warning).