commit ecdd0431925bfb50310dab17cc0c16c7b266fd55 Author: Milan Špinka Date: Wed Jul 23 22:45:51 2025 +0200 Initial commit. diff --git a/cheatsheet.md b/cheatsheet.md new file mode 100644 index 0000000..d8475c6 --- /dev/null +++ b/cheatsheet.md @@ -0,0 +1,1055 @@ +# 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)