# User-mode x86 + amd64 Cheatsheet ## Terminology - **IA-32**: - The official name for the 32-bit processor architecture made by Intel, commonly known as x86. - **x86**: - A more ubiquitous name for IA-32, but technically also includes older, 16-bit CPUs. - The name originated from Intel processors with this architecture having model numbers ending in 86, beginning with the Intel 8086. - Notable models include Intel 80186, 80286, 80386 and 80486, colloquially referred to as "186", "286", "386" and "486" respectively. - **i386**, **i686**: - Versions of the x86 architecture specific to the respective CPU models. For practical purposes synonymous to x86. - Often used in so called [target triples](https://wiki.osdev.org/Target_Triplet). - **amd64**: - A 64-bit extension of IA-32 developed by AMD. Today's predominant PC architecture. - **Intel® 64** (also **IA-32e**): - Intel's name for amd64. - **x86_64**, **x64**: - Aliases for amd64. Notably, `x86_64` is used in [target triples](https://wiki.osdev.org/Target_Triplet). --- ## Modes of operation - **Real address mode**: - The initial operating mode for any x86/amd64 CPU following a reset. - There is no paging in real-address mode, although segmentation can be used. - **Protected mode**: - The "standard" operating mode for 32-bit CPUs. On 32-bit systems, user apps and (usually) the OS operate here. - After processor reset (boot), the bootloader or early kernel initializes protected mode by setting up various control registers and structures in physical memory, such as an Interrupt Vector Table or a Global (segment) Descriptor Table. - Protected mode allows for paging and segmentation, although the latter is rarely used. - **IA-32e mode** (also **long mode**): - The extended mode available to 64-bit CPUs, with backwards compatibility with 32-bit code. - **64-bit mode**: - Fully 64-bit mode (addresses are 64 bits long, instruction operands up to 64 bits). - **Compatibility mode**: - Allows running 32-bit user applications within a long-mode enabled OS. - Addresses as 32-bit and operands are 32-bit by default. - Paging is mandatory in both compatibility and 64-bit mode. - **System management mode (SMM)**: - Enables (usually) the operating system to perform platform-specific actions (think power management, invoking BIOS functions, ...). - **Virtual-8086 mode**: - Practically of negligible importance. --- ## Basic program execution registers & data size terminology - A **byte** is an octet — a memory cell containing 8 binary digits. - A **word** is twice the size of a byte, i.e. a 16-bit cell. - A **doubleword** (also **dword**) is a 32-bit cell. - A **quadword** (also **qword**) is a 64-bit cell. - (An **xmmword** is a 128-bit cell.) ### General purpose registers **General purpose registers available in 32-bit mode:** | 32-bit register name | 16-bit register name | high 8-bit register name | low 8-bit register name | typical usage | | -------------------- | -------------------- | ------------------------ | ----------------------- | ------------------------ | | EAX | AX | AH | AL | return value | | EBX | BX | BH | BL | - | | ECX | CX | CH | CL | - | | EDX | DX | DH | DL | - | | EBP | BP | - | BPL | stack frame base pointer | | ESI | SI | - | SIL | copy source | | EDI | DI | - | DIL | copy destination | | ESP | SP | - | SPL | pointer to top of stack | **General purpose registers available in 64-bit mode:** | 64-bit register name | 32-bit register name | 16-bit register name | high 8-bit register name | low 8-bit register name | typical usage | | -------------------- | -------------------- | -------------------- | ------------------------ | ----------------------- | ------------------------ | | RAX | EAX | AX | AH | AL | return value | | RBX | EBX | BX | BH | BL | - | | RCX | ECX | CX | CH | CL | - | | RDX | EDX | DX | DH | DL | - | | RBP | EBP | BP | - | BPL | stack frame base pointer | | RSI | ESI | SI | - | SIL | copy source | | RDI | EDI | DI | - | DIL | copy destination | | RSP | ESP | SP | - | SPL | pointer to top of stack | | R8 | R8D | R8W | - | R8B | - | | R9 | R9D | R9W | - | R9B | - | | R10 | R10D | R10W | - | R10B | - | | R11 | R11D | R11W | - | R11B | - | | R12 | R12D | R12W | - | R12B | - | | R13 | R13D | R13W | - | R13B | - | | R14 | R14D | R14W | - | R14B | - | | R15 | R15D | R15W | - | R15B | - | ### Segment registers | Register name | Register size | Meaning | | ------------- | ------------- | ---------------------- | | CS | 16-bit | Code segment selector | | DS | 16-bit | Data segment selector | | SS | 16-bit | Stack segment selector | | ES | 16-bit | Data segment selector | | FS | 16-bit | Data segment selector | | GS | 16-bit | Data segment selector | **Segment registers in 64-bit mode (quote from the manual):** > In 64-bit mode: CS, DS, ES, SS are treated as if each segment base is 0, regardless of the value of the associated > segment descriptor base. This creates a flat address space for code, data, and stack. FS and GS are exceptions. > Both segment registers may be used as additional base registers in linear address calculations (in the addressing > of local data and certain operating system data structures). > Even though segmentation is generally disabled, segment register loads may cause the processor to perform > segment access assists. During these activities, enabled processors will still perform most of the legacy checks on > loaded values (even if the checks are not applicable in 64-bit mode). Such checks are needed because a segment > register loaded in 64-bit mode may be used by an application running in compatibility mode. > Limit checks for CS, DS, ES, SS, FS, and GS are disabled in 64-bit mode. ### Instruction pointer and status flags | 64-bit register name | 32-bit register name | Meaning | | -------------------- | -------------------- | ----------------------------------- | | RFLAGS | EFLAGS | Program Status and Control Register | | RIP | EIP | Instruction Pointer | **Status Flags in the EFLAGS/RFLAGS register:** | Bit number | Bit mask | Name | Shorthand | Meaning | | ---------- | -------- | -------------------- | --------- | -------------------------------------------------------------------------------------- | | 0 | 0x001 | Carry flag | CF | Did a carry occur? | | 2 | 0x004 | Parity flag | PF | Does the least-significant byte of the result contain an even number of 1 bits? | | 4 | 0x010 | Auxiliary Carry flag | AF | Did a carry or a borrow out of bit 3 of the result occur? (Used in decimal arithmetic) | | 6 | 0x040 | Zero flag | ZF | Is the result zero? | | 7 | 0x080 | Sign flag | SF | Is the (signed) result negative? | | 11 | 0x800 | Overflow flag | OF | Did an overflow occur? | ### Floating-point number registers todo --- ## Instruction encoding ### Opcodes, ModR/M and SIB bytes todo ### Prefixes | Prefix | Name | Description | | ------ | ----------------------------- | ----------------------- | | `F0` | LOCK | todo | | `F2` | BND, REPNE/REPNZ | see string instructions | | `F3` | REP, REPE/REPZ | see string instructions | | `2E` | CS segment override | todo | | `36` | SS segment override | todo | | `3E` | DS segment override | todo | | `26` | ES segment override | todo | | `64` | FS segment override | todo | | `65` | GS segment override | todo | | `66` | Operand-size override prefix | todo | | `67` | Address-size override prefix | todo | | `4?` | REX prefix (64-bit mode only) | todo | ### Data copying instructions #### MOV — Move **Encodings available in 32-bit mode:** | Opcode | Operands | Assembly | Description | | ------ | -------- | -------- | ----------- | **Encodings available in 64-bit mode:** | Opcode | Operands | Assembly | Description | | ----------------------------------------- | ----------------------- | -------------------------------------------------------------- | -------------------- | | todo | | | | | | | | | | `C6 0[0???] ??`\*\* | R/M != \{4, 5\}; imm8 | `mov byte ptr [r64], imm8` | Move imm8 to r/m8. | | `C6 04 ?[????] ??`\*\* | SIB, Base != 5; imm8 | `mov byte ptr [base_r64 + (index_r64*scale)], imm8` | Move imm8 to r/m8. | | `C6 04 ?[?101] ?? ?? ?? ?? ??`\*\* | SIB; disp32; imm8 | `mov byte ptr [(index_r64*scale) + disp32], imm8` | Move imm8 to r/m8. | | `C6 05 ?? ?? ?? ?? ??`\*\* | disp32; imm8 | `mov byte ptr [$ + 7 + disp32], imm8` | Move imm8 to r/m8. | | `C6 4[0???] ?? ??`\*\* | R/M != 4; disp8; imm8 | `mov byte ptr [r64 + disp8], imm8` | Move imm8 to r/m8. | | `C6 44 ?? ?? ??`\*\* | SIB; disp8; imm8 | `mov byte ptr [base_r64 + (index_r64*scale) + disp8], imm8` | Move imm8 to r/m8. | | `C6 8[0???] ?? ?? ?? ?? ??`\*\* | R/M != 4; disp32; imm8 | `mov byte ptr [r64 + disp32], imm8` | Move imm8 to r/m8. | | `C6 84 ?? ?? ?? ?? ?? ??`\*\* | SIB; disp32; imm8 | `mov byte ptr [base_r64 + (index_r64*scale) + disp32], imm8` | Move imm8 to r/m8. | | `C6 C[0???] ??`\*\* | R/M; imm8 | `mov r8, imm8` | Move imm8 to r/m8. | | | | | | | `66 C7 0[0???] ?? ??` | R/M != \{4, 5\}; imm16 | `mov word ptr [r64], imm16` | Move imm16 to r/m16. | | `66 C7 04 ?[????] ?? ??` | SIB, Base != 5; imm16 | `mov word ptr [base_r64 + (index_r64*scale)], imm16` | Move imm16 to r/m16. | | `66 C7 04 ?[?101] ?? ?? ?? ?? ?? ??` | SIB; disp32; imm16 | `mov word ptr [(index_r64*scale) + disp32], imm16` | Move imm16 to r/m16. | | `66 C7 05 ?? ?? ?? ?? ?? ??` | disp32; imm16 | `mov word ptr [$ + 11 + disp32], imm16` | Move imm16 to r/m16. | | `66 C7 4[0???] ?? ?? ??` | R/M != 4; disp8; imm16 | `mov word ptr [r64 + disp8], imm16` | Move imm16 to r/m16. | | `66 C7 44 ?? ?? ?? ??` | SIB; disp8; imm16 | `mov word ptr [base_r64 + (index_r64*scale) + disp8], imm16` | Move imm16 to r/m16. | | `66 C7 8[0???] ?? ?? ?? ?? ?? ??` | R/M != 4; disp32; imm16 | `mov word ptr [r64 + disp32], imm16` | Move imm16 to r/m16. | | `66 C7 84 ?? ?? ?? ?? ?? ?? ??` | SIB; disp32; imm16 | `mov word ptr [base_r64 + (index_r64*scale) + disp32], imm16` | Move imm16 to r/m16. | | `66 C7 C[0???] ?? ??` | R/M; imm16 | `mov r16, imm16` | Move imm16 to r/m16. | | | | | | | `C7 0[0???] ?? ?? ?? ??`\* | R/M != \{4, 5\}; imm32 | `mov dword ptr [r64], imm32` | Move imm32 to r/m32. | | `C7 04 ?[????] ?? ?? ?? ??`\* | SIB, Base != 5; imm32 | `mov dword ptr [base_r64 + (index_r64*scale)], imm32` | Move imm32 to r/m32. | | `C7 04 ?[?101] ?? ?? ?? ?? ?? ?? ?? ??`\* | SIB; disp32; imm32 | `mov dword ptr [(index_r64*scale) + disp32], imm32` | Move imm32 to r/m32. | | `C7 05 ?? ?? ?? ?? ?? ?? ?? ??`\* | disp32; imm32 | `mov dword ptr [$ + 11 + disp32], imm32` | Move imm32 to r/m32. | | `C7 4[0???] ?? ?? ?? ?? ??`\* | R/M != 4; disp8; imm32 | `mov dword ptr [r64 + disp8], imm32` | Move imm32 to r/m32. | | `C7 44 ?? ?? ?? ?? ?? ??`\* | SIB; disp8; imm32 | `mov dword ptr [base_r64 + (index_r64*scale) + disp8], imm32` | Move imm32 to r/m32. | | `C7 8[0???] ?? ?? ?? ?? ?? ?? ?? ??`\* | R/M != 4; disp32; imm32 | `mov dword ptr [r64 + disp32], imm32` | Move imm32 to r/m32. | | `C7 84 ?? ?? ?? ?? ?? ?? ?? ?? ??`\* | SIB; disp32; imm32 | `mov dword ptr [base_r64 + (index_r64*scale) + disp32], imm32` | Move imm32 to r/m32. | | `C7 C[0???] ?? ?? ?? ??`\* | R/M; imm32 | `mov r64, imm32` | Move imm32 to r/m32. | \*: The REX.W prefix (`4[1???]`) can be used to change the destination operand to 64-bits, i.e. a 64-bit register or a `qword ptr` location. In this situation, the imm32 value is sign-extended to 64 bits. \*\* The REX prefix (`4?`) can be used, e.g. to access additional registers not available in 32-bit mode. #### MOVZX — Move With Zero-Extension **Encodings available in both 32-bit and 64-bit mode:** | Opcode | Operands | Assembly (32-bit) | Assembly (64-bit) | Description | | -------------------------------------------- | --------------------- | ----------------------------------------------------------- | ----------------------------------------------------------- | -------------------------------------------- | | `0F B6 [00 ??? ???]`\* | Reg, R/M != \{4, 5\} | `movzx r32, byte ptr [r32]` | `movzx r32, byte ptr [r64]` | Move byte to doubleword with zero-extension. | | `0F B6 [00 ??? 100] ?[????]`\* | Reg; SIB, Base != 5 | `movzx r32, byte ptr [base_r32 + index_r32*scale]` | `movzx r32, byte ptr [base_r64 + index_r64*scale]` | Move byte to doubleword with zero-extension. | | `0F B6 [00 ??? 100] ?[?101] ?? ?? ?? ??`\* | Reg; SIB; disp32 | `movzx r32, byte ptr [index_r32*scale + disp32]` | `movzx r32, byte ptr [index_r64*scale + disp32]` | Move byte to doubleword with zero-extension. | | `0F B6 [00 ??? 101] ?? ?? ?? ??`\* | Reg; disp32 | `movzx r32, byte ptr ds:disp32` | `movzx r32, byte ptr [$ + 7 + disp32]`\* | Move byte to doubleword with zero-extension. | | `0F B6 [01 ??? ???] ??`\* | Reg, R/M != 4; disp8 | `movzx r32, byte ptr [r32 + disp8]` | `movzx r32, byte ptr [r64 + disp8]` | Move byte to doubleword with zero-extension. | | `0F B6 [01 ??? 100] ?? ??`\* | Reg; SIB; disp8 | `movzx r32, byte ptr [base_r32 + index_r32*scale + disp8]` | `movzx r32, byte ptr [base_r64 + index_r64*scale + disp8]` | Move byte to doubleword with zero-extension. | | `0F B6 [10 ??? ???] ?? ?? ?? ??`\* | Reg, R/M != 4; disp32 | `movzx r32, byte ptr [r32 + disp32]` | `movzx r32, byte ptr [r64 + disp32]` | Move byte to doubleword with zero-extension. | | `0F B6 [10 ??? 100] ?? ?? ?? ?? ??`\* | Reg; SIB; disp32 | `movzx r32, byte ptr [base_r32 + index_r32*scale + disp32]` | `movzx r32, byte ptr [base_r64 + index_r64*scale + disp32]` | Move byte to doubleword with zero-extension. | | `0F B6 [11 ??? ???]`\* | Reg, R/M | `movzx r32, r8` | `movzx r32, r8` | Move byte to doubleword with zero-extension. | | | | | | | | `0F B7 [00 ??? ???]`\*\* | Reg, R/M != \{4, 5\} | `movzx r32, word ptr [r32]` | `movzx r32, word ptr [r64]` | Move word to doubleword with zero-extension. | | `0F B7 [00 ??? 100] ?[????]`\*\* | Reg; SIB, Base != 5 | `movzx r32, word ptr [base_r32 + index_r32*scale]` | `movzx r32, word ptr [base_r64 + index_r64*scale]` | Move word to doubleword with zero-extension. | | `0F B7 [00 ??? 100] ?[?101] ?? ?? ?? ??`\*\* | Reg; SIB; disp32 | `movzx r32, word ptr [index_r32*scale + disp32]` | `movzx r32, word ptr [index_r64*scale + disp32]` | Move word to doubleword with zero-extension. | | `0F B7 [00 ??? 101] ?? ?? ?? ??`\*\* | Reg; disp32 | `movzx r32, word ptr ds:disp32` | `movzx r32, word ptr [$ + 7 + disp32]`\* | Move word to doubleword with zero-extension. | | `0F B7 [01 ??? ???] ??`\*\* | Reg, R/M != 4; disp8 | `movzx r32, word ptr [r32 + disp8]` | `movzx r32, word ptr [r64 + disp8]` | Move word to doubleword with zero-extension. | | `0F B7 [01 ??? 100] ?? ??`\*\* | Reg; SIB; disp8 | `movzx r32, word ptr [base_r32 + index_r32*scale + disp8]` | `movzx r32, word ptr [base_r64 + index_r64*scale + disp8]` | Move word to doubleword with zero-extension. | | `0F B7 [10 ??? ???] ?? ?? ?? ??`\*\* | Reg, R/M != 4; disp32 | `movzx r32, word ptr [r32 + disp32]` | `movzx r32, word ptr [r64 + disp32]` | Move word to doubleword with zero-extension. | | `0F B7 [10 ??? 100] ?? ?? ?? ?? ??`\*\* | Reg; SIB; disp32 | `movzx r32, word ptr [base_r32 + index_r32*scale + disp32]` | `movzx r32, word ptr [base_r64 + index_r64*scale + disp32]` | Move word to doubleword with zero-extension. | | `0F B7 [11 ??? ???]`\*\* | Reg, R/M | `movzx r32, r16` | `movzx r32, r16` | Move word to doubleword with zero-extension. | \* `66` applicable; REX.W applicable in 64-bit mode (applies to dest register); note: using a prefix increases the instruction length and influences RIP-relative addressing! \*\* REX.W applicable in 64-bit mode (applies to dest register) **Encodings available in 32-bit mode only:** todo (pain) #### MOVSX — Move With Sign-Extension **Encodings available in both 32-bit and 64-bit modes:** | Opcode | Operands | Assembly (32-bit) | Assembly (64-bit) | Description | | ------------------------------------------ | --------------------- | ----------------------------------------------------------- | ----------------------------------------------------------- | -------------------------------------------- | | `0F BE [00 ??? ???]`\* | Reg, R/M != \{4, 5\} | `movsx r32, byte ptr [r32]` | `movsx r32, byte ptr [r64]` | Move byte to doubleword with sign-extension. | | `0F BE [00 ??? 100] ?[????]`\* | Reg; SIB, Base != 5 | `movsx r32, byte ptr [base_r32 + index_r32*scale]` | `movsx r32, byte ptr [base_r64 + index_r64*scale]` | Move byte to doubleword with sign-extension. | | `0F BE [00 ??? 100] ?[?101] ?? ?? ?? ??`\* | Reg; SIB; disp32 | `movsx r32, byte ptr [index_r32*scale + disp32]` | `movsx r32, byte ptr [index_r64*scale + disp32]` | Move byte to doubleword with sign-extension. | | `0F BE [00 ??? 101] ?? ?? ?? ??`\* | Reg; disp32 | `movsx r32, byte ptr ds:disp32` | `movsx r32, byte ptr [$ + 7 + disp32]`\* | Move byte to doubleword with sign-extension. | | `0F BE [01 ??? ???] ??`\* | Reg, R/M != 4; disp8 | `movsx r32, byte ptr [r32 + disp8]` | `movsx r32, byte ptr [r64 + disp8]` | Move byte to doubleword with sign-extension. | | `0F BE [01 ??? 100] ?? ??`\* | Reg; SIB; disp8 | `movsx r32, byte ptr [base_r32 + index_r32*scale + disp8]` | `movsx r32, byte ptr [base_r64 + index_r64*scale + disp8]` | Move byte to doubleword with sign-extension. | | `0F BE [10 ??? ???] ?? ?? ?? ??`\* | Reg, R/M != 4; disp32 | `movsx r32, byte ptr [r32 + disp32]` | `movsx r32, byte ptr [r64 + disp32]` | Move byte to doubleword with sign-extension. | | `0F BE [10 ??? 100] ?? ?? ?? ?? ??`\* | Reg; SIB; disp32 | `movsx r32, byte ptr [base_r32 + index_r32*scale + disp32]` | `movsx r32, byte ptr [base_r64 + index_r64*scale + disp32]` | Move byte to doubleword with sign-extension. | | `0F BE [11 ??? ???]`\* | Reg, R/M | `movsx r32, r8` | `movsx r32, r8` | Move byte to doubleword with sign-extension. | | | | | | | | `0F BF [00 ??? ???]`\*\* | Reg, R/M != \{4, 5\} | `movsx r32, word ptr [r32]` | `movsx r32, word ptr [r64]` | Move word to doubleword with sign-extension. | | `0F BF [00 ??? 100] ?[????]`\*\* | Reg; SIB, Base != 5 | `movsx r32, word ptr [base_r32 + index_r32*scale]` | `movsx r32, word ptr [base_r64 + index_r64*scale]` | Move word to doubleword with sign-extension. | | `0F BF [00 ??? 100] ?[?101]`\*\* | Reg; SIB; disp32 | `movsx r32, word ptr [index_r32*scale + disp32]` | `movsx r32, word ptr [index_r64*scale + disp32]` | Move word to doubleword with sign-extension. | | `0F BF [00 ??? 101] ?? ?? ?? ??`\*\* | Reg; disp32 | `movsx r32, word ptr ds:disp32` | `movsx r32, word ptr [$ + 7 + disp32]`\* | Move word to doubleword with sign-extension. | | `0F BF [01 ??? ???] ??`\*\* | Reg, R/M != 4; disp8 | `movsx r32, word ptr [r32 + disp8]` | `movsx r32, word ptr [r64 + disp8]` | Move word to doubleword with sign-extension. | | `0F BF [01 ??? 100] ?? ??`\*\* | Reg; SIB; disp8 | `movsx r32, word ptr [base_r32 + index_r32*scale + disp8]` | `movsx r32, word ptr [base_r64 + index_r64*scale + disp8]` | Move word to doubleword with sign-extension. | | `0F BF [10 ??? ???] ?? ?? ?? ??`\*\* | Reg, R/M != 4; disp32 | `movsx r32, word ptr [r32 + disp32]` | `movsx r32, word ptr [r64 + disp32]` | Move word to doubleword with sign-extension. | | `0F BF [10 ??? 100] ?? ?? ?? ?? ??`\*\* | Reg; SIB; disp32 | `movsx r32, word ptr [base_r32 + index_r32*scale + disp32]` | `movsx r32, word ptr [base_r64 + index_r64*scale + disp32]` | Move word to doubleword with sign-extension. | | `0F BF [11 ??? ???]`\*\* | Reg, R/M | `movsx r32, r8` | `movsx r32, r8` | Move word to doubleword with sign-extension. | \* `66` applicable; REX.W applicable in 64-bit mode (applies to dest register); note: using a prefix increases the instruction length and influences RIP-relative addressing! \*\* REX.W applicable in 64-bit mode (applies to dest register) **Encodings available only in 64-bit mode:** | Opcode | Operands | Assembly | Description | | --------------------------------------- | --------------------- | ------------------------------------------------------------- | ------------------------------------------------------------- | -------------------------------------------------- | | `63 [00 ??? ???]`\* | Reg, R/M != \{4, 5\} | `movsxd r32, dword ptr [r32]` | `movsxd r32, dword ptr [r64]` | Move doubleword to doubleword with sign-extension. | | `63 [00 ??? 100] ?[????]`\* | Reg; SIB, Base != 5 | `movsxd r32, dword ptr [base_r32 + index_r32*scale]` | `movsxd r32, dword ptr [base_r64 + index_r64*scale]` | Move doubleword to doubleword with sign-extension. | | `63 [00 ??? 100] ?[?101] ?? ?? ?? ??`\* | Reg; SIB; disp32 | `movsxd r32, dword ptr [index_r32*scale + disp32]` | `movsxd r32, dword ptr [index_r64*scale + disp32]` | Move doubleword to doubleword with sign-extension. | | `63 [00 ??? 101] ?? ?? ?? ??`\* | Reg; disp32 | `movsxd r32, dword ptr ds:disp32` | `movsxd r32, dword ptr [$ + 7 + disp32]`\* | Move doubleword to doubleword with sign-extension. | | `63 [01 ??? ???] ??`\* | Reg, R/M != 4; disp8 | `movsxd r32, dword ptr [r32 + disp8]` | `movsxd r32, dword ptr [r64 + disp8]` | Move doubleword to doubleword with sign-extension. | | `63 [01 ??? 100] ?? ??`\* | Reg; SIB; disp8 | `movsxd r32, dword ptr [base_r32 + index_r32*scale + disp8]` | `movsxd r32, dword ptr [base_r64 + index_r64*scale + disp8]` | Move doubleword to doubleword with sign-extension. | | `63 [10 ??? ???] ?? ?? ?? ??`\* | Reg, R/M != 4; disp32 | `movsxd r32, dword ptr [r32 + disp32]` | `movsxd r32, dword ptr [r64 + disp32]` | Move doubleword to doubleword with sign-extension. | | `63 [10 ??? 100] ?? ?? ?? ?? ??`\* | Reg; SIB; disp32 | `movsxd r32, dword ptr [base_r32 + index_r32*scale + disp32]` | `movsxd r32, dword ptr [base_r64 + index_r64*scale + disp32]` | Move doubleword to doubleword with sign-extension. | | `63 [11 ??? ???]`\* | Reg, R/M | `movsxd r32, r32` | `movsxd r32, r32` | Move doubleword to doubleword with sign-extension. | \* REX.W applicable (applies to dest register) **Encodings available in 32-bit mode only:** todo (pain) #### CMOVcc — Conditional Move **Relation between second opcode byte and condition:** | Opcode byte following `0F` | Assembly mnemonic | Description | Test | | -------------------------- | ----------------- | ----------------------------- | ---------------- | | `40` | `cmovo` | Move if overflow. | OF=1 | | `41` | `cmovno` | Move if not overflow. | OF=0 | | `42` | `cmovb` | Move if below/move if carry. | CF=1 | | `42` | `cmovnae` | Move if not above or equal. | CF=1 | | `42` | `cmovc` | Move if carry. | CF=1 | | `43` | `cmovae` | Move if above or equal. | CF=0 | | `43` | `cmovnb` | Move if not below. | CF=0 | | `43` | `cmovnc` | Move if not carry. | CF=0 | | `44` | `cmove` | Move if equal. | ZF=1 | | `44` | `cmovz` | Move if zero. | ZF=1 | | `45` | `cmovne` | Move if not equal. | ZF=0 | | `45` | `cmovnz` | Move if not zero. | ZF=0 | | `46` | `cmovbe` | Move if below or equal. | CF=1 or ZF=1 | | `46` | `cmovna` | Move if not above. | CF=1 or ZF=1 | | `47` | `cmova` | Move if above. | CF=0 and ZF=0 | | `47` | `cmovnbe` | Move if not below or equal. | CF=0 and ZF=0 | | `48` | `cmovs` | Move if sign. | SF=1 | | `49` | `cmovns` | Move if not sign. | SF=0 | | `4A` | `cmovp` | Move if parity. | PF=1 | | `4A` | `cmovpe` | Move if parity even. | PF=1 | | `4B` | `cmovnp` | Move if not parity. | PF=0 | | `4B` | `cmovpo` | Move if parity odd. | PF=0 | | `4C` | `cmovl` | Move if less. | SF≠OF | | `4C` | `cmovnge` | Move if not greater or equal. | SF≠OF | | `4D` | `cmovge` | Move if greater or equal. | SF=OF | | `4D` | `cmovnl` | Move if not less. | SF=OF | | `4E` | `cmovle` | Move if less or equal. | ZF=1 or SF≠OF | | `4E` | `cmovng` | Move if not greater. | ZF=1 or SF≠OF | | `4F` | `cmovg` | Move if greater. | ZF=0 and SF=OF | | `4F` | `cmovnle` | Move if not less or equal. | ZF=0 and SF=OF | **Encodings available in both 32-bit and 64-bit mode:** In the following table, the `XX` placeholder signifies one of the condition opcodes from the table above. | Opcode | Operands | Assembly (32-bit) | Assembly (64-bit) | Description | | ------------------------------------------ | --------------------- | ------------------------------------------------------------- | ------------------------------------------------------------- | -------------------------------------------------- | | `0F XX [00 ??? ???]`\* | Reg, R/M != \{4, 5\} | `cmovcc r32, dword ptr [r32]` | `cmovcc r32, dword ptr [r64]` | Move doubleword to doubleword with sign-extension. | | `0F XX [00 ??? 100] ?[????]`\* | Reg; SIB, Base != 5 | `cmovcc r32, dword ptr [base_r32 + index_r32*scale]` | `cmovcc r32, dword ptr [base_r64 + index_r64*scale]` | Move doubleword to doubleword with sign-extension. | | `0F XX [00 ??? 100] ?[?101] ?? ?? ?? ??`\* | Reg; SIB; disp32 | `cmovcc r32, dword ptr [index_r32*scale + disp32]` | `cmovcc r32, dword ptr [index_r64*scale + disp32]` | Move doubleword to doubleword with sign-extension. | | `0F XX [00 ??? 101] ?? ?? ?? ??`\* | Reg; disp32 | `cmovcc r32, dword ptr ds:disp32` | `cmovcc r32, dword ptr [$ + 7 + disp32]`\* | Move doubleword to doubleword with sign-extension. | | `0F XX [01 ??? ???] ??`\* | Reg, R/M != 4; disp8 | `cmovcc r32, dword ptr [r32 + disp8]` | `cmovcc r32, dword ptr [r64 + disp8]` | Move doubleword to doubleword with sign-extension. | | `0F XX [01 ??? 100] ?? ??`\* | Reg; SIB; disp8 | `cmovcc r32, dword ptr [base_r32 + index_r32*scale + disp8]` | `cmovcc r32, dword ptr [base_r64 + index_r64*scale + disp8]` | Move doubleword to doubleword with sign-extension. | | `0F XX [10 ??? ???] ?? ?? ?? ??`\* | Reg, R/M != 4; disp32 | `cmovcc r32, dword ptr [r32 + disp32]` | `cmovcc r32, dword ptr [r64 + disp32]` | Move doubleword to doubleword with sign-extension. | | `0F XX [10 ??? 100] ?? ?? ?? ?? ??`\* | Reg; SIB; disp32 | `cmovcc r32, dword ptr [base_r32 + index_r32*scale + disp32]` | `cmovcc r32, dword ptr [base_r64 + index_r64*scale + disp32]` | Move doubleword to doubleword with sign-extension. | | `0F XX [11 ??? ???]`\* | Reg, R/M | `cmovcc r32, r32` | `cmovcc r32, r32` | Move doubleword to doubleword with sign-extension. | \* `66` applicable; REX.W applicable in 64-bit mode (applies to source and dest); note: using a prefix increases the instruction length and influences RIP-relative addressing! **Encodings available in 32-bit mode only:** todo (pain) #### XCHG — Exchange Register/Memory With Register **Encodings available in both 32-bit and 64-bit mode:** | Opcode | Operands | Assembly | Description | | ------- | -------- | ---------------------------------- | ------------------------------------- | | `90`\* | - | `xchg eax, eax` | Exchange EAX with EAX (no operation). | | `91`\* | - | `xchg eax, ecx` or `xchg ecx, eax` | Exchange EAX with ECX. | | `92`\* | - | `xchg eax, edx` or `xchg edx, eax` | Exchange EAX with EDX. | | `93`\* | - | `xchg eax, ebx` or `xchg ebx, eax` | Exchange EAX with EBX. | | `94`\* | - | `xchg eax, esp` or `xchg esp, eax` | Exchange EAX with ESP. | | `95`\* | - | `xchg eax, ebp` or `xchg ebp, eax` | Exchange EAX with EBP. | | `96`\* | - | `xchg eax, esi` or `xchg esi, eax` | Exchange EAX with ESI. | | `97`\* | - | `xchg eax, edi` or `xchg edi, eax` | Exchange EAX with EDI. | | `86 /r` | todo | | | | `87 /r` | todo | | | \*: The `66` prefix can be used to exchange the contents of corresponding **16-bit** registers. **Encodings only available in 64-bit mode:** | Opcode | Operands | Assembly | Description | | ------------ | -------- | ---------------------------------- | ------------------------------------- | | `4[1???] 90` | - | `xchg rax, rax` | Exchange RAX with RAX (no operation). | | `4[1???] 91` | - | `xchg rax, rcx` or `xchg rcx, rax` | Exchange RAX with RCX. | | `4[1???] 92` | - | `xchg rax, rdx` or `xchg rdx, rax` | Exchange RAX with RDX. | | `4[1???] 93` | - | `xchg rax, rbx` or `xchg rbx, rax` | Exchange RAX with RBX. | | `4[1???] 94` | - | `xchg rax, rsp` or `xchg rsp, rax` | Exchange RAX with RSP. | | `4[1???] 95` | - | `xchg rax, rbp` or `xchg rbp, rax` | Exchange RAX with RBP. | | `4[1???] 96` | - | `xchg rax, rsi` or `xchg rsi, rax` | Exchange RAX with RSI. | | `4[1???] 97` | - | `xchg rax, rdi` or `xchg rdi, rax` | Exchange RAX with RDI. | ### Effective address computation #### LEA — Load Effective Address **Encodings available in both 32-bit and 64-bit mode:** | Opcode | Operands | Assembly (32-bit) | Assembly (64-bit) | Description | | -------------------------------------------- | --------------------- | -------------------------------------------------- | -------------------------------------------------- | ----------------------- | | `8D [00 ??? ???]`\* | Reg, R/M != \{4, 5\} | `lea r32, [r32]` | `lea r32, [r64]` | | | `8D [00 ??? 100] [?? ??? ???]`\* | R/M; SIB, Base != 5 | `lea r32, [base_r32 + (index_r32*scale)]` | `lea r32, [base_r64 + (index_r64*scale)]` | | | `8D [00 ??? 100] [?? ??? 101] ?? ?? ?? ??`\* | R/M; SIB | `lea r32, [(index_r32*scale) + disp32]` | `lea r32, [(index_r64*scale) + disp32]` | | | `8D [00 ??? 101] ?? ?? ?? ??`\* | R/M; disp32 | `lea r32, ds:disp32` | `lea r32, [$ + 6 + disp32]` | | | `8D [01 ??? ???]`\* | Reg, R/M != 4 | `lea r32, [r32 + disp8]` | `lea r32, [r64 + disp8]` | | | `8D [01 ??? 100] ?? ??`\* | R/M; SIB; disp8 | `lea r32, [base_r32 + (index_r32*scale) + disp8]` | `lea r32, [base_r64 + (index_r64*scale) + disp8]` | | | `8D [10 ??? ???] ?? ?? ?? ??`\* | Reg, R/M != 4; disp32 | `lea r32, [r32 + disp32]` | `lea r32, [r64 + disp32]` | | | `8D [10 ??? 100] ?? ?? ?? ?? ??`\* | Reg, R/M; SIB; disp32 | `lea r32, [base_r32 + (index_r32*scale) + disp32]` | `lea r32, [base_r64 + (index_r64*scale) + disp32]` | | | `8D [11 ??? ???]` | Reg, R/M | - | - | Raises a #UD exception. | | `66 8D [11 ??? ???]` | Reg, R/M | - | - | Raises a #UD exception. | | `67 8D [11 ??? ???]` | Reg, R/M | - | - | Raises a #UD exception. | **Encodings available in 32-bit mode only:** | Opcode | Operands | Assembly | Description | | ---------------------------- | ---------------- | ------------------------------- | ----------- | | `67 8D [00 ??? ???]`\* | Reg, R/M != 6 | `lea r32, [r16(+r16)?]` | | | `67 8D [00 ??? 110] ?? ??`\* | R/M; disp16 | `lea r32, ds:disp16` | | | `67 8D [01 ??? ???] ??`\* | Reg, R/M; disp8 | `lea r32, [r16(+r16) + disp8]` | | | `67 8D [10 ??? ???] ?? ??`\* | Reg, R/M; disp16 | `lea r32, [r16(+r16) + disp16]` | | \* 66 applicable -> dest r16 **Encodings available in 64-bit mode only:** | Opcode | Operands | Assembly | Description | | ------------------------------------------------------ | ------------------------------ | -------------------------------------------------------- | ----------------------- | | `67 8D [00 ??? ???]`\* | Reg, R/M != \{4, 5\} | `lea r32, [r32]` | | | `67 8D [00 ??? 100] [?? ??? ???]`\* | R/M; SIB, Base != 5 | `lea r32, [base_r32 + (index_r32*scale)]` | | | `67 8D [00 ??? 100] [?? ??? 101] ?? ?? ?? ??`\* | R/M; SIB | `lea r32, [(index_r32*scale) + disp32]` | | | `67 8D [00 ??? 101] ?? ?? ?? ??`\* | R/M; disp32 | `lea r32, [eip+disp32]` (`eip` = `($ + 7) & 0xffffffff`) | | | `67 8D [01 ??? ???]`\* | Reg, R/M != 4 | `lea r32, [r32 + disp8]` | | | `67 8D [01 ??? 100] ?? ??`\* | R/M; SIB; disp8 | `lea r32, [base_r32 + (index_r32*scale) + disp8]` | | | `67 8D [10 ??? ???] ?? ?? ?? ??`\* | Reg, R/M != 4; disp32 | `lea r32, [r32 + disp32]` | | | `67 8D [10 100 ???] ?? ?? ?? ?? ??`\* | Reg; SIB; disp32 | `lea r32, [base_r32 + (index_r32*scale) + disp32]` | | | `4[1???] 8D [00 ??? ???]`\*\* | REX.RXB; Reg, R/M != \{4, 5\} | `lea r64, [r64]` | | | `4[1???] 8D [00 ??? 100] [?? ??? ???]`\*\* | REX.RXB; Reg; SIB, Base != 5 | `lea r64, [base_r64 + (index_r64*scale)]` | | | `4[1???] 8D [00 ??? 100] [?? ??? 101] ?? ?? ?? ??`\*\* | REX.RXB; Reg; SIB; disp32 | `lea r64, [(index_r64*scale) + disp32]` | | | `4[1???] 8D [00 ??? 101] ?? ?? ?? ??`\*\* | REX.RXB; Reg, R/M; disp32 | `lea r64, [$ + 7 + disp32]` | | | `4[1???] 8D [01 ??? ???] ??`\*\* | REX.RXB; Reg, R/M != 4; disp8 | `lea r64, [r64 + disp8]` | | | `4[1???] 8D [01 ??? 100] ?? ??`\*\* | REX.RXB; Reg; SIB; disp8 | `lea r64, [base_r64 + (index_r64*scale) + disp8]` | | | `4[1???] 8D [10 ??? ???] ?? ?? ?? ??`\*\* | REX.RXB; Reg, R/M != 4; disp32 | `lea r64, [r64 + disp32]` | | | `4[1???] 8D [10 ??? 100] ?? ?? ?? ?? ??`\*\* | REX.RXB; Reg, R/M; SIB; disp32 | `lea r64, [base_r64 + (index_r64*scale) + disp32]` | | | `4[1???] 8D [11 ??? ???]`\*\* | REX.RXB; Reg, R/M | - | Raises a #UD exception. | \*: 66 applicable -> dest register 16-bit \*\*: 67 applicable -> memory addressing 32-bit ### Stack manipulation instructions #### PUSH — Push Word, Doubleword, or Quadword Onto the Stack **Push encodings available in both 32-bit and 64-bit mode:** | Opcode | Operands | Assembly | Description | | ---------------- | -------- | -------------- | --------------------------------------------------------------- | | `50`\* | - | `push (e/r)ax` | Push the value in the (E/R)AX register to the stack. | | `51`\* | - | `push (e/r)cx` | Push the value in the (E/R)CX register to the stack. | | `52`\* | - | `push (e/r)dx` | Push the value in the (E/R)DX register to the stack. | | `53`\* | - | `push (e/r)bx` | Push the value in the (E/R)BX register to the stack. | | `54`\* | - | `push (e/r)sp` | Push the (original) value in the (E/R)SP register to the stack. | | `55`\* | - | `push (e/r)bp` | Push the value in the (E/R)BP register to the stack. | | `56`\* | - | `push (e/r)si` | Push the value in the (E/R)SI register to the stack. | | `57`\* | - | `push (e/r)di` | Push the value in the (E/R)DI register to the stack. | | `6A ??` | imm8 | `push imm8` | Push an immediate value to the stack. | | `66 68 ?? ??` | imm16 | `push imm16` | Push an immediate value to the stack. | | `68 ?? ?? ?? ??` | imm32 | `push imm32` | Push an immediate value to the stack. | | `0F A0` | - | `push fs` | Push the value in the FS register to the stack. | | `0F A8` | - | `push gs` | Push the value in the GS register to the stack. | \*: The instruction pushes the corresponding 32-bit register in 32-bit mode and the corresponding 64-bit register in 64-bit mode. In both modes, the `66` prefix may be used to push the corresponding **16-bit** register instead of the native-sized register. **Push encodings only available in 32-bit mode:** | Opcode | Operands | Assembly | Description | | ----------------------------- | ---------------------- | ---------------------------------------------------------- | ----------------------------------------------- | | `FF 3[0???]`\* | R/M value != \{4, 5\} | `push dword ptr [r32]` | todo | | `FF 34 ?[?101] ?? ?? ?? ??`\* | SIB; disp32 | `push dword ptr [(index_r32 * scale) + disp32]` | todo | | `FF 34 ?[????]`\* | SIB, Base != 5 | `push dword ptr [base_r32 + (index_r32 * scale)]` | todo | | `FF 35 ?? ?? ?? ??`\* | disp32 | `push dword ptr ds:disp32` | todo | | `FF 7[0???] ??`\* | R/M value != 4; disp8 | `push dword ptr [r32 + disp8]` | todo | | `FF 74 ?? ??`\* | SIB; disp8 | `push dword ptr [base_r32 + (index_r32 * scale) + disp8]` | todo | | `FF B[0???] ?? ?? ?? ??`\* | R/M value != 4; disp32 | `push dword ptr [r32 + disp32]` | todo | | `FF B4 ?? ?? ?? ?? ??`\* | SIB; disp32 | `push dword ptr [base_r32 + (index_r32 * scale) + disp32]` | todo | | `FF F[0???]`\*\* | R/M value | `push r32` | todo | | `67 FF 3[0???]`\* | R/M value != 6 | `push dword ptr [r16(+r16)?]` | todo | | `67 FF 36 ??`\* | disp16 | `push dword ptr [disp16]` | todo | | `67 FF 7[0???] ??` | R/M value; disp8 | `push dword ptr [r16(+r16)?+disp8]` | todo | | `67 FF B[0???] ?? ??` | R/M value; disp16 | `push dword ptr [r16(+r16)?+disp16]` | todo | | `67 FF F[0???]` | R/M value | `push r16` | todo | | `0E` | - | `push cs` | Push the value in the CS register to the stack. | | `16` | - | `push ss` | Push the value in the SS register to the stack. | | `1E` | - | `push ds` | Push the value in the DS register to the stack. | | `06` | - | `push es` | Push the value in the ES register to the stack. | \*: `66` prefix applicable (todo) \*\*: `66` prefix applicable (todo) **Push encodings only available in 64-bit mode:** | Opcode | Operands | Assembly | Description | | ----------------------------- | ---------------------- | ---------------------------------------------------------- | ----------- | | `FF 3[0???]`\* | R/M value != \{4, 5\} | `push qword ptr [r64]` | todo | | `FF 34 ?[?101] ?? ?? ?? ??`\* | SIB; disp32 | `push qword ptr [(index_r64 * scale) + disp64]` | todo | | `FF 34 ?[????]`\* | SIB, Base != 5 | `push qword ptr [base_r64 + (index_r64 * scale)]` | todo | | `FF 35 ?? ?? ?? ??`\* | disp32 | `push qword ptr [$+6+disp32]` | todo | | `FF 7[0???] ??`\* | R/M value != 4; disp8 | `push qword ptr [r64 + disp8]` | todo | | `FF 74 ?? ??`\* | SIB; disp8 | `push qword ptr [base_r64 + (index_r64 * scale) + disp8]` | todo | | `FF B[0???] ?? ?? ?? ??`\* | R/M value != 4; disp32 | `push qword ptr [r64 + disp32]` | todo | | `FF B4 ?? ?? ?? ?? ??`\* | SIB; disp32 | `push qword ptr [base_r64 + (index_r64 * scale) + disp32]` | todo | | `FF F[0???]`\*\* | R/M value | `push r64` | todo | todo REX? push r8-r15 etc. \*: todo #### POP — Pop a Value From the Stack **Pop encodings available in both 32-bit and 64-bit mode:** | Opcode | Operands | Assembly | Description | | ---------- | -------- | ------------- | ------------------------------------------------------------- | | `58`\* | - | `pop (e/r)ax` | Pop value into the (E/R)AX register from the stack. | | `59`\* | - | `pop (e/r)cx` | Pop value into the (E/R)CX register from the stack. | | `5A`\* | - | `pop (e/r)dx` | Pop value into the (E/R)DX register from the stack. | | `5B`\* | - | `pop (e/r)bx` | Pop value into the (E/R)BX register from the stack. | | `5C`\* | - | `pop (e/r)sp` | Pop value into the (E/R)SP register from the stack. | | `5D`\* | - | `pop (e/r)bp` | Pop value into the (E/R)BP register from the stack. | | `5E`\* | - | `pop (e/r)si` | Pop value into the (E/R)SI register from the stack. | | `5F`\* | - | `pop (e/r)di` | Pop value into the (E/R)DI register from the stack. | | `66 0F A1` | - | `popw fs` | Pop top of stack into FS; increment stack pointer by 16 bits. | | `66 0F A9` | - | `popw gs` | Pop top of stack into GS; increment stack pointer by 16 bits. | \*: The instruction uses the corresponding 32-bit register in 32-bit mode and the corresponding 64-bit register in 64-bit mode. In both modes, the `66` prefix may be used to pop into the corresponding **16-bit** register instead of the native-sized register. **Pop encodings only available in 32-bit mode:** | Opcode | Operands | Assembly | Description | | ----------------------------- | ---------------------- | ------------------------------------------------------- | ------------------------------------------------------------- | | `8F 0[0???]`\* | R/M value != \{4, 5\} | `pop dword ptr [r32]` | | | `8F 04 ?[????]`\* | SIB, Base != 5 | `pop dword ptr [base_r32 + (index_r32*scale)]` | | | `8F 04 ?[?101] ?? ?? ?? ??`\* | SIB; disp32 | `pop dword ptr [(index_r32*scale) + disp32]` | | | `8F 05 ?? ?? ?? ??`\* | disp32 | `pop dword ptr ds:disp32` | | | `8F 4[0???] ??`\* | R/M value != 4; disp8 | `pop dword ptr [r32 + disp8]` | | | `8F 44 ?? ??`\* | SIB; disp8 | `pop dword ptr [base_r32 + (index_r32*scale) + disp8]` | | | `8F 8[0???] ?? ?? ?? ??`\* | R/M value != 4; disp32 | `pop dword ptr [r32 + disp32]` | | | `8F 84 ?? ?? ?? ?? ??`\* | SIB; disp32 | `pop dword ptr [base_r32 + (index_r32*scale) + disp32]` | | | `8F C[0???]` | R/M value | `pop r32` | | | `67 8F 0[0???]`\* | R/M value != 6 | `pop dword ptr [r16(+r16)?]` | todo | | `67 8F 06 ?? ??`\* | disp16 | `pop dword ptr ds:disp16` | todo | | `67 8F 4[0???] ??`\* | R/M value; disp8 | `pop dword ptr [r16(+r16)? + disp8]` | todo | | `67 8F 8[0???] ?? ??`\* | R/M value; disp16 | `pop dword ptr [r16(+r16)? + disp16]` | todo | | `66 8F C[0???]` | R/M value | `pop r16` | todo | | `1F` | - | `pop ds` | Pop top of stack into DS; increment stack pointer. | | `07` | - | `pop es` | Pop top of stack into ES; increment stack pointer. | | `17` | - | `pop ss` | Pop top of stack into SS; increment stack pointer. | | `0F A1` | - | `pop fs` | Pop top of stack into FS; increment stack pointer by 32 bits. | | `0F A9` | - | `pop gs` | Pop top of stack into GS; increment stack pointer by 32 bits. | **Pop encodings only available in 64-bit mode:** | Opcode | Operands | Assembly | Description | Notes | | ----------------------------- | ---------------------- | ------------------------------------------------------- | ------------------------------------------------------------- | ----- | | `8F 0[0???]`\* | R/M value != \{4, 5\} | `pop qword ptr [r64]` | | | | `8F 04 ?[????]`\* | SIB, Base != 5 | `pop qword ptr [base_r64 + (index_r64*scale)]` | | | | `8F 04 ?[?101] ?? ?? ?? ??`\* | SIB; disp32 | `pop qword ptr [(index_r64*scale) + disp32]` | | | | `8F 05 ?? ?? ?? ??`\* | disp32 | `pop qword ptr [$ + 6 + disp32]` | RIP-relative addressing | | | `8F 4[0???] ??`\* | R/M value != 4; disp8 | `pop qword ptr [r64 + disp8]` | | | | `8F 44 ?? ??`\* | SIB; disp8 | `pop qword ptr [base_r64 + (index_r64*scale) + disp8]` | | | | `8F 8[0???] ?? ?? ?? ??`\* | R/M value != 4; disp32 | `pop qword ptr [r64 + disp32]` | | | | `8F 84 ?? ?? ?? ?? ??`\* | SIB; disp32 | `pop qword ptr [base_r64 + (index_r64*scale) + disp32]` | | | | `8F C[0???]` | R/M value | `pop r64` | | | | `0F A1` | - | `pop fs` | Pop top of stack into FS; increment stack pointer by 64 bits. | | `0F A9` | - | `pop gs` | Pop top of stack into GS; increment stack pointer by 64 bits. | \*: The `67` prefix can be used to pop a 32-bit value into a `dword ptr` location. todo 66, 67 prefixes, r8-r15 etc. ### Control flow instructions #### JMP — Jump **Short jump encodings available in both 32-bit and 64-bit modes:** | Opcode | Operands | Assembly | Description | | ------- | ------------------------- | --------------------- | ------------------------------------------------------------------------------------------------------- | | `EB ??` | 8-bit signed displacement | `jmp short $+2+disp8` | Jump short, relative to the next instruction, EIP/RIP += (8-bit displacement sign-extended to 32 bits). | **Near jump encodings available in 32-bit mode:** | Opcode | Operands | Assembly | Description | | ------------------------------ | ------------------------------------------------ | ---------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | | `E9 ?? ?? ?? ??` | 32-bit signed displacement | `jmp $+5+disp32` | Jump near, relative to the next instruction, EIP += 32-bit signed displacement. | | `FF 2[0???]` | ModR/M:RM value != \{4, 5\} | `jmp dword ptr [reg]` | Jump near, absolute indirect, 32-bit address read from `[eax]`/`[ecx]`/`[ebx]`/`[edx]`/`[esi]`/`[edi]`. | | `FF 25 ?? ?? ?? ??` | 32-bit absolute address | `jmp address` | Jump near, absolute, 32-bit address given as operand. | | `FF 24 [????????]` | SIB byte, Base != 5 | `jmp dword ptr [reg (+ scale * reg)]` | todo | | `FF 24 [?????101] ?? ?? ?? ??` | SIB Index and Scale values; disp32 | `jmp dword ptr [(scale * reg) + disp32]` | todo | | `FF 6[0???] ??` | ModR/M:RM value != 4; 8-bit signed displacement | `jmp dword ptr [reg + disp8]` | Jump near, absolute indirect, 32-bit address read from `[(eax\|ecx\|edx\|ebx\|ebp\|esi\|edi)+disp8]`. | | `FF 64 ?? ??` | SIB byte; 8-bit signed displacement | `jmp dword ptr [reg (+ scale * reg) + disp8]` | todo | | `FF A[0???] ?? ?? ?? ??` | ModR/M:RM value != 4; 32-bit signed displacement | `jmp dword ptr [reg + disp32]` | Jump near, absolute indirect, 32-bit address read from `[(eax\|ecx\|edx\|ebx\|ebp\|esi\|edi)+disp32]`. | | `FF A4 ?? ?? ?? ?? ??` | SIB byte; 32-bit signed displacement | `jmp dword ptr [reg (+ scale * reg) + disp32]` | todo | | `FF E[0???]` | ModR/M:RM value | `jmp reg` | Jump near, absolute, to zero-extended `eax`/`ecx`/`edx`/`ebx`/`esp`/`ebp`/`esi`/`edi`. | | `66 E9 ?? ??` | 16-bit signed displacement | `jmp $+4+disp16` | Jump near, relative to the next instruction, EIP += (16-bit displacement sign-extended to 32 bits). | | `67 FF 26 ?? ??` | 16-bit absolute address | `jmp address` | Jump near, absolute, 16-bit address given as operand. | | `67 FF 2[0???]`\* | ModR/M:RM value != 6 | `jmp dword ptr [reg(+reg)?]` | Jump near, absolute indirect, 32-bit address zero-extended from `[bx]` or one of `[(bx\|bp)+(si\|di)]`. | | `67 FF 6[0???] ??`\* | ModR/M:RM value, disp8 | `jmp dword ptr [reg(+reg)? + disp8]` | Jump near, absolute indirect, 32-bit address zero-extended from `[(bx\|bp)+disp8]` or `[(bx\|bp)+(si\|di)+disp8]`. | | `67 FF A[0???] ?? ??`\* | ModR/M:RM value, disp16 | `jmp dword ptr [reg(+reg)? + disp16]` | Jump near, absolute indirect, 32-bit address zero-extended from `[(bx\|bp)+disp16]` or `[(bx\|bp)+(si\|di)+disp16]`. | | `66 FF E[0???]` | ModR/M:RM value | `jmp reg` | Jump near, absolute, to zero-extended `ax`/`cx`/`dx`/`bx`/`sp`/`bp`/`si`/`di`. | \*: The `66` prefix can be used to change the dword ptr to a word ptr and jump to a 16-bit address instead. **Near jump encodings available in 64-bit mode:** | Opcode | Operands | Assembly | Description | | ------------------------ | ---------------------------- | ------------------------------------------------- | ------------------------------------------------------------------------------- | | `E9 ?? ?? ?? ??` | 32-bit signed displacement | `jmp $+5+disp32` | Jump near, relative to the next instruction, RIP += 32-bit signed displacement. | | `FF 2[0???]` | ModR/M:RM value != \{4, 5\} | `jmp qword ptr [reg]` | ?? | | `FF 24 [????????]` | SIB byte, Base != 5 | `jmp qword ptr [base + (scale * index)]` | ?? | | `FF 24 [?????101]` | SIB:Scale; SIB:Index | `jmp qword ptr [(scale * index) + disp32]` | ?? | | `FF 25 ?? ?? ?? ??` | disp32 | `jmp qword ptr [$+6+disp32]` | ?? | | `FF 6[0???] ??` | ModR/M:RM value != 4; disp8 | `jmp qword ptr [reg + disp8]` | ?? | | `FF 64 ?? ??` | SIB byte; disp8 | `jmp qword ptr [base + (scale * index) + disp8]` | ?? | | `FF A[0???] ?? ?? ?? ??` | ModR/M:RM value != 4; disp32 | `jmp qword ptr [reg + disp32]` | ?? | | `FF A4 ?? ?? ?? ?? ??` | SIB byte; disp32 | `jmp qword ptr [base + (scale * index) + disp32]` | ?? | | `FF E[0???]` | ModR/M:RM value | `jmp reg` | ?? | todo: far jumps #### Jcc — Jump if Condition Is Met **Optional branch predictor hint prefixes (both 32-bit and 64-bit mode):** | Prefix | Meaning | | ------ | ---------------- | | `2E` | Branch not taken | | `3E` | Branch taken | **Short jump encodings available in both 32-bit and 64-bit modes:** | Opcode | Operands | Assembly | Description | Test | | ------- | -------- | ---------------- | ----------------------------------- | ---------------- | | `77 ??` | rel8 | `ja $+2+rel8` | Jump short if above. | CF=0 and ZF=0 | | `73 ??` | rel8 | `jae $+2+rel8` | Jump short if above or equal. | CF=0 | | `72 ??` | rel8 | `jb $+2+rel8` | Jump short if below (CF=1). | CF=1 | | `76 ??` | rel8 | `jbe $+2+rel8` | Jump short if below or equal. | CF=1 or ZF=1 | | `72 ??` | rel8 | `jc $+2+rel8` | Jump short if carry. | CF=1 | | `E3 ??` | rel8 | `jecxz $+2+rel8` | Jump short if ECX register is 0. | ECX=0 | | `74 ??` | rel8 | `je $+2+rel8` | Jump short if equal. | ZF=1 | | `7F ??` | rel8 | `jg $+2+rel8` | Jump short if greater. | ZF=0 and SF=OF | | `7D ??` | rel8 | `jge $+2+rel8` | Jump short if greater or equal. | SF=OF | | `7C ??` | rel8 | `jl $+2+rel8` | Jump short if less. | SF≠OF | | `7E ??` | rel8 | `jle $+2+rel8` | Jump short if less or equal. | ZF=1 or SF≠OF | | `76 ??` | rel8 | `jna $+2+rel8` | Jump short if not above. | CF=1 or ZF=1 | | `72 ??` | rel8 | `jnae $+2+rel8` | Jump short if not above or equal. | CF=1 | | `73 ??` | rel8 | `jnb $+2+rel8` | Jump short if not below. | CF=0 | | `77 ??` | rel8 | `jnbe $+2+rel8` | Jump short if not below or equal. | CF=0 and ZF=0 | | `73 ??` | rel8 | `jnc $+2+rel8` | Jump short if not carry. | CF=0 | | `75 ??` | rel8 | `jne $+2+rel8` | Jump short if not equal. | ZF=0 | | `7E ??` | rel8 | `jng $+2+rel8` | Jump short if not greater. | ZF=1 or SF≠OF | | `7C ??` | rel8 | `jnge $+2+rel8` | Jump short if not greater or equal. | SF≠OF | | `7D ??` | rel8 | `jnl $+2+rel8` | Jump short if not less. | SF=OF | | `7F ??` | rel8 | `jnle $+2+rel8` | Jump short if not less or equal. | ZF=0 and SF=OF | | `71 ??` | rel8 | `jno $+2+rel8` | Jump short if not overflow. | OF=0 | | `7B ??` | rel8 | `jnp $+2+rel8` | Jump short if not parity. | PF=0 | | `79 ??` | rel8 | `jns $+2+rel8` | Jump short if not sign. | SF=0 | | `75 ??` | rel8 | `jnz $+2+rel8` | Jump short if not zero. | ZF=0 | | `70 ??` | rel8 | `jo $+2+rel8` | Jump short if overflow. | OF=1 | | `7A ??` | rel8 | `jp $+2+rel8` | Jump short if parity. | PF=1 | | `7A ??` | rel8 | `jpe $+2+rel8` | Jump short if parity even. | PF=1 | | `7B ??` | rel8 | `jpo $+2+rel8` | Jump short if parity odd. | PF=0 | | `78 ??` | rel8 | `js $+2+rel8` | Jump short if sign. | SF=1 | | `74 ??` | rel8 | `jz $+2+rel8` | Jump short if zero. | ZF=1 | **Short jump encodings only available in 32-bit mode:** | Opcode | Operands | Assembly | Description | Test | | ------- | -------- | --------------- | ------------------------------- | ---- | | `E3 cb` | rel8 | `jcxz $+2+rel8` | Jump short if CX register is 0. | CX=0 | **Short jump encodings only available in 64-bit mode:** | Opcode | Operands | Assembly | Description | Test | | ------- | -------- | ---------------- | -------------------------------- | ----- | | `E3 cb` | rel8 | `jrcxz $+2+rel8` | Jump short if RCX register is 0. | RCX=0 | **Near relative jump encodings available in both 32-bit and 64-bit modes:** | Opcode | Operands | Assembly | Description | Test | | ------------------- | -------- | ---------------- | ---------------------------------- | ---------------- | | `0F 87 ?? ?? ?? ??` | rel32 | `ja $+6+rel32` | Jump near if above. | CF=0 and ZF=0 | | `0F 83 ?? ?? ?? ??` | rel32 | `jae $+6+rel32` | Jump near if above or equal. | CF=0 | | `0F 82 ?? ?? ?? ??` | rel32 | `jb $+6+rel32` | Jump near if below. | CF=1 | | `0F 86 ?? ?? ?? ??` | rel32 | `jbe $+6+rel32` | Jump near if below or equal. | CF=1 or ZF=1 | | `0F 82 ?? ?? ?? ??` | rel32 | `jc $+6+rel32` | Jump near if carry. | CF=1 | | `0F 84 ?? ?? ?? ??` | rel32 | `je $+6+rel32` | Jump near if equal. | ZF=1 | | `0F 84 ?? ?? ?? ??` | rel32 | `jz $+6+rel32` | Jump near if 0. | ZF=1 | | `0F 8F ?? ?? ?? ??` | rel32 | `jg $+6+rel32` | Jump near if greater. | ZF=0 and SF=OF | | `0F 8D ?? ?? ?? ??` | rel32 | `jge $+6+rel32` | Jump near if greater or equal. | SF=OF | | `0F 8C ?? ?? ?? ??` | rel32 | `jl $+6+rel32` | Jump near if less. | SF≠OF | | `0F 8E ?? ?? ?? ??` | rel32 | `jle $+6+rel32` | Jump near if less or equal. | ZF=1 or SF≠OF | | `0F 86 ?? ?? ?? ??` | rel32 | `jna $+6+rel32` | Jump near if not above. | CF=1 or ZF=1 | | `0F 82 ?? ?? ?? ??` | rel32 | `jnae $+6+rel32` | Jump near if not above or equal. | CF=1 | | `0F 83 ?? ?? ?? ??` | rel32 | `jnb $+6+rel32` | Jump near if not below. | CF=0 | | `0F 87 ?? ?? ?? ??` | rel32 | `jnbe $+6+rel32` | Jump near if not below or equal. | CF=0 and ZF=0 | | `0F 83 ?? ?? ?? ??` | rel32 | `jnc $+6+rel32` | Jump near if not carry. | CF=0 | | `0F 85 ?? ?? ?? ??` | rel32 | `jne $+6+rel32` | Jump near if not equal. | ZF=0 | | `0F 8E ?? ?? ?? ??` | rel32 | `jng $+6+rel32` | Jump near if not greater. | ZF=1 or SF≠OF | | `0F 8C ?? ?? ?? ??` | rel32 | `jnge $+6+rel32` | Jump near if not greater or equal. | SF≠OF | | `0F 8D ?? ?? ?? ??` | rel32 | `jnl $+6+rel32` | Jump near if not less. | SF=OF | | `0F 8F ?? ?? ?? ??` | rel32 | `jnle $+6+rel32` | Jump near if not less or equal. | ZF=0 and SF=OF | | `0F 81 ?? ?? ?? ??` | rel32 | `jno $+6+rel32` | Jump near if not overflow. | OF=0 | | `0F 8B ?? ?? ?? ??` | rel32 | `jnp $+6+rel32` | Jump near if not parity. | PF=0 | | `0F 89 ?? ?? ?? ??` | rel32 | `jns $+6+rel32` | Jump near if not sign. | SF=0 | | `0F 85 ?? ?? ?? ??` | rel32 | `jnz $+6+rel32` | Jump near if not zero. | ZF=0 | | `0F 80 ?? ?? ?? ??` | rel32 | `jo $+6+rel32` | Jump near if overflow. | OF=1 | | `0F 8A ?? ?? ?? ??` | rel32 | `jp $+6+rel32` | Jump near if parity. | PF=1 | | `0F 8A ?? ?? ?? ??` | rel32 | `jpe $+6+rel32` | Jump near if parity even. | PF=1 | | `0F 8B ?? ?? ?? ??` | rel32 | `jpo $+6+rel32` | Jump near if parity odd. | PF=0 | | `0F 88 ?? ?? ?? ??` | rel32 | `js $+6+rel32` | Jump near if sign. | SF=1 | **Near relative jump encodings only available in 32-bit mode:** | Opcode | Operands | Assembly | Description | Test | | ---------------- | -------- | ---------------- | ---------------------------------- | ---------------- | | `66 0F 87 ?? ??` | rel16 | `ja $+5+rel16` | Jump near if above. | CF=0 and ZF=0 | | `66 0F 83 ?? ??` | rel16 | `jae $+5+rel16` | Jump near if above or equal. | CF=0 | | `66 0F 82 ?? ??` | rel16 | `jb $+5+rel16` | Jump near if below. | CF=1 | | `66 0F 86 ?? ??` | rel16 | `jbe $+5+rel16` | Jump near if below or equal. | CF=1 or ZF=1 | | `66 0F 82 ?? ??` | rel16 | `jc $+5+rel16` | Jump near if carry. | CF=1 | | `66 0F 84 ?? ??` | rel16 | `je $+5+rel16` | Jump near if equal. | ZF=1 | | `66 0F 84 ?? ??` | rel16 | `jz $+5+rel16` | Jump near if 0. | ZF=1 | | `66 0F 8F ?? ??` | rel16 | `jg $+5+rel16` | Jump near if greater. | ZF=0 and SF=OF | | `66 0F 8D ?? ??` | rel16 | `jge $+5+rel16` | Jump near if greater or equal. | SF=OF | | `66 0F 8C ?? ??` | rel16 | `jl $+5+rel16` | Jump near if less. | SF≠OF | | `66 0F 8E ?? ??` | rel16 | `jle $+5+rel16` | Jump near if less or equal. | ZF=1 or SF≠OF | | `66 0F 86 ?? ??` | rel16 | `jna $+5+rel16` | Jump near if not above. | CF=1 or ZF=1 | | `66 0F 82 ?? ??` | rel16 | `jnae $+5+rel16` | Jump near if not above or equal. | CF=1 | | `66 0F 83 ?? ??` | rel16 | `jnb $+5+rel16` | Jump near if not below. | CF=0 | | `66 0F 87 ?? ??` | rel16 | `jnbe $+5+rel16` | Jump near if not below or equal. | CF=0 and ZF=0 | | `66 0F 83 ?? ??` | rel16 | `jnc $+5+rel16` | Jump near if not carry. | CF=0 | | `66 0F 85 ?? ??` | rel16 | `jne $+5+rel16` | Jump near if not equal. | ZF=0 | | `66 0F 8E ?? ??` | rel16 | `jng $+5+rel16` | Jump near if not greater. | ZF=1 or SF≠OF | | `66 0F 8C ?? ??` | rel16 | `jnge $+5+rel16` | Jump near if not greater or equal. | SF≠OF | | `66 0F 8D ?? ??` | rel16 | `jnl $+5+rel16` | Jump near if not less. | SF=OF | | `66 0F 8F ?? ??` | rel16 | `jnle $+5+rel16` | Jump near if not less or equal. | ZF=0 and SF=OF | | `66 0F 81 ?? ??` | rel16 | `jno $+5+rel16` | Jump near if not overflow. | OF=0 | | `66 0F 8B ?? ??` | rel16 | `jnp $+5+rel16` | Jump near if not parity. | PF=0 | | `66 0F 89 ?? ??` | rel16 | `jns $+5+rel16` | Jump near if not sign. | SF=0 | | `66 0F 85 ?? ??` | rel16 | `jnz $+5+rel16` | Jump near if not zero. | ZF=0 | | `66 0F 80 ?? ??` | rel16 | `jo $+5+rel16` | Jump near if overflow. | OF=1 | | `66 0F 8A ?? ??` | rel16 | `jp $+5+rel16` | Jump near if parity. | PF=1 | | `66 0F 8A ?? ??` | rel16 | `jpe $+5+rel16` | Jump near if parity even. | PF=1 | | `66 0F 8B ?? ??` | rel16 | `jpo $+5+rel16` | Jump near if parity odd. | PF=0 | | `66 0F 88 ?? ??` | rel16 | `js $+5+rel16` | Jump near if sign. | SF=1 | #### CALL — Call Procedure **Near relative call encodings available in 32-bit mode:** | Opcode | Operands | Assembly | Description | | --------------------------- | ---------------------------- | ---------------------------------------------- | ------------------------------------------------------------------------ | | `E8 ?? ?? ?? ??` | rel32 | `call $+5+rel32` | Call near, relative, displacement relative to next instruction. | | `FF 1[0???] todo` | ModR/M:RM value != \{4, 5\} | `call dword ptr [reg]` | Call near, absolute indirect, address given in register. | | `FF 14 ?[?101] ?? ?? ?? ??` | SIB byte; disp32 | `call dword ptr [scale*index + disp32]` | Call near, absolute indirect, address given according to SIB and disp32. | | `FF 14 ?[????]` | SIB byte; Base != 5 | `call dword ptr [base + scale*index]` | Call near, absolute indirect, address given according to SIB. | | `FF 15 ?? ?? ?? ??` | disp32 | `call dword ptr ds:disp32` | Call near, absolute, address given in disp32. | | `FF 5[0???] ??` | ModR/M:RM value != 4; disp8 | `call dword ptr [reg + disp8]` | Call near, absolute indirect, address given in register and disp8. | | `FF 54 ?? ??` | SIB byte; disp8 | `call dword ptr [base + scale*index + disp8]` | Call near, absolute indirect, address given according to SIB and disp8. | | `FF 9[0???] ?? ?? ?? ??` | ModR/M:RM value != 4; disp32 | `call dword ptr [reg + disp32]` | Call near, absolute indirect, address given in register and disp32. | | `FF 94 ?? ?? ?? ?? ??` | SIB byte; disp32 | `call dword ptr [base + scale*index + disp32]` | Call near, absolute indirect, address given according to SIB and disp32. | | `FF D[0???]` | ModR/M:RM value | `call dword ptr reg` | Call near, absolute indirect, address given in register. | | `66 E8 ?? ??` | rel16 | `callw $+4+rel16` | Call near, relative, displacement relative to next instruction. | | `67 FF 1[0???]`\* | ModR/M:RM value != 6 | `call dword ptr [reg(+reg)?]` | Call near, absolute indirect. | | `67 FF 16 ?? ??`\* | disp16 | `call dword ptr ds:disp16` | Call near, absolute, address given in disp16. | | `67 FF 5[0???] ??`\* | ModR/M:RM value; disp8 | `call dword ptr [reg(+reg)?+disp8]` | Call near, absolute indirect. | | `67 FF 9[0???] ?? ??`\* | ModR/M:RM value; disp16 | `call dword ptr [reg(+reg)?+disp16]` | Call near, absolute indirect. | | `67 FF D[0???]`\* | ModR/M:RM value | `call reg` | Call near, absolute. | \*: The `66` prefix can be used to change the dword ptr to a word ptr and jump to a 16-bit address instead. **Near relative call encodings available in 64-bit mode:** | Opcode | Operands | Assembly | Description | Notes | | --------------------------- | --------------------------- | ---------------------------------------------- | --------------------------------------------------------------- | ----------------------- | | `E8 ?? ?? ?? ??` | rel32 | `call $+5+rel32` | Call near, relative, displacement relative to next instruction. | - | | `FF 1[0???] todo` | ModR/M:RM value != \{4, 5\} | `call qword ptr [reg]` | Call near, absolute indirect, address given in register. | - | | `FF 14 ?[?101] ?? ?? ?? ??` | SIB byte; disp32 | `call qword ptr [index*scale + disp32]` | Call near, absolute indirect, address given in r/m64. | - | | `FF 14 ?[????]` | SIB byte, Base != 5 | `call qword ptr [base + index*scale]` | Call near, absolute indirect, address given in r/m64. | - | | `FF 15 ?? ?? ?? ??` | disp32 | `call qword ptr [$+6+disp32]` | Call near, absolute indirect, RIP offset given in disp32. | RIP-relative addressing | | `FF 5[0???] ??` | ModR/M:RM value != 4 | `call qword ptr [reg + disp8]` | Call near, absolute indirect, address given in r/m64. | - | | `FF 54 ?? ??` | SIB byte, disp8 | `call qword ptr [base + index*scale + disp8]` | Call near, absolute indirect, address given in r/m64. | - | | `FF 9[0???] ?? ?? ?? ??` | ModR/M:RM value != 4 | `call qword ptr [reg + disp32]` | Call near, absolute indirect, address given in r/m64. | - | | `FF 94 ?? ?? ?? ?? ??` | SIB byte, disp32 | `call qword ptr [base + index*scale + disp32]` | Call near, absolute indirect, address given in r/m64. | - | | `FF D[0???]` | ModR/M:RM value | `call reg` | Call near, absolute. | - | todo: far calls #### RET — Return from procedure call **Encodings available in both 32-bit and 64-bit modes:** | Opcode | Operands | Assembly | Description | | ---------- | -------- | ------------ | ------------------------------------------------------------------ | | `C3` | - | `ret` | Near return to calling procedure. | | `CB` | - | `retf` | Far return to calling procedure. | | `C2 ?? ??` | imm16 | `ret imm16` | Near return to calling procedure and pop `imm16` bytes from stack. | | `CA ?? ??` | imm16 | `retf imm16` | Far return to calling procedure and pop `imm16` bytes from stack. | ### Integer arithmetic operations #### ADD — Add #### SUB — Subtract #### MUL — Unsigned Multiply #### IMUL — Signed Multiply #### DIV — Unsigned Divide #### IDIV — Signed Divide #### INC — Increment by 1 **Encodings available in 32-bit mode:** | Opcode | Operands | Assembly | Description | | ------------------------------ | ---------------- | ------------------------------------------------------- | ------------------------------- | | `FE 0[0???]` | R/M != \{4, 5\} | `inc byte ptr [r32]` | Increment r/m byte by 1. | | `FE 04 ?[????]` | SIB, Base != 5 | `inc byte ptr [base_r32 + (index_r32*scale)]` | Increment r/m byte by 1. | | `FE 04 ?[?101] ?? ?? ?? ??` | SIB; disp32 | `inc byte ptr [(index_r32*scale) + disp32]` | Increment r/m byte by 1. | | `FE 05 ?? ?? ?? ??` | disp32 | `inc byte ptr ds:disp32` | Increment r/m byte by 1. | | `FE 4[0???] ??` | R/M != 4; disp8 | `inc byte ptr [r32 + disp8]` | Increment r/m byte by 1. | | `FE 44 ?? ??` | SIB; disp8 | `inc byte ptr [base_r32 + (index_r32*scale) + disp8]` | Increment r/m byte by 1. | | `FE 8[0???] ?? ?? ?? ??` | R/M != 4; disp32 | `inc byte ptr [r32 + disp32]` | Increment r/m byte by 1. | | `FE 84 ?? ?? ?? ?? ??` | SIB; disp32 | `inc byte ptr [base_r32 + (index_r32*scale) + disp32]` | Increment r/m byte by 1. | | `FE C[0???]` | R/M | `inc r8` | Increment r/m byte by 1. | | | | | | | `67 FE 0[0???]` | todo | | Increment r/m byte by 1. | | `67 FE 04 ?[????]` | todo | | Increment r/m byte by 1. | | `67 FE 04 ?[?101] ?? ?? ?? ??` | todo | | Increment r/m byte by 1. | | `67 FE 05 ?? ?? ?? ??` | todo | | Increment r/m byte by 1. | | `67 FE 4[0???] ??` | todo | | Increment r/m byte by 1. | | `67 FE 44 ?? ??` | todo | | Increment r/m byte by 1. | | `67 FE 8[0???] ?? ?? ?? ??` | todo | | Increment r/m byte by 1. | | `67 FE 84 ?? ?? ?? ?? ??` | todo | | Increment r/m byte by 1. | | | | | | | `FF 0[0???]`\* | R/M != \{4, 5\} | `inc dword ptr [r32]` | Increment r/m doubleword by 1. | | `FF 04 ?[????]`\* | SIB, Base != 5 | `inc dword ptr [base_r32 + (index_r32*scale)]` | Increment r/m doubleword by 1. | | `FF 04 ?[?101] ?? ?? ?? ??` | SIB; disp32 | `inc dword ptr [(index_r32*scale) + disp32]` | Increment r/m doubleword by 1. | | `FF 05 ?? ?? ?? ??`\* | disp32 | `inc dword ptr ds:disp32` | Increment r/m doubleword by 1. | | `FF 4[0???] ??`\* | R/M != 4; disp8 | `inc dword ptr [r32 + disp8]` | Increment r/m doubleword by 1. | | `FF 44 ?? ??`\* | SIB; disp8 | `inc dword ptr [base_r32 + (index_r32*scale) + disp8]` | Increment r/m doubleword by 1. | | `FF 8[0???] ?? ?? ?? ??`\* | R/M != 4; disp32 | `inc dword ptr [r32 + disp32]` | Increment r/m doubleword by 1. | | `FF 84 ?? ?? ?? ?? ??`\* | SIB; disp32 | `inc dword ptr [base_r32 + (index_r32*scale) + disp32]` | Increment r/m doubleword by 1. | | `FF C[0???]`\* | R/M | `inc r8` | Increment r/m doubleword by 1. | | | | | | | `67 FF 0[0???]`\* | todo | todo | Increment r/m doubleword by 1. | | `67 FF 04 ?[????]`\* | todo | todo | Increment r/m doubleword by 1. | | `67 FF 04 ?[?101] ?? ?? ?? ??` | todo | todo | Increment r/m doubleword by 1. | | `67 FF 05 ?? ?? ?? ??`\* | todo | todo | Increment r/m doubleword by 1. | | `67 FF 4[0???] ??`\* | todo | todo | Increment r/m doubleword by 1. | | `67 FF 44 ?? ??`\* | todo | todo | Increment r/m doubleword by 1. | | `67 FF 8[0???] ?? ?? ?? ??`\* | todo | todo | Increment r/m doubleword by 1. | | `67 FF 84 ?? ?? ?? ?? ??`\* | todo | todo | Increment r/m doubleword by 1. | | `67 FF C[0???]`\* | todo | todo | Increment r/m doubleword by 1. | | | | | | | `66 40` | - | `inc ax` | Increment 16-bit register by 1. | | `66 41` | - | `inc cx` | Increment 16-bit register by 1. | | `66 42` | - | `inc dx` | Increment 16-bit register by 1. | | `66 43` | - | `inc bx` | Increment 16-bit register by 1. | | `66 44` | - | `inc sp` | Increment 16-bit register by 1. | | `66 45` | - | `inc bp` | Increment 16-bit register by 1. | | `66 46` | - | `inc si` | Increment 16-bit register by 1. | | `66 47` | - | `inc di` | Increment 16-bit register by 1. | | `40` | - | `inc eax` | Increment 32-bit register by 1. | | `41` | - | `inc ecx` | Increment 32-bit register by 1. | | `42` | - | `inc edx` | Increment 32-bit register by 1. | | `43` | - | `inc ebx` | Increment 32-bit register by 1. | | `44` | - | `inc esp` | Increment 32-bit register by 1. | | `45` | - | `inc ebp` | Increment 32-bit register by 1. | | `46` | - | `inc esi` | Increment 32-bit register by 1. | | `47` | - | `inc edi` | Increment 32-bit register by 1. | \* The prefix `66` can be used to increment a 16-bit register or memory location instead of a 32-bit one. **Encodings available in 64-bit mode:** | Opcode | Operands | Assembly | Description | | ------------- | -------- | -------- | ------------------------------ | | `FE /0` | todo | todo | Increment r/m byte by 1. | | `REX + FE /0` | todo | todo | Increment r/m byte by 1. | | `66 FF /0` | todo | todo | Increment r/m word by 1. | | `FF /0` | todo | todo | Increment r/m doubleword by 1. | | `REX.W FF /0` | todo | todo | Increment r/m quadword by 1. | #### DEC — Decrement by 1 #### NOT — One's Complement Negation **Encodings available in both 32-bit and 64-bit mode:** | Opcode | Operands | Assembly (32-bit) | Assembly (64-bit) | Description | | ------------------------------- | ---------------- | ------------------------------------------------------- | ------------------------------------------------------- | ------------------------------------------ | | `F6 1[0???]`\* | R/M != \{4, 5\} | `not byte ptr [r32]` | `not byte ptr [r64]` | Invert each bit of a byte in memory. | | `F6 14 ?[????]`\* | SIB, Base != 5 | `not byte ptr [base_r32 + (index_r32*scale)]` | `not byte ptr [base_r64 + (index_r64*scale)]` | Invert each bit of a byte in memory. | | `F6 14 ?[?101] ?? ?? ?? ??`\* | SIB; disp32 | `not byte ptr [(index_r32*scale) + disp32]` | `not byte ptr [(index_r64*scale) + disp32]` | Invert each bit of a byte in memory. | | `F6 15 ?? ?? ?? ??`\* | disp32 | `not byte ptr ds:disp32` | `not byte ptr [$ + 6 + disp32]` | Invert each bit of a byte in memory. | | `F6 5[0???] ??`\* | R/M != 4; disp8 | `not byte ptr [r32 + disp8]` | `not byte ptr [r64 + disp8]` | Invert each bit of a byte in memory. | | `F6 54 ?? ??`\* | SIB; disp8 | `not byte ptr [base_r32 + (index_r32*scale) + disp8]` | `not byte ptr [base_r64 + (index_r64*scale) + disp8]` | Invert each bit of a byte in memory. | | `F6 9[0???] ?? ?? ?? ??`\* | R/M != 4; disp32 | `not byte ptr [r32 + disp32]` | `not byte ptr [r64 + disp32]` | Invert each bit of a byte in memory. | | `F6 94 ?? ?? ?? ?? ??`\* | SIB; disp32 | `not byte ptr [base_r32 + (index_r32*scale) + disp32]` | `not byte ptr [base_r64 + (index_r64*scale) + disp32]` | Invert each bit of a byte in memory. | | `F6 D[0???]`\* | R/M | `not r8` | `not r8` | Invert each bit of an 8-bit register. | | | | | | | | `F7 1[0???]`\*\* | R/M != \{4, 5\} | `not dword ptr [r32]` | `not dword ptr [r64]` | Invert each bit of a doubleword in memory. | | `F7 14 ?[????]`\*\* | SIB, Base != 5 | `not dword ptr [base_r32 + (index_r32*scale)]` | `not dword ptr [base_r64 + (index_r64*scale)]` | Invert each bit of a doubleword in memory. | | `F7 14 ?[?101] ?? ?? ?? ??`\*\* | SIB; disp32 | `not dword ptr [(index_r32*scale) + disp32]` | `not dword ptr [(index_r64*scale) + disp32]` | Invert each bit of a doubleword in memory. | | `F7 15 ?? ?? ?? ??`\*\* | disp32 | `not dword ptr ds:disp32` | `not dword ptr [$ + 6 + disp32]` | Invert each bit of a doubleword in memory. | | `F7 5[0???] ??`\*\* | R/M != 4; disp8 | `not dword ptr [r32 + disp8]` | `not dword ptr [r64 + disp8]` | Invert each bit of a doubleword in memory. | | `F7 54 ?? ??`\*\* | SIB; disp8 | `not dword ptr [base_r32 + (index_r32*scale) + disp8]` | `not dword ptr [base_r64 + (index_r64*scale) + disp8]` | Invert each bit of a doubleword in memory. | | `F7 9[0???] ?? ?? ?? ??`\*\* | R/M != 4; disp32 | `not dword ptr [r32 + disp32]` | `not dword ptr [r64 + disp32]` | Invert each bit of a doubleword in memory. | | `F7 94 ?? ?? ?? ?? ??`\*\* | SIB; disp32 | `not dword ptr [base_r32 + (index_r32*scale) + disp32]` | `not dword ptr [base_r64 + (index_r64*scale) + disp32]` | Invert each bit of a doubleword in memory. | | `F7 D[0???]`\*\* | R/M | `not r32` | `not r32` | Invert each bit of an 32-bit register. | \* REX applicable \*\* 66 -> 16-bit memory/reg; REX.W -> 64-bit memory/reg **Encodings only available in 32-bit mode:** todo (pain) #### NEG — Two's Complement Negation **Encodings available in both 32-bit and 64-bit mode:** | Opcode | Operands | Assembly (32-bit) | Assembly (64-bit) | Description | | ------------------------------- | ---------------- | ------------------------------------------------------- | ------------------------------------------------------- | ----------------------------------------------- | | `F6 1[1???]`\* | R/M != \{4, 5\} | `neg byte ptr [r32]` | `neg byte ptr [r64]` | Two's complement negate a byte in memory. | | `F6 1C ?[????]`\* | SIB, Base != 5 | `neg byte ptr [base_r32 + (index_r32*scale)]` | `neg byte ptr [base_r64 + (index_r64*scale)]` | Two's complement negate a byte in memory. | | `F6 1C ?[?101] ?? ?? ?? ??`\* | SIB; disp32 | `neg byte ptr [(index_r32*scale) + disp32]` | `neg byte ptr [(index_r64*scale) + disp32]` | Two's complement negate a byte in memory. | | `F6 1D ?? ?? ?? ??`\* | disp32 | `neg byte ptr ds:disp32` | `neg byte ptr [$ + 6 + disp32]` | Two's complement negate a byte in memory. | | `F6 5[1???] ??`\* | R/M != 4; disp8 | `neg byte ptr [r32 + disp8]` | `neg byte ptr [r64 + disp8]` | Two's complement negate a byte in memory. | | `F6 5C ?? ??`\* | SIB; disp8 | `neg byte ptr [base_r32 + (index_r32*scale) + disp8]` | `neg byte ptr [base_r64 + (index_r64*scale) + disp8]` | Two's complement negate a byte in memory. | | `F6 9[1???] ?? ?? ?? ??`\* | R/M != 4; disp32 | `neg byte ptr [r32 + disp32]` | `neg byte ptr [r64 + disp32]` | Two's complement negate a byte in memory. | | `F6 9C ?? ?? ?? ?? ??`\* | SIB; disp32 | `neg byte ptr [base_r32 + (index_r32*scale) + disp32]` | `neg byte ptr [base_r64 + (index_r64*scale) + disp32]` | Two's complement negate a byte in memory. | | `F6 D[1???]`\* | R/M | `neg r8` | `neg r8` | Two's complement negate an 8-bit register. | | | | | | | | `F7 1[1???]`\*\* | R/M != \{4, 5\} | `neg dword ptr [r32]` | `neg dword ptr [r64]` | Two's complement negate a doubleword in memory. | | `F7 1C ?[????]`\*\* | SIB, Base != 5 | `neg dword ptr [base_r32 + (index_r32*scale)]` | `neg dword ptr [base_r64 + (index_r64*scale)]` | Two's complement negate a doubleword in memory. | | `F7 1C ?[?101] ?? ?? ?? ??`\*\* | SIB; disp32 | `neg dword ptr [(index_r32*scale) + disp32]` | `neg dword ptr [(index_r64*scale) + disp32]` | Two's complement negate a doubleword in memory. | | `F7 1D ?? ?? ?? ??`\*\* | disp32 | `neg dword ptr ds:disp32` | `neg dword ptr [$ + 6 + disp32]` | Two's complement negate a doubleword in memory. | | `F7 5[1???] ??`\*\* | R/M != 4; disp8 | `neg dword ptr [r32 + disp8]` | `neg dword ptr [r64 + disp8]` | Two's complement negate a doubleword in memory. | | `F7 5C ?? ??`\*\* | SIB; disp8 | `neg dword ptr [base_r32 + (index_r32*scale) + disp8]` | `neg dword ptr [base_r64 + (index_r64*scale) + disp8]` | Two's complement negate a doubleword in memory. | | `F7 9[1???] ?? ?? ?? ??`\*\* | R/M != 4; disp32 | `neg dword ptr [r32 + disp32]` | `neg dword ptr [r64 + disp32]` | Two's complement negate a doubleword in memory. | | `F7 9C ?? ?? ?? ?? ??`\*\* | SIB; disp32 | `neg dword ptr [base_r32 + (index_r32*scale) + disp32]` | `neg dword ptr [base_r64 + (index_r64*scale) + disp32]` | Two's complement negate a doubleword in memory. | | `F7 D[1???]`\*\* | R/M | `neg r32` | `neg r32` | Two's complement negate an 32-bit register. | \* REX applicable \*\* 66 -> 16-bit memory/reg; REX.W -> 64-bit memory/reg **Encodings only available in 32-bit mode:** todo (pain) #### AND — Logical AND #### OR — Logical Inclusive OR #### XOR — Logical Exclusive OR #### CMP — Compare Two Operands #### TEST — Logical Compare ### String instructions #### REP\* Prefixes #### MOVS — Move Data From String to String #### LODS — Load String #### STOS — Store String #### CMPS — Compare String Operands #### SCAS — Scan String ### Miscellaneous instructions #### NOP — No Operation Encodings available in both 32-bit and 64-bit modes: | Opcode | Operands | Assembly (32-bit mode) | Description | | --------------------------- | ---------------------------- | ---------------------------------- | ------------------------------------ | | `90` | - | `nop` | One byte no-operation instruction. | | `67 0F 1F 06 ?? ??` | disp16 | `nop dword ptr ds:disp16` | Multi-byte no-operation instruction. | | `67 0F 1F 0[0???]` | ModR/M:RM value != 6 | `nop dword ptr [reg(+reg)?]` | Multi-byte no-operation instruction. | | `67 0F 1F 4[0???] ??` | ModR/M:RM value; imm8 | `nop dword ptr [reg(+reg)?+imm8]` | Multi-byte no-operation instruction. | | `67 0F 1F 8[0???] ?? ??` | ModR/M:RM value; imm16 | `nop dword ptr [reg(+reg)?+imm16]` | Multi-byte no-operation instruction. | | `67 0F 1F C[0???]` | ModR/M:RM value | `nop reg` | Multi-byte no-operation instruction. | | `0F 1F 04 ??` | SIB byte | `nop dword ptr todo` | Multi-byte no-operation instruction. | | `0F 1F 05 ?? ?? ?? ??` | disp32 | `nop dword ptr ds:disp32` | Multi-byte no-operation instruction. | | `0F 1F 0[0???] todo` | ModR/M:RM value != \{4, 5\} | `nop dword ptr [reg]` | Multi-byte no-operation instruction. | | `0F 1F 44 ?? ??` | SIB byte; disp8 | `nop dword ptr todo` | Multi-byte no-operation instruction. | | `0F 1F 4[0???] ??` | ModR/M:RM value != 4; disp8 | `nop dword ptr [reg+disp8]` | Multi-byte no-operation instruction. | | `0F 1F 84 ?? ?? ?? ?? ??` | SIB byte; disp32 | `nop dword ptr todo` | Multi-byte no-operation instruction. | | `0F 1F 8[0???] ?? ?? ?? ??` | ModR/M:RM value != 4; disp32 | `nop dword ptr [reg+disp32]` | Multi-byte no-operation instruction. | | `0F 1F C[0???]` | ModR/M:RM value | `nop reg` | Multi-byte no-operation instruction. | #### FNOP — No Operation Encodings available in both 32-bit and 64-bit modes: | Opcode | Operands | Assembly | Description | | ------- | -------- | -------- | -------------------------- | | `D9 D0` | - | `fnop` | No operation is performed. | #### INT3 — Generate Breakpoint Trap Encodings available in both 32-bit and 64-bit modes: | Opcode | Operands | Assembly | Description | | ------ | -------- | -------- | ------------------------- | | `CC` | - | `int3` | Generate breakpoint trap. | #### INT — Call to Interrupt Procedure Encodings available in both 32-bit and 64-bit modes: | Opcode | Operands | Assembly | Description | | ------- | -------- | ---------- | -------------------------------------------------------------------- | | `CD ??` | imm8 | `int imm8` | Generate software interrupt with vector specified by immediate byte. | #### SYSCALL — Fast System Call (64-bit only) Encodings available in 64-bit mode: | Opcode | Operands | Assembly | Description | | ------- | -------- | --------- | ------------------------------------------------- | | `0F 05` | - | `syscall` | Fast call to privilege level 0 system procedures. | ## Appendix ## References [Intel® 64 and IA-32 Architectures Software Developer’s Manual Combined Volumes: 1, 2A, 2B, 2C, 2D, 3A, 3B, 3C, 3D, and 4](https://cdrdv2.intel.com/v1/dl/getContent/671200)