summaryrefslogtreecommitdiff
path: root/thirdparty/mhook/disasm-lib/disasm.h
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/mhook/disasm-lib/disasm.h')
-rw-r--r--thirdparty/mhook/disasm-lib/disasm.h578
1 files changed, 578 insertions, 0 deletions
diff --git a/thirdparty/mhook/disasm-lib/disasm.h b/thirdparty/mhook/disasm-lib/disasm.h
new file mode 100644
index 00000000..6e35ab72
--- /dev/null
+++ b/thirdparty/mhook/disasm-lib/disasm.h
@@ -0,0 +1,578 @@
+// Copyright (C) 2004, Matt Conover (mconover@gmail.com)
+//
+// WARNING:
+// I wouldn't recommend changing any flags like OP_*, ITYPE_*, or *_MASK
+// aside from those marked as UNUSED. This is because the flags parts of
+// the flags are architecture independent and other are left to specific
+// architectures to define, so unless you understand the relationships
+// between them, I would leave them as is.
+
+#ifndef DISASM_H
+#define DISASM_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include <windows.h>
+#include <stdio.h>
+#include "misc.h"
+
+typedef signed char S8;
+typedef unsigned char U8;
+typedef signed short S16;
+typedef unsigned short U16;
+typedef signed long S32;
+typedef unsigned long U32;
+typedef LONG64 S64;
+typedef ULONG64 U64;
+
+#ifdef SPEEDY
+// On Visual Studio 6, making the internal functions inline makes compiling take forever
+#define INTERNAL static _inline
+#define INLINE _inline
+#else
+#define INTERNAL static
+#define INLINE
+#endif
+
+#define VALID_INSTRUCTION(i) ((i) && !((i)->ErrorOccurred))
+#define NEXT_INSTRUCTION(i) ((i)->Address + (i)->Length)
+#define DISASM_ARCH_TYPE(dis) ((dis)->ArchType)
+#define INS_ARCH_TYPE(ins) DISASM_ARCH_TYPE((ins)->Disassembler)
+
+// NOTE: these should be as big set to the maximum of the supported architectures
+#define MAX_PREFIX_LENGTH 15
+#define MAX_OPERAND_COUNT 3
+#define MAX_INSTRUCTION_LENGTH 25
+#define MAX_OPCODE_LENGTH 3
+#define MAX_OPCODE_DESCRIPTION 256
+
+/////////////////////////////////////////////////////////////////////
+// Code branch
+/////////////////////////////////////////////////////////////////////
+
+#define MAX_CODE_REFERENCE_COUNT 3
+
+typedef struct _CODE_BRANCH
+{
+ U64 Addresses[MAX_CODE_REFERENCE_COUNT]; // NULL if multiple to addresses
+ U32 Count;
+ U8 IsLoop : 1;
+ U8 IsCall : 1; // branch if false
+ U8 IsIndirect : 1; // call/jmp [Address]
+ U8 AddressOffset: 5;
+ struct _INSTRUCTION_OPERAND *Operand; // the operand containg the address
+} CODE_BRANCH;
+
+/////////////////////////////////////////////////////////////////////
+// Data references
+/////////////////////////////////////////////////////////////////////
+
+#define MAX_DATA_REFERENCE_COUNT 3
+
+typedef struct _DATA_REFERENCE
+{
+ U64 Addresses[MAX_DATA_REFERENCE_COUNT]; // NULL if multiple to addresses
+ U32 Count;
+ ULONG_PTR DataSize;
+ struct _INSTRUCTION_OPERAND *Operand; // the operand containg the address
+} DATA_REFERENCE;
+
+////////////////////////////////////////////////////////////////////
+// Instruction
+/////////////////////////////////////////////////////////////////////
+
+//
+// Instruction types (bits 0-7)
+// Instruction groups (bits 8-26)
+//
+#define ITYPE_EXEC_OFFSET (1<<8)
+#define ITYPE_ARITH_OFFSET (1<<9)
+#define ITYPE_LOGIC_OFFSET (1<<10)
+#define ITYPE_STACK_OFFSET (1<<11)
+#define ITYPE_TESTCOND_OFFSET (1<<12)
+#define ITYPE_LOAD_OFFSET (1<<13)
+#define ITYPE_ARRAY_OFFSET (1<<14)
+#define ITYPE_BIT_OFFSET (1<<15)
+#define ITYPE_FLAG_OFFSET (1<<16)
+#define ITYPE_FPU_OFFSET (1<<17)
+#define ITYPE_TRAPS_OFFSET (1<<18)
+#define ITYPE_SYSTEM_OFFSET (1<<19)
+#define ITYPE_OTHER_OFFSET (1<<20)
+#define ITYPE_UNUSED1_OFFSET (1<<21)
+#define ITYPE_UNUSED2_OFFSET (1<<22)
+#define ITYPE_UNUSED3_OFFSET (1<<23)
+#define ITYPE_UNUSED4_OFFSET (1<<24)
+#define ITYPE_UNUSED5_OFFSET (1<<25)
+#define ITYPE_UNUSED6_OFFSET (1<<26)
+#define ITYPE_EXT_UNUSED1 (1<<27)
+#define ITYPE_EXT_UNUSED2 (1<<28)
+#define ITYPE_EXT_UNUSED3 (1<<29)
+#define ITYPE_EXT_UNUSED4 (1<<30)
+#define ITYPE_EXT_UNUSED5 (1<<31)
+
+//
+// X86-specific flags (bits 27-31)
+//
+
+#define ITYPE_EXT_64 ITYPE_EXT_UNUSED1 // Use index 1 if in 64-bit mode and 0 otherwise
+#define ITYPE_EXT_MODRM ITYPE_EXT_UNUSED2 // ModRM byte may extend the opcode
+#define ITYPE_EXT_SUFFIX ITYPE_EXT_UNUSED3 // byte after ModRM/SIB/displacement is the third opcode
+#define ITYPE_EXT_PREFIX ITYPE_EXT_UNUSED4 // prefix
+#define ITYPE_EXT_FPU ITYPE_EXT_UNUSED5 // FPU instructions require special handling
+
+#define ITYPE_3DNOW_OFFSET ITYPE_UNUSED1_OFFSET
+#define ITYPE_MMX_OFFSET ITYPE_UNUSED2_OFFSET
+#define ITYPE_SSE_OFFSET ITYPE_UNUSED3_OFFSET
+#define ITYPE_SSE2_OFFSET ITYPE_UNUSED4_OFFSET
+#define ITYPE_SSE3_OFFSET ITYPE_UNUSED5_OFFSET
+
+//
+// Instruction types
+//
+
+#define ITYPE_TYPE_MASK 0x7FFFFFFF
+#define ITYPE_GROUP_MASK 0x7FFFFF00
+
+typedef enum _INSTRUCTION_TYPE
+{
+ // ITYPE_EXEC group
+ ITYPE_EXEC = ITYPE_EXEC_OFFSET,
+ ITYPE_BRANCH,
+ ITYPE_BRANCHCC, // conditional (not necessarily just flags)
+ ITYPE_CALL,
+ ITYPE_CALLCC, // conditional (not necessarily just flags)
+ ITYPE_RET,
+ ITYPE_LOOPCC,
+
+ // ITYPE_ARITH group
+ ITYPE_ARITH = ITYPE_ARITH_OFFSET,
+ ITYPE_XCHGADD,
+ ITYPE_ADD,
+ ITYPE_SUB,
+ ITYPE_MUL,
+ ITYPE_DIV,
+ ITYPE_INC,
+ ITYPE_DEC,
+ ITYPE_SHL,
+ ITYPE_SHR,
+ ITYPE_ROL,
+ ITYPE_ROR,
+
+ // ITYPE_LOGIC group
+ ITYPE_LOGIC=ITYPE_LOGIC_OFFSET,
+ ITYPE_AND,
+ ITYPE_OR,
+ ITYPE_XOR,
+ ITYPE_NOT,
+ ITYPE_NEG,
+
+ // ITYPE_STACK group
+ ITYPE_STACK=ITYPE_STACK_OFFSET,
+ ITYPE_PUSH,
+ ITYPE_POP,
+ ITYPE_PUSHA,
+ ITYPE_POPA,
+ ITYPE_PUSHF,
+ ITYPE_POPF,
+ ITYPE_ENTER,
+ ITYPE_LEAVE,
+
+ // ITYPE_TESTCOND group
+ ITYPE_TESTCOND=ITYPE_TESTCOND_OFFSET,
+ ITYPE_TEST,
+ ITYPE_CMP,
+
+ // ITYPE_LOAD group
+ ITYPE_LOAD=ITYPE_LOAD_OFFSET,
+ ITYPE_MOV,
+ ITYPE_MOVCC, // conditional
+ ITYPE_LEA,
+ ITYPE_XCHG,
+ ITYPE_XCHGCC, // conditional
+
+ // ITYPE_ARRAY group
+ ITYPE_ARRAY=ITYPE_ARRAY_OFFSET,
+ ITYPE_STRCMP,
+ ITYPE_STRLOAD,
+ ITYPE_STRMOV,
+ ITYPE_STRSTOR,
+ ITYPE_XLAT,
+
+ // ITYPE_BIT group
+ ITYPE_BIT=ITYPE_BIT_OFFSET,
+ ITYPE_BITTEST,
+ ITYPE_BITSET,
+ ITYPE_BITCLR,
+
+ // ITYPE_FLAG group
+ // PF = parify flag
+ // ZF = zero flag
+ // OF = overflow flag
+ // DF = direction flag
+ // SF = sign flag
+ ITYPE_FLAG=ITYPE_FLAG_OFFSET,
+ // clear
+ ITYPE_CLEARCF,
+ ITYPE_CLEARZF,
+ ITYPE_CLEAROF,
+ ITYPE_CLEARDF,
+ ITYPE_CLEARSF,
+ ITYPE_CLEARPF,
+ // set
+ ITYPE_SETCF,
+ ITYPE_SETZF,
+ ITYPE_SETOF,
+ ITYPE_SETDF,
+ ITYPE_SETSF,
+ ITYPE_SETPF,
+ // toggle
+ ITYPE_TOGCF,
+ ITYPE_TOGZF,
+ ITYPE_TOGOF,
+ ITYPE_TOGDF,
+ ITYPE_TOGSF,
+ ITYPE_TOGPF,
+
+ // ITYPE_FPU group
+ ITYPE_FPU=ITYPE_FPU_OFFSET,
+ ITYPE_FADD,
+ ITYPE_FSUB,
+ ITYPE_FMUL,
+ ITYPE_FDIV,
+ ITYPE_FCOMP,
+ ITYPE_FEXCH,
+ ITYPE_FLOAD,
+ ITYPE_FLOADENV,
+ ITYPE_FSTORE,
+ ITYPE_FSTOREENV,
+ ITYPE_FSAVE,
+ ITYPE_FRESTORE,
+ ITYPE_FMOVCC,
+
+ ITYPE_UNUSED1=ITYPE_UNUSED1_OFFSET,
+ ITYPE_UNUSED2=ITYPE_UNUSED2_OFFSET,
+ ITYPE_UNUSED3=ITYPE_UNUSED3_OFFSET,
+
+ // ITYPE_MMX group
+ ITYPE_MMX=ITYPE_MMX_OFFSET,
+ ITYPE_MMX_MOV,
+ ITYPE_MMX_ADD,
+ ITYPE_MMX_SUB,
+ ITYPE_MMX_MUL,
+ ITYPE_MMX_DIV,
+ ITYPE_MMX_AND,
+ ITYPE_MMX_OR,
+ ITYPE_MMX_XOR,
+ ITYPE_MMX_CMP,
+
+ // ITYPE_SSE group
+ ITYPE_SSE=ITYPE_SSE_OFFSET,
+ ITYPE_SSE_MOV,
+ ITYPE_SSE_ADD,
+ ITYPE_SSE_SUB,
+ ITYPE_SSE_MUL,
+ ITYPE_SSE_DIV,
+ ITYPE_SSE_AND,
+ ITYPE_SSE_OR,
+ ITYPE_SSE_XOR,
+ ITYPE_SSE_CMP,
+
+ // ITYPE_SSE2 group
+ ITYPE_SSE2=ITYPE_SSE2_OFFSET,
+ ITYPE_SSE2_MOV,
+ ITYPE_SSE2_ADD,
+ ITYPE_SSE2_SUB,
+ ITYPE_SSE2_MUL,
+ ITYPE_SSE2_DIV,
+ ITYPE_SSE2_AND,
+ ITYPE_SSE2_OR,
+ ITYPE_SSE2_XOR,
+ ITYPE_SSE2_CMP,
+
+ // ITYPE_SSE3 group
+ ITYPE_SSE3=ITYPE_SSE3_OFFSET,
+ ITYPE_SSE3_MOV,
+ ITYPE_SSE3_ADD,
+ ITYPE_SSE3_SUB,
+ ITYPE_SSE3_MUL,
+ ITYPE_SSE3_DIV,
+ ITYPE_SSE3_AND,
+ ITYPE_SSE3_OR,
+ ITYPE_SSE3_XOR,
+ ITYPE_SSE3_CMP,
+
+ // ITYPE_3DNOW group
+ ITYPE_3DNOW=ITYPE_3DNOW_OFFSET,
+ ITYPE_3DNOW_ADD,
+ ITYPE_3DNOW_SUB,
+ ITYPE_3DNOW_MUL,
+ ITYPE_3DNOW_DIV,
+ ITYPE_3DNOW_CMP,
+ ITYPE_3DNOW_XCHG,
+
+ // ITYPE_TRAP
+ ITYPE_TRAPS=ITYPE_TRAPS_OFFSET,
+ ITYPE_TRAP, // generate trap
+ ITYPE_TRAPCC, // conditional trap gen
+ ITYPE_TRAPRET, // return from trap
+ ITYPE_BOUNDS, // gen bounds trap
+ ITYPE_DEBUG, // gen breakpoint trap
+ ITYPE_TRACE, // gen single step trap
+ ITYPE_INVALID, // gen invalid instruction
+ ITYPE_OFLOW, // gen overflow trap
+
+ // ITYPE_SYSTEM group
+ ITYPE_SYSTEM=ITYPE_SYSTEM_OFFSET,
+ ITYPE_HALT, // halt machine
+ ITYPE_IN, // input form port
+ ITYPE_OUT, // output to port
+ ITYPE_CPUID, // identify cpu
+ ITYPE_SETIF, // allow interrupts
+ ITYPE_CLEARIF, // block interrupts
+ ITYPE_SYSCALL,
+ ITYPE_SYSCALLRET,
+
+ // ITYPE_OTHER group
+ ITYPE_OTHER = ITYPE_OTHER_OFFSET,
+ ITYPE_NOP,
+ ITYPE_BCDCONV, // convert to/from BCD
+ ITYPE_SZCONV // convert size of operand
+} INSTRUCTION_TYPE;
+
+//
+// Operand flags
+//
+
+// Type = bits 0-6 (these are mutually exclusive -- bits 0-6 will always be a power of 2))
+#define OPTYPE_NONE 0x00
+#define OPTYPE_IMM 0x01 // immediate value
+#define OPTYPE_OFFSET 0x02 // relative offset
+#define OPTYPE_FLOAT 0x03 // floating point
+#define OPTYPE_BCD 0x04
+#define OPTYPE_STRING 0x05
+#define OPTYPE_SPECIAL 0x06
+#define OPTYPE_MASK 0x7F
+
+// Flags = bits 7-23 (these can be combinations)
+// These are used in the X86 opcode table
+#define OP_REG (1<<7) // 0x80
+#define OP_SIGNED (1<<8)
+#define OP_SYS (1<<9) // parameter is an index into some system structure
+#define OP_CONDR (1<<10)
+#define OP_CONDW (1<<11)
+#define OP_UNUSED (1<<12)
+#define OP_SRC (1<<13) // operand is source operand
+#define OP_DST (1<<14) // operand is destination operand
+#define OP_EXEC (1<<15) // operand is executed
+
+#define OP_CONDE OP_CONDR
+#define OP_COND_EXEC (OP_CONDE|OP_EXEC) // executed only if the pre-conditions are met
+#define OP_COND_SRC (OP_CONDR|OP_SRC) // set only if pre-conditions are met
+#define OP_COND_DST (OP_CONDW|OP_DST) // set only if pre-conditions are met
+#define OP_COND (OP_CONDR|OP_CONDW)
+
+// Bits 16-31 are available for use outside of the opcode table, but they can only
+// be used in INSTRUCTION_OPERAND.Flags, they may conflit with the architecture specific
+// operands. For example, bits 16-31 are used in X86 for AMODE_* and OPTYPE_*
+#define OP_ADDRESS (1<<16)
+#define OP_LOCAL (1<<17)
+#define OP_PARAM (1<<18)
+#define OP_GLOBAL (1<<19)
+#define OP_FAR (1<<20)
+#define OP_IPREL (1<<21)
+
+//
+// X86-specific flags (bits 27-31)
+//
+#define OP_MSR (OP_SYS|OP_UNUSED)
+
+//
+// Other architecture flags
+//
+#define OP_DELAY OP_UNUSED // delayed instruction (e.g., delayed branch that executes after the next instruction)
+
+/////////////////////////////////////////////////////////////////////
+// Architectures
+/////////////////////////////////////////////////////////////////////
+
+typedef enum _ARCHITECTURE_TYPE
+{
+ ARCH_UNKNOWN=0,
+
+ // x86-based
+ ARCH_X86, // 32-bit x86
+ ARCH_X86_16, // 16-bit x86
+ ARCH_X64, // AMD64 and Intel EMD64
+
+ // everything else
+ ARCH_ALPHA,
+ ARCH_ARM,
+ ARCH_DOTNET,
+ ARCH_EFI,
+ ARCH_IA64,
+ ARCH_M68K,
+ ARCH_MIPS,
+ ARCH_PPC,
+ ARCH_SH3,
+ ARCH_SH4,
+ ARCH_SPARC,
+ ARCH_THUMB
+
+} ARCHITECTURE_TYPE;
+
+typedef BOOL (*INIT_INSTRUCTION)(struct _INSTRUCTION *Instruction);
+typedef void (*DUMP_INSTRUCTION)(struct _INSTRUCTION *Instruction, BOOL ShowBytes, BOOL Verbose);
+typedef BOOL (*GET_INSTRUCTION)(struct _INSTRUCTION *Instruction, U8 *Address, U32 Flags);
+typedef U8 *(*FIND_FUNCTION_BY_PROLOGUE)(struct _INSTRUCTION *Instruction, U8 *StartAddress, U8 *EndAddress, U32 Flags);
+
+typedef struct _ARCHITECTURE_FORMAT_FUNCTIONS
+{
+ INIT_INSTRUCTION InitInstruction;
+ DUMP_INSTRUCTION DumpInstruction;
+ GET_INSTRUCTION GetInstruction;
+ FIND_FUNCTION_BY_PROLOGUE FindFunctionByPrologue;
+} ARCHITECTURE_FORMAT_FUNCTIONS;
+
+typedef struct _ARCHITECTURE_FORMAT
+{
+ ARCHITECTURE_TYPE Type;
+ ARCHITECTURE_FORMAT_FUNCTIONS *Functions;
+} ARCHITECTURE_FORMAT;
+
+#define DISASSEMBLER_INITIALIZED 0x1234566F
+#define INSTRUCTION_INITIALIZED 0x1234567F
+
+#include "disasm_x86.h"
+
+typedef struct DECLSPEC_ALIGN(16) _S128
+{
+ U64 Low;
+ S64 High;
+} S128;
+typedef struct DECLSPEC_ALIGN(16) _U128
+{
+ U64 Low;
+ U64 High;
+} U128;
+
+typedef struct _INSTRUCTION_OPERAND
+{
+ U32 Flags;
+ U8 Type : 6;
+ U8 Unused : 2;
+ U16 Length;
+
+
+ // If non-NULL, this indicates the target address of the instruction (e.g., a branch or
+ // a displacement with no base register). However, this address is only reliable if the
+ // image is mapped correctly (e.g., the executable is mapped as an image and fixups have
+ // been applied if it is not at its preferred image base).
+ //
+ // If disassembling a 16-bit DOS application, TargetAddress is in the context of
+ // X86Instruction->Segment. For example, if TargetAddress is the address of a code branch,
+ // it is in the CS segment (unless X86Instruction->HasSegmentOverridePrefix is set). If
+ // TargetAddress is a data pointer, it is in the DS segment (unless
+ // X86Instruction->HasSegmentOverridePrefix is set)
+ U64 TargetAddress;
+ U32 Register;
+
+ union
+ {
+ // All 8/16/32-bit operands are extended to 64-bits automatically
+ // If you want to downcast, check whether Flags & OP_SIGNED is set
+ // Like this:
+ // U32 GetOperand32(OPERAND *Operand)
+ // {
+ // if (Operand->Flags & OP_SIGNED) return (S32)Operand->Value_S64;
+ // else return (U32)Operand->Value_U64;
+ //}
+ U64 Value_U64;
+ S64 Value_S64;
+ U128 Value_U128;
+ U128 Float128;
+ U8 Float80[80];
+ U8 BCD[10];
+ };
+} INSTRUCTION_OPERAND;
+
+typedef struct _INSTRUCTION
+{
+ U32 Initialized;
+ struct _DISASSEMBLER *Disassembler;
+
+ char String[MAX_OPCODE_DESCRIPTION];
+ U8 StringIndex;
+ U64 VirtualAddressDelta;
+
+ U32 Groups; // ITYPE_EXEC, ITYPE_ARITH, etc. -- NOTE groups can be OR'd together
+ INSTRUCTION_TYPE Type; // ITYPE_ADD, ITYPE_RET, etc. -- NOTE there is only one possible type
+
+ U8 *Address;
+ U8 *OpcodeAddress;
+ U32 Length;
+
+ U8 Prefixes[MAX_PREFIX_LENGTH];
+ U32 PrefixCount;
+
+ U8 LastOpcode; // last byte of opcode
+ U8 OpcodeBytes[MAX_OPCODE_LENGTH];
+ U32 OpcodeLength; // excludes any operands and prefixes
+
+ INSTRUCTION_OPERAND Operands[MAX_OPERAND_COUNT];
+ U32 OperandCount;
+
+ X86_INSTRUCTION X86;
+
+ DATA_REFERENCE DataSrc;
+ DATA_REFERENCE DataDst;
+ CODE_BRANCH CodeBranch;
+
+ // Direction depends on which direction the stack grows
+ // For example, on x86 a push results in StackChange < 0 since the stack grows down
+ // This is only relevant if (Group & ITYPE_STACK) is true
+ //
+ // If Groups & ITYPE_STACK is set but StackChange = 0, it means that the change
+ // couldn't be determined (non-constant)
+ LONG StackChange;
+
+ // Used to assist in debugging
+ // If set, the current instruction is doing something that requires special handling
+ // For example, popf can cause tracing to be disabled
+
+ U8 StringAligned : 1; // internal only
+ U8 NeedsEmulation : 1; // instruction does something that re
+ U8 Repeat : 1; // instruction repeats until some condition is met (e.g., REP prefix on X86)
+ U8 ErrorOccurred : 1; // set if instruction is invalid
+ U8 AnomalyOccurred : 1; // set if instruction is anomalous
+ U8 LastInstruction : 1; // tells the iterator callback it is the last instruction
+ U8 CodeBlockFirst: 1;
+ U8 CodeBlockLast : 1;
+} INSTRUCTION;
+
+typedef struct _DISASSEMBLER
+{
+ U32 Initialized;
+ ARCHITECTURE_TYPE ArchType;
+ ARCHITECTURE_FORMAT_FUNCTIONS *Functions;
+ INSTRUCTION Instruction;
+ U32 Stage1Count; // GetInstruction called
+ U32 Stage2Count; // Opcode fully decoded
+ U32 Stage3CountNoDecode; // made it through all checks when DISASM_DECODE is not set
+ U32 Stage3CountWithDecode; // made it through all checks when DISASM_DECODE is set
+} DISASSEMBLER;
+
+#define DISASM_DISASSEMBLE (1<<1)
+#define DISASM_DECODE (1<<2)
+#define DISASM_SUPPRESSERRORS (1<<3)
+#define DISASM_SHOWFLAGS (1<<4)
+#define DISASM_ALIGNOUTPUT (1<<5)
+#define DISASM_DISASSEMBLE_MASK (DISASM_ALIGNOUTPUT|DISASM_SHOWBYTES|DISASM_DISASSEMBLE)
+
+BOOL InitDisassembler(DISASSEMBLER *Disassembler, ARCHITECTURE_TYPE Architecture);
+void CloseDisassembler(DISASSEMBLER *Disassembler);
+INSTRUCTION *GetInstruction(DISASSEMBLER *Disassembler, U64 VirtualAddress, U8 *Address, U32 Flags);
+
+#ifdef __cplusplus
+}
+#endif
+#endif // DISASM_H