Skip to content

Disassembly Error, missing one operand in some long multi-byte NOPs #539

Open
@venkyqz

Description

@venkyqz

Work environment

Questions Answers
OS/arch/bits x86_64 Ubuntu 20.04
Architecture x86_64
Source of Capstone git clone, default on master branch.
Version/git commit v4.1.0, bffbb6

Instruction bytes giving faulty results

0f 1a de

Expected results

It should be:

nop esi, ebx

Steps to get the wrong result

With ZydisInfo:

./ZydisInfo -64 "0f 1a de"
== [    BASIC ] ============================================================================================
   MNEMONIC: nop [ENC: DEFAULT, MAP: 0F, OPC: 0x1A]
     LENGTH:  3
        SSZ: 64
       EOSZ: 32
       EASZ: 64
   CATEGORY: WIDENOP
    ISA-SET: PPRO
    ISA-EXT: BASE
 EXCEPTIONS: NONE
 ATTRIBUTES: HAS_MODRM
  OPTIMIZED: 0F 18 C3

== [ OPERANDS ] ============================================================================================
##       TYPE  VISIBILITY  ACTION      ENCODING   SIZE  NELEM  ELEMSZ  ELEMTYPE                        VALUE
--  ---------  ----------  ------  ------------   ----  -----  ------  --------  ---------------------------
 0   REGISTER    EXPLICIT       R     MODRM_REG     32      1      32       INT                          ebx
--  ---------  ----------  ------  ------------   ----  -----  ------  --------  ---------------------------

== [      ATT ] ============================================================================================
   ABSOLUTE: nop %ebx
   RELATIVE: nop %ebx

== [    INTEL ] ============================================================================================
   ABSOLUTE: nop ebx
   RELATIVE: nop ebx

== [ SEGMENTS ] ============================================================================================
0F 1A DE
:     :..MODRM
:..OPCODE

Additional Logs, screenshots, source code, configuration dump, ...

x86 (and x86_64) processors have single-byte NOP instructions and various multi-byte NOP-like instructions. Real-world compilers sometimes use multi-byte NOPs for code alignment and performance optimization purposes. Please refer to the StackOverflow post for more details. Zydis thinks the raw bytes "0f 1a de" have only one operand "ebx". But it has two operands "esi" and "ebx" according to the ModR/M encoding shown below:

  • The ModR/M byte DE translates to binary 11011110 (0xDE).
    • Bits 7-6 (Mod): 11 (binary) = 3 (decimal)
      Indicates register-direct addressing mode.
    • Bits 5-3 (Reg): 011 (binary) = 3 (decimal)
      Corresponds to the EBX (or RBX in 64-bit mode) register.
    • Bits 2-0 (R/M): 110 (binary) = 6 (decimal)
      Corresponds to the ESI (or RSI in 64-bit mode) register.

XED also translate "0f 1a de" into "nop esi, ebx".

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions