Specifically flag multi-byte NOP operands as not-accessed.

New capability - bddisasm can now be instructed whether to decode some instructions as NOPs are as MPX/CET/CLDEMOTE. This is the case for instructions that are mapped onto the wide NOP space: in that case, an encoding might be NOP if the feature is off, but might be something else (even #UD) if the feature is on.
Added NdDecodeWithContext API - this becomes the base decode API; it received the input information filled in a ND_CONTEXT structure, whih has to be initialized only once, and can be reused across calls. The NdInitContext function must be used to initialize the context, as it ensures backwards compatibility by filling new options with default values.
Improvements to the README file.
pull/15/head
Andrei Vlad LUTAS 4 years ago
parent 4328dc4efa
commit ed564dba32

@ -65,7 +65,22 @@ In order to build bddisasm and bdshemu run `make` in the root of the repository.
In order to build disasmtool_lix go to the disasmtool_lix directory and run `make`. The results will be in the bin directory in the disasmtool_lix/build directory.
## Example
## Decoding instructions
### Decoding API
There are 4 decoding functions, but internally, they all do the same, albeit some of them with implicit arguments:
* `NDSTATUS NdDecode(INSTRUX *Instrux, const uint8_t *Code, uint8_t DefCode, uint8_t DefData)` - this API should be used only if you don't care about the length of the input buffer;
* `NDSTATUS NdDecodeEx(INSTRUX *Instrux, const uint8_t *Code, size_t Size, uint8_t DefCode, uint8_t DefData);` - decode instruction from a buffer with maximum length `Size`;
* `NDSTATUS NdDecodeEx2(INSTRUX *Instrux, const uint8_t *Code, size_t Size, uint8_t DefCode, uint8_t DefData, uint8_t DefStack, uint8_t PreferedVendor);` - decode instructions with a preferred vendor;
* `NDSTATUS NdDecodeWithContext(INSTRUX *Instrux, const uint8_t *Code, size_t Size, ND_CONTEXT *Context);` - base decode API; the input parameters - `DefCode`, `DefData`, `DefStack`, `VendMode` and `FeatMode` must all be filled in the `Context` structure before calling this function. The Context structure should also be initialized using `NdInitContext` before the first decode call.
Note that by default, the default vendor `ND_VEND_ANY` is used for decoding (which means that bddisasm will try to decode as much as possible). Also, the default features mask is `ND_FEAT_ALL`, meaning that bddisasm will optimistically try to decode instructions which are mapped onto the wide NOP space as well (for example, MPX or CET). If these parameters must be changed, it is advised to use the `NdDecodeWithContext` API.
Converting decoded instructions to textual disassembly must be done using the `NdToText` API. bddisasm only supports Intel, masm-style syntax.
### Example
Working with bddisasm is very easy. Decoding and printing the disassembly of an instruction is quick & simple:
@ -160,6 +175,26 @@ int main()
}
```
Working with the extended API is also trivial:
```c
INSTRUX ix;
ND_CONTEXT ctx;
uint8_t code[] = { 0x48, 0x8B, 0x48, 0x28 };
// This has to be done only once.
NdInitContext(&ctx);
ctx.DefCode = ND_CODE_64;
ctx.DefData = ND_DATA_64;
ctx.DefStack = ND_STACK_64;
ctx.VendMode = ND_VEND_ANY;
ctx.FeatMode = ND_FEAT_ALL; // Use ND_FEAT_NONE, if you wish to see NOPs instead of MPX/CET/CLDEMOTE instructions.
// From here one, the ctx can be reused for any number of NdDecodeWithContext calls.
NDSTATUS status = NdDecodeWithContext(&ix, code, sizeof(code), &ctx);
...
```
## Credits
The entire Bitdefender HVI team.

@ -3097,7 +3097,6 @@ NdFindInstruction(
const uint8_t *Code,
uint8_t Offset,
size_t Size,
uint8_t Vendor,
ND_INSTRUCTION **InsDef
)
{
@ -3386,9 +3385,9 @@ NdFindInstruction(
case ND_ILUT_VENDOR:
// Vendor redirection. Go to the vendor specific entry.
if (NULL != pTable->Table[Vendor])
if (NULL != pTable->Table[Instrux->VendMode])
{
pTable = (const ND_TABLE *)pTable->Table[Vendor];
pTable = (const ND_TABLE *)pTable->Table[Instrux->VendMode];
}
else
{
@ -3396,6 +3395,26 @@ NdFindInstruction(
}
break;
case ND_ILUT_FEATURE:
// Feature redirection. Normally NOP if feature is not set, but may be something else if feature is set.
if ((NULL != pTable->Table[ND_ILUT_FEATURE_MPX]) && !!(Instrux->FeatMode & ND_FEAT_MPX))
{
pTable = (const ND_TABLE *)pTable->Table[ND_ILUT_FEATURE_MPX];
}
else if ((NULL != pTable->Table[ND_ILUT_FEATURE_CET]) && !!(Instrux->FeatMode & ND_FEAT_CET))
{
pTable = (const ND_TABLE *)pTable->Table[ND_ILUT_FEATURE_CET];
}
else if ((NULL != pTable->Table[ND_ILUT_FEATURE_CLDEMOTE]) && !!(Instrux->FeatMode & ND_FEAT_CLDEMOTE))
{
pTable = (const ND_TABLE *)pTable->Table[ND_ILUT_FEATURE_CLDEMOTE];
}
else
{
pTable = (const ND_TABLE *)pTable->Table[ND_ILUT_FEATURE_NONE];
}
break;
case ND_ILUT_VEX_MMMMM:
pTable = (const ND_TABLE *)pTable->Table[Instrux->Exs.m];
break;
@ -3816,6 +3835,28 @@ NdDecodeEx2(
uint8_t DefStack,
uint8_t Vendor
)
{
ND_CONTEXT opt;
NdInitContext(&opt);
opt.DefCode = DefCode;
opt.DefData = DefData;
opt.DefStack = DefStack;
opt.VendMode = Vendor;
opt.FeatMode = ND_FEAT_ALL; // Optimistically decode everything, as if all features are enabled.
return NdDecodeWithContext(Instrux, Code, Size, &opt);
}
NDSTATUS
NdDecodeWithContext(
INSTRUX *Instrux,
const uint8_t *Code,
size_t Size,
ND_CONTEXT *Context
)
{
NDSTATUS status;
PND_INSTRUCTION pIns;
@ -3842,17 +3883,22 @@ NdDecodeEx2(
return ND_STATUS_INVALID_PARAMETER;
}
if (ND_CODE_64 < DefCode)
if (NULL == Context)
{
return ND_STATUS_INVALID_PARAMETER;
}
if (ND_CODE_64 < Context->DefCode)
{
return ND_STATUS_INVALID_PARAMETER;
}
if (ND_DATA_64 < DefData)
if (ND_DATA_64 < Context->DefData)
{
return ND_STATUS_INVALID_PARAMETER;
}
if (ND_VEND_CYRIX < Vendor)
if (ND_VEND_CYRIX < Context->VendMode)
{
return ND_STATUS_INVALID_PARAMETER;
}
@ -3860,9 +3906,11 @@ NdDecodeEx2(
// Initialize with zero.
nd_memzero(Instrux, sizeof(INSTRUX));
Instrux->DefCode = DefCode;
Instrux->DefData = DefData;
Instrux->DefStack = DefStack;
Instrux->DefCode = (uint8_t)Context->DefCode;
Instrux->DefData = (uint8_t)Context->DefData;
Instrux->DefStack = (uint8_t)Context->DefStack;
Instrux->VendMode = (uint8_t)Context->VendMode;
Instrux->FeatMode = (uint8_t)Context->FeatMode;
// Fetch prefixes. We peek at the first byte, if that's not a prefix, there's no need to call the main decoder.
if (ND_PREF_CODE_NONE != gPrefixesMap[Code[0]])
@ -3882,7 +3930,7 @@ NdDecodeEx2(
}
// Start iterating the tables, in order to extract the instruction entry.
status = NdFindInstruction(Instrux, Code, Instrux->Length, Size, Vendor, &pIns);
status = NdFindInstruction(Instrux, Code, Instrux->Length, Size, &pIns);
if (!ND_SUCCESS(status))
{
return status;
@ -5101,3 +5149,12 @@ NdGetFullAccessMap(
return ND_STATUS_SUCCESS;
}
void
NdInitContext(
ND_CONTEXT *Context
)
{
nd_memzero(Context, sizeof(*Context));
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -330,13 +330,13 @@ const ND_TABLE_INSTRUCTION gXopTable_root_09_01_06_leaf =
const ND_TABLE_INSTRUCTION gXopTable_root_09_01_07_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[1295]
(const void *)&gInstructions[1299]
};
const ND_TABLE_INSTRUCTION gXopTable_root_09_01_04_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[1317]
(const void *)&gInstructions[1321]
};
const ND_TABLE_MODRM_REG gXopTable_root_09_01_modrmreg =
@ -390,7 +390,7 @@ const ND_TABLE_INSTRUCTION gXopTable_root_09_12_reg_00_leaf =
const ND_TABLE_INSTRUCTION gXopTable_root_09_12_reg_01_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[1247]
(const void *)&gInstructions[1251]
};
const ND_TABLE_MODRM_REG gXopTable_root_09_12_reg_modrmreg =
@ -420,127 +420,127 @@ const ND_TABLE_MODRM_MOD gXopTable_root_09_12_modrmmod =
const ND_TABLE_INSTRUCTION gXopTable_root_09_81_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[1668]
(const void *)&gInstructions[1672]
};
const ND_TABLE_INSTRUCTION gXopTable_root_09_80_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[1669]
(const void *)&gInstructions[1673]
};
const ND_TABLE_INSTRUCTION gXopTable_root_09_83_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[1670]
(const void *)&gInstructions[1674]
};
const ND_TABLE_INSTRUCTION gXopTable_root_09_82_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[1671]
(const void *)&gInstructions[1675]
};
const ND_TABLE_INSTRUCTION gXopTable_root_09_c2_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2057]
(const void *)&gInstructions[2061]
};
const ND_TABLE_INSTRUCTION gXopTable_root_09_c3_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2058]
(const void *)&gInstructions[2062]
};
const ND_TABLE_INSTRUCTION gXopTable_root_09_c1_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2059]
(const void *)&gInstructions[2063]
};
const ND_TABLE_INSTRUCTION gXopTable_root_09_cb_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2061]
(const void *)&gInstructions[2065]
};
const ND_TABLE_INSTRUCTION gXopTable_root_09_d2_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2063]
(const void *)&gInstructions[2067]
};
const ND_TABLE_INSTRUCTION gXopTable_root_09_d3_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2064]
(const void *)&gInstructions[2068]
};
const ND_TABLE_INSTRUCTION gXopTable_root_09_d1_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2065]
(const void *)&gInstructions[2069]
};
const ND_TABLE_INSTRUCTION gXopTable_root_09_db_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2066]
(const void *)&gInstructions[2070]
};
const ND_TABLE_INSTRUCTION gXopTable_root_09_d6_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2067]
(const void *)&gInstructions[2071]
};
const ND_TABLE_INSTRUCTION gXopTable_root_09_d7_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2068]
(const void *)&gInstructions[2072]
};
const ND_TABLE_INSTRUCTION gXopTable_root_09_c6_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2070]
(const void *)&gInstructions[2074]
};
const ND_TABLE_INSTRUCTION gXopTable_root_09_c7_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2071]
(const void *)&gInstructions[2075]
};
const ND_TABLE_INSTRUCTION gXopTable_root_09_e1_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2073]
(const void *)&gInstructions[2077]
};
const ND_TABLE_INSTRUCTION gXopTable_root_09_e3_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2075]
(const void *)&gInstructions[2079]
};
const ND_TABLE_INSTRUCTION gXopTable_root_09_e2_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2078]
(const void *)&gInstructions[2082]
};
const ND_TABLE_INSTRUCTION gXopTable_root_09_90_00_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2240]
(const void *)&gInstructions[2244]
};
const ND_TABLE_INSTRUCTION gXopTable_root_09_90_01_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2241]
(const void *)&gInstructions[2245]
};
const ND_TABLE_VEX_W gXopTable_root_09_90_w =
@ -555,13 +555,13 @@ const ND_TABLE_VEX_W gXopTable_root_09_90_w =
const ND_TABLE_INSTRUCTION gXopTable_root_09_92_00_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2243]
(const void *)&gInstructions[2247]
};
const ND_TABLE_INSTRUCTION gXopTable_root_09_92_01_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2244]
(const void *)&gInstructions[2248]
};
const ND_TABLE_VEX_W gXopTable_root_09_92_w =
@ -576,13 +576,13 @@ const ND_TABLE_VEX_W gXopTable_root_09_92_w =
const ND_TABLE_INSTRUCTION gXopTable_root_09_93_00_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2246]
(const void *)&gInstructions[2250]
};
const ND_TABLE_INSTRUCTION gXopTable_root_09_93_01_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2247]
(const void *)&gInstructions[2251]
};
const ND_TABLE_VEX_W gXopTable_root_09_93_w =
@ -597,13 +597,13 @@ const ND_TABLE_VEX_W gXopTable_root_09_93_w =
const ND_TABLE_INSTRUCTION gXopTable_root_09_91_00_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2249]
(const void *)&gInstructions[2253]
};
const ND_TABLE_INSTRUCTION gXopTable_root_09_91_01_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2250]
(const void *)&gInstructions[2254]
};
const ND_TABLE_VEX_W gXopTable_root_09_91_w =
@ -618,13 +618,13 @@ const ND_TABLE_VEX_W gXopTable_root_09_91_w =
const ND_TABLE_INSTRUCTION gXopTable_root_09_98_00_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2257]
(const void *)&gInstructions[2261]
};
const ND_TABLE_INSTRUCTION gXopTable_root_09_98_01_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2258]
(const void *)&gInstructions[2262]
};
const ND_TABLE_VEX_W gXopTable_root_09_98_w =
@ -639,13 +639,13 @@ const ND_TABLE_VEX_W gXopTable_root_09_98_w =
const ND_TABLE_INSTRUCTION gXopTable_root_09_9a_00_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2259]
(const void *)&gInstructions[2263]
};
const ND_TABLE_INSTRUCTION gXopTable_root_09_9a_01_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2260]
(const void *)&gInstructions[2264]
};
const ND_TABLE_VEX_W gXopTable_root_09_9a_w =
@ -660,13 +660,13 @@ const ND_TABLE_VEX_W gXopTable_root_09_9a_w =
const ND_TABLE_INSTRUCTION gXopTable_root_09_9b_00_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2261]
(const void *)&gInstructions[2265]
};
const ND_TABLE_INSTRUCTION gXopTable_root_09_9b_01_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2262]
(const void *)&gInstructions[2266]
};
const ND_TABLE_VEX_W gXopTable_root_09_9b_w =
@ -681,13 +681,13 @@ const ND_TABLE_VEX_W gXopTable_root_09_9b_w =
const ND_TABLE_INSTRUCTION gXopTable_root_09_99_00_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2263]
(const void *)&gInstructions[2267]
};
const ND_TABLE_INSTRUCTION gXopTable_root_09_99_01_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2264]
(const void *)&gInstructions[2268]
};
const ND_TABLE_VEX_W gXopTable_root_09_99_w =
@ -702,13 +702,13 @@ const ND_TABLE_VEX_W gXopTable_root_09_99_w =
const ND_TABLE_INSTRUCTION gXopTable_root_09_94_00_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2265]
(const void *)&gInstructions[2269]
};
const ND_TABLE_INSTRUCTION gXopTable_root_09_94_01_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2266]
(const void *)&gInstructions[2270]
};
const ND_TABLE_VEX_W gXopTable_root_09_94_w =
@ -723,13 +723,13 @@ const ND_TABLE_VEX_W gXopTable_root_09_94_w =
const ND_TABLE_INSTRUCTION gXopTable_root_09_95_01_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2267]
(const void *)&gInstructions[2271]
};
const ND_TABLE_INSTRUCTION gXopTable_root_09_95_00_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2278]
(const void *)&gInstructions[2282]
};
const ND_TABLE_VEX_W gXopTable_root_09_95_w =
@ -744,13 +744,13 @@ const ND_TABLE_VEX_W gXopTable_root_09_95_w =
const ND_TABLE_INSTRUCTION gXopTable_root_09_96_01_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2268]
(const void *)&gInstructions[2272]
};
const ND_TABLE_INSTRUCTION gXopTable_root_09_96_00_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2269]
(const void *)&gInstructions[2273]
};
const ND_TABLE_VEX_W gXopTable_root_09_96_w =
@ -765,13 +765,13 @@ const ND_TABLE_VEX_W gXopTable_root_09_96_w =
const ND_TABLE_INSTRUCTION gXopTable_root_09_97_00_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2276]
(const void *)&gInstructions[2280]
};
const ND_TABLE_INSTRUCTION gXopTable_root_09_97_01_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2277]
(const void *)&gInstructions[2281]
};
const ND_TABLE_VEX_W gXopTable_root_09_97_w =
@ -1049,13 +1049,13 @@ const ND_TABLE_OPCODE gXopTable_root_09_opcode =
const ND_TABLE_INSTRUCTION gXopTable_root_08_a2_00_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[1943]
(const void *)&gInstructions[1947]
};
const ND_TABLE_INSTRUCTION gXopTable_root_08_a2_01_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[1944]
(const void *)&gInstructions[1948]
};
const ND_TABLE_VEX_W gXopTable_root_08_a2_w =
@ -1070,133 +1070,133 @@ const ND_TABLE_VEX_W gXopTable_root_08_a2_w =
const ND_TABLE_INSTRUCTION gXopTable_root_08_cc_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[1973]
(const void *)&gInstructions[1977]
};
const ND_TABLE_INSTRUCTION gXopTable_root_08_ce_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[1974]
(const void *)&gInstructions[1978]
};
const ND_TABLE_INSTRUCTION gXopTable_root_08_cf_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[1979]
(const void *)&gInstructions[1983]
};
const ND_TABLE_INSTRUCTION gXopTable_root_08_ec_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[1980]
(const void *)&gInstructions[1984]
};
const ND_TABLE_INSTRUCTION gXopTable_root_08_ee_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[1981]
(const void *)&gInstructions[1985]
};
const ND_TABLE_INSTRUCTION gXopTable_root_08_ef_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[1982]
(const void *)&gInstructions[1986]
};
const ND_TABLE_INSTRUCTION gXopTable_root_08_ed_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[1983]
(const void *)&gInstructions[1987]
};
const ND_TABLE_INSTRUCTION gXopTable_root_08_cd_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[1984]
(const void *)&gInstructions[1988]
};
const ND_TABLE_INSTRUCTION gXopTable_root_08_9e_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2093]
(const void *)&gInstructions[2097]
};
const ND_TABLE_INSTRUCTION gXopTable_root_08_9f_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2094]
(const void *)&gInstructions[2098]
};
const ND_TABLE_INSTRUCTION gXopTable_root_08_97_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2095]
(const void *)&gInstructions[2099]
};
const ND_TABLE_INSTRUCTION gXopTable_root_08_8e_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2096]
(const void *)&gInstructions[2100]
};
const ND_TABLE_INSTRUCTION gXopTable_root_08_8f_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2097]
(const void *)&gInstructions[2101]
};
const ND_TABLE_INSTRUCTION gXopTable_root_08_87_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2098]
(const void *)&gInstructions[2102]
};
const ND_TABLE_INSTRUCTION gXopTable_root_08_86_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2099]
(const void *)&gInstructions[2103]
};
const ND_TABLE_INSTRUCTION gXopTable_root_08_85_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2100]
(const void *)&gInstructions[2104]
};
const ND_TABLE_INSTRUCTION gXopTable_root_08_96_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2101]
(const void *)&gInstructions[2105]
};
const ND_TABLE_INSTRUCTION gXopTable_root_08_95_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2102]
(const void *)&gInstructions[2106]
};
const ND_TABLE_INSTRUCTION gXopTable_root_08_a6_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2103]
(const void *)&gInstructions[2107]
};
const ND_TABLE_INSTRUCTION gXopTable_root_08_b6_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2104]
(const void *)&gInstructions[2108]
};
const ND_TABLE_INSTRUCTION gXopTable_root_08_a3_00_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2229]
(const void *)&gInstructions[2233]
};
const ND_TABLE_INSTRUCTION gXopTable_root_08_a3_01_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2230]
(const void *)&gInstructions[2234]
};
const ND_TABLE_VEX_W gXopTable_root_08_a3_w =
@ -1211,25 +1211,25 @@ const ND_TABLE_VEX_W gXopTable_root_08_a3_w =
const ND_TABLE_INSTRUCTION gXopTable_root_08_c0_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2239]
(const void *)&gInstructions[2243]
};
const ND_TABLE_INSTRUCTION gXopTable_root_08_c2_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2242]
(const void *)&gInstructions[2246]
};
const ND_TABLE_INSTRUCTION gXopTable_root_08_c3_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2245]
(const void *)&gInstructions[2249]
};
const ND_TABLE_INSTRUCTION gXopTable_root_08_c1_leaf =
{
ND_ILUT_INSTRUCTION,
(const void *)&gInstructions[2248]
(const void *)&gInstructions[2252]
};
const ND_TABLE_OPCODE gXopTable_root_08_opcode =

@ -26,6 +26,8 @@ typedef enum _ND_ILUT_TYPE
// 4 (default op size 16), 5 (default op size 32), 6 (default op size 64),
ND_ILUT_VENDOR, // Preferred vendor is used to transition. Default is entry 0. Otherwise, preferred
// vendor selects an alternate entry.
ND_ILUT_FEATURE, // Some instructions are mapped onto wide NOP space. They will be decoded only if the
// associated feature is set during decoding.
ND_ILUT_VEX_MMMMM, // Table contains 32 entries. Next entry is vex/xop/evex.mmmmm
ND_ILUT_VEX_PP, // Table contains 4 entries. Next entry is vex/xop/evex.pp
ND_ILUT_VEX_L, // Table contains 4 entries. Next entry is vex/xop.l or evex.l'l
@ -66,6 +68,12 @@ typedef enum _ND_ILUT_TYPE
#define ND_ILUT_INDEX_AUX_F3 4
#define ND_ILUT_INDEX_AUX_REP 5
#define ND_ILUT_FEATURE_NONE 0
#define ND_ILUT_FEATURE_MPX 1
#define ND_ILUT_FEATURE_CET 2
#define ND_ILUT_FEATURE_CLDEMOTE 3
@ -124,6 +132,12 @@ typedef struct _ND_TABLE_VENDOR
const void *Table[6];
} ND_TABLE_VENDOR;
typedef struct _ND_TABLE_FEATURE
{
uint32_t Type;
const void *Table[4];
} ND_TABLE_FEATURE;
typedef struct _ND_TABLE_DSIZE
{
uint32_t Type;

@ -32,7 +32,8 @@ typedef struct _DISASM_OPTIONS
BOOLEAN Print; // Print instruction disassembly, if true.
uint8_t Mode; // Mode - 16, 32 or 64 bit mode.
uint8_t Ring; // Ring - 0, 1, 2 or 3.
uint8_t Vendor; // Proffered vendor.
uint8_t Vendor; // Preffered vendor.
uint8_t Feature; // Used features.
char *FileName; // Input file, if any.
size_t ShemuRegs[NDR_R15 + 1];
BOOLEAN UseShemuRegs;
@ -1013,17 +1014,25 @@ handle_search(
{
NDSTATUS status;
INSTRUX instrux;
ND_CONTEXT ctx;
SIZE_T rip = 0, i;
char text[ND_MIN_BUF_SIZE], target[ND_MIN_BUF_SIZE];
char *token1, *token2, *ctx1, *ctx2;
BOOLEAN match;
NdInitContext(&ctx);
ctx.DefCode = Options->Mode;
ctx.DefData = Options->Mode;
ctx.DefStack = Options->Mode;
ctx.VendMode = Options->Vendor;
ctx.FeatMode = Options->Feature;
// Disassemble
rip = 0;
while (rip < Options->Size)
{
status = NdDecodeEx2(&instrux, Options->Buffer + rip, Options->Size - rip, Options->Mode,
Options->Mode, Options->Mode, ND_VEND_ANY);
status = NdDecodeWithContext(&instrux, Options->Buffer + rip, Options->Size - rip, &ctx);
if (!ND_SUCCESS(status))
{
goto _continue;
@ -1100,10 +1109,15 @@ _continue_match:
print_instruction(rip, &instrux, Options);
rip2 += instrux.Length;
instrux.DefCode = Options->Mode;
instrux.DefData = Options->Mode;
instrux.DefStack = Options->Mode;
instrux.VendMode = Options->Vendor;
instrux.FeatMode = Options->Feature;
while (rip2 < Options->Size && count++ < 8)
{
status = NdDecodeEx2(&instrux, Options->Buffer + rip2, Options->Size - rip2, Options->Mode,
Options->Mode, Options->Mode, ND_VEND_ANY);
status = NdDecodeWithContext(&instrux, Options->Buffer + rip2, Options->Size - rip2, &ctx);
if (!ND_SUCCESS(status))
{
printf("%p ERROR\n", (void*)rip2);
@ -1136,13 +1150,21 @@ handle_disasm(
{
NDSTATUS status;
INSTRUX instrux;
ND_CONTEXT ctx = { 0 };
QWORD icount = 0, istart = 0, iend = 0, start = 0, end = 0, itotal = 0;
SIZE_T rip = 0, fsize = Options->Size;
PBYTE buffer = Options->Buffer;
BYTE mode = Options->Mode, vend = Options->Vendor;
start = clock();
NdInitContext(&ctx);
ctx.DefCode = Options->Mode;
ctx.DefData = Options->Mode;
ctx.DefStack = Options->Mode;
ctx.VendMode = Options->Vendor;
ctx.FeatMode = Options->Feature;
// Disassemble
rip = Options->Offset;
while (rip < Options->Size)
@ -1150,7 +1172,7 @@ handle_disasm(
icount++;
istart = __rdtsc();
status = NdDecodeEx2(&instrux, buffer + rip, fsize - rip, mode, mode, mode, vend);
status = NdDecodeWithContext(&instrux, buffer + rip, fsize - rip, &ctx);
iend = __rdtsc();
itotal += iend - istart;
@ -1565,7 +1587,7 @@ int main(
DWORD fsize, offset;
SIZE_T rip;
char text[ND_MIN_BUF_SIZE], *fname, *target, *shemuCtxFname;
BYTE mode, print, highlight, fmode, hmode, stats, exi, vend, search, isShemu, isShemuCtxf, isKernel;
BYTE mode, print, highlight, fmode, hmode, stats, exi, vend, feat, search, isShemu, isShemuCtxf, isKernel;
INT ret, i;
BYTE hexbuf[256], *buffer;
DISASM_OPTIONS options;
@ -1582,6 +1604,7 @@ int main(
exi = 0;
offset = 0;
search = 0;
feat = ND_FEAT_ALL;
vend = ND_VEND_ANY;
fname = NULL;
mode = ND_CODE_16;
@ -1614,7 +1637,8 @@ int main(
printf(" -o offset start disasm at specified offset\n");
printf(" -r rip use the provided RIP\n");
printf(" -b[16|32|64] set decoding mode; default is 16\n");
printf(" -v[intel|amd|cyrix|any] set preferred vendor\n");
printf(" -v[intel|amd|cyrix|mpx|any] set preferred vendor\n");
printf(" -t[none|all|mpx|cet|cldm] set preferred feature mode; default is all\n");
printf(" -s \"ins\" search for the given instructions\n");
printf(" -nv don't print disassembly\n");
printf(" -iv display statistics\n");
@ -1747,6 +1771,41 @@ int main(
{
vend = ND_VEND_ANY;
}
else if (0 == strcmp(argv[i], "-tall"))
{
feat = ND_FEAT_ALL;
}
else if (0 == strcmp(argv[i], "-tmpx"))
{
if (feat == ND_FEAT_ALL)
{
feat = 0;
}
feat |= ND_FEAT_MPX;
}
else if (0 == strcmp(argv[i], "-tcet"))
{
if (feat == ND_FEAT_ALL)
{
feat = 0;
}
feat |= ND_FEAT_CET;
}
else if (0 == strcmp(argv[i], "-tcldm"))
{
if (feat == ND_FEAT_ALL)
{
feat = 0;
}
feat |= ND_FEAT_CLDEMOTE;
}
else if (0 == strcmp(argv[i], "-tnone"))
{
feat = ND_FEAT_NONE;
}
else if (0 == strcmp(argv[i], "-nv"))
{
print = 0;
@ -1877,6 +1936,7 @@ int main(
options.Target = target;
options.Print = print;
options.Vendor = vend;
options.Feature = feat;
options.Rip = rip;
if (isShemu)

@ -28,6 +28,18 @@
#define ND_VEND_GEODE 3 // Prefer Geode.
#define ND_VEND_CYRIX 4 // Prefer Cyrix.
//
// These control what instructions should be decoded if they map onto the wide NOP space (0F 1A and 0F 1B). Those are
// tricky, because they might be NOP if the feature is disabled, but might be something else (even #UD) if the feature
// is enabled. Ergo, we allow the user to select whether said feature is on or off, so that he controls whether he
// sees the NOPs or the MPX/CET/CLDEMOTE/etc. instructions instead.
//
#define ND_FEAT_NONE 0x00 // No feature/mode enabled.
#define ND_FEAT_MPX 0x01 // MPX support enabled.
#define ND_FEAT_CET 0x02 // CET support enabled.
#define ND_FEAT_CLDEMOTE 0x04 // CLDEMOTE support enabled.
#define ND_FEAT_ALL 0xFF // Decode as if all features are enabled. This is default.
//
// Code type
//
@ -1208,6 +1220,8 @@ typedef struct _INSTRUX
uint8_t DefCode:4; // ND_CODE_*. Indicates disassembly mode.
uint8_t DefData:4; // ND_DATA_*. Indicates default data size.
uint8_t DefStack:4; // ND_STACK_*. Indicates default stack pointer width.
uint8_t VendMode:4; // ND_VEND_*. Indicates vendor mode.
uint8_t FeatMode; // ND_FEAT_*. Indicates which features are enabled.
uint8_t EncMode:4; // ND_ENCM_*. Indicates encoding mode.
uint8_t VexMode:4; // ND_VEX_*. Indicates the VEX mode, if any.
uint8_t AddrMode:4; // ND_ADDR_*. Indicates addressing mode.
@ -1215,7 +1229,7 @@ typedef struct _INSTRUX
uint8_t EfOpMode:4; // ND_OPSZ_*. Indicates effective operand mode/size.
uint8_t VecMode:4; // ND_VECM_*. Indicates vector length.
uint8_t EfVecMode:4; // ND_VECM_*. Indicates effective vector length.
// Prefixes.
bool HasRex:1; // TRUE - REX is present.
bool HasVex:1; // TRUE - VEX is present.
@ -1394,7 +1408,7 @@ typedef struct _INSTRUX
ND_VALID_MODES ValidModes; // Valid CPU modes for the instruction.
ND_VALID_PREFIXES ValidPrefixes; // Indicates which prefixes are valid for this instruction.
ND_VALID_DECORATORS ValidDecorators; // What decorators are accepted by the instruction.
uint64_t Reserved1; // Padding purpose. Aligns the mnemonic to 8 bytes.
uint8_t Reserved1[3]; // Padding purpose. Aligns the mnemonic to 8 bytes.
char Mnemonic[ND_MAX_MNEMONIC_LENGTH]; // Instruction mnemonic.
uint8_t OpCodeBytes[3]; // Opcode bytes - escape codes and main op code
uint8_t PrimaryOpCode; // Main/nominal opcode
@ -1405,7 +1419,22 @@ typedef struct _INSTRUX
//
// API
// Decoder context. Such a structure must be passed to the NdDecodeWithContext API. This structure must be initialized
// only once, and then it can be re-used across NdDecodeWithContext calls.
//
typedef struct _ND_CONTEXT
{
uint64_t DefCode : 4;
uint64_t DefData : 4;
uint64_t DefStack : 4;
uint64_t VendMode : 4;
uint64_t FeatMode : 8;
uint64_t Reserved : 40;
} ND_CONTEXT;
//
// Returns the bddisasm version.
//
void
NdGetVersion(
@ -1416,6 +1445,12 @@ NdGetVersion(
char **BuildTime
);
//
// Decode one instruction. Note that this is equivalent to:
// NdDecodeEx(Instrux, Code, ND_MAX_INSTRUCTION_LEN, DefCode, DefData).
// This version should be used if the caller doesn't care about the length of the buffer. Otherwise, use the other
// decode API.
//
NDSTATUS
NdDecode(
INSTRUX *Instrux,
@ -1424,6 +1459,13 @@ NdDecode(
uint8_t DefData
);
//
// Decode one instruction. Note that this is equivalent to:
// NdDecodeEx2(Instrux, Code, Size, DefCode, DefData, DefCode, ND_VEND_ANY).
// By default, the used vendor will be ND_VEND_ANY, so all instructions will be decoded.
// By default, the feature mode will be ND_FEAT_ALL, so all instructions will be decoded (but may yield error where
// otherwise a NOP would be encoded - use ND_FEAT_NONE in that case).
//
NDSTATUS
NdDecodeEx(
INSTRUX *Instrux,
@ -1433,6 +1475,9 @@ NdDecodeEx(
uint8_t DefData
);
//
// Fills a ND_CONTEXT structure, and calls NdDecodeWithContext. The feature mode will be ND_FEAT_ALL by default.
//
NDSTATUS
NdDecodeEx2(
INSTRUX *Instrux,
@ -1444,6 +1489,26 @@ NdDecodeEx2(
uint8_t PreferedVendor
);
//
// This API received a decode context, where it expects DefCode, DefData, DefStack, VendMode and FeatMode to be
// already initialized. The Context will not be modified by the decoder, so it can be reused across decode calls.
// The Context should initially be initialized using NdInitContext. This will ensure backwards compatibility
// by setting new fields to default values.
// Note that this is the base decoding API, and this ends up being called by all the other decoding APIs, after
// providing default arguments and filling them in the Context structure. For maximum speed, use this instead of
// the others.
//
NDSTATUS
NdDecodeWithContext(
INSTRUX *Instrux,
const uint8_t *Code,
size_t Size,
ND_CONTEXT *Context
);
//
// Convert the given instruction into textual representation (Intel syntax).
//
NDSTATUS
NdToText(
const INSTRUX *Instrux,
@ -1452,17 +1517,31 @@ NdToText(
char *Buffer
);
//
// Returns true if the instruction is RIP relative. Note that this function is kept for backwards compatibility, since
// there already is a IsRipRelative field inside INSTRUX.
//
bool
NdIsInstruxRipRelative(
const INSTRUX *Instrux
);
//
// Returns an access map that contains the access for each register.
//
NDSTATUS
NdGetFullAccessMap(
const INSTRUX *Instrux,
ND_ACCESS_MAP *AccessMap
);
//
// Initialize the decoder context.
//
void
NdInitContext(
ND_CONTEXT *Context
);
// #pragma warning(default: 4214) // Bitfield in type other than int.
// #pragma warning(default: 4201) // Nonstandard extension used: nameless struct/union.

@ -6,7 +6,7 @@
#define DISASM_VER_H
#define DISASM_VERSION_MAJOR 1
#define DISASM_VERSION_MINOR 27
#define DISASM_VERSION_MINOR 28
#define DISASM_VERSION_REVISION 0
#endif // DISASM_VER_H

@ -635,6 +635,8 @@ class Instruction():
self.RedRex = self.RedRexW = self.RedRep = self.Red64 = self.RedF3 = False
# Misc - vendor
self.Vendor = None
# Misc - feature.
self.Feature = None
# XOP, VEX and EVEX classes.
self.Vex = self.Xop = self.Evex = self.Mvex = False
@ -770,6 +772,8 @@ class Instruction():
self.Opcodes.append(int(t, 16))
elif t in ['intel', 'amd', 'via', 'cyrix']:
self.Vendor = t
elif t in ['mpx', 'cet', 'cldm']:
self.Feature = t
elif 'vsib' == t:
self.HasVsib = True
if 'VSIB' not in self.Flags:
@ -874,7 +878,7 @@ class Instruction():
self.Spec = { "mmmmm" : e[0], "opcodes" : e[1], "modrm" : e[2], "pp" : e[3], "l" : e[4], "w" : e[5] }
else:
self.Spec = { "opcodes" : e[0], "modrm" : e[1], "mpre" : e[2], "mode" : e[3], "dsize" : e[4], \
"asize" : e[5], "opre" : e[6], "vendor" : e[7] }
"asize" : e[5], "opre" : e[6], "vendor" : e[7], "feature": e[8] }
def process_operands(self, ops, imp = False):
p = 1
@ -979,7 +983,7 @@ class Instruction():
if self.RedRep:
oprefixes.append('rep')
# Vendor redirection, if any.
return (opcodes, modrm, mprefixes, mode, dsize, asize, oprefixes, self.Vendor)
return (opcodes, modrm, mprefixes, mode, dsize, asize, oprefixes, self.Vendor, self.Feature)
def __str__(self):

@ -393,6 +393,11 @@ indexes = {
"amd" : 2,
"geode" : 3,
"cyrix" : 4,
# Feature redirection.
"mpx" : 1,
"cet" : 2,
"cldm" : 3,
}
ilut = {
@ -409,6 +414,7 @@ ilut = {
"asize" : ("ND_ILUT_ASIZE", 4, "ND_TABLE_ASIZE"),
"auxiliary" : ("ND_ILUT_AUXILIARY", 6, "ND_TABLE_AUXILIARY"),
"vendor" : ("ND_ILUT_VENDOR", 6, "ND_TABLE_VENDOR"),
"feature" : ("ND_ILUT_FEATURE", 4, "ND_TABLE_FEATURE"),
"mmmmm" : ("ND_ILUT_VEX_MMMMM", 32, "ND_TABLE_VEX_MMMMM"),
"pp" : ("ND_ILUT_VEX_PP", 4, "ND_TABLE_VEX_PP"),
"l" : ("ND_ILUT_VEX_L", 4, "ND_TABLE_VEX_L"),
@ -566,8 +572,8 @@ disasmlib.Instruction.cdef = cdef_instruction
def group_instructions(ilist):
d = { }
is3dnow = False
priorities = ["opcode", "vendor", "modrmmod", "modrmreg", "modrmmodpost", "modrmrm", "mprefix", "mode", "dsize", \
"asize", "auxiliary", "_"]
priorities = ["opcode", "vendor", "feature", "modrmmod", "modrmreg", "modrmmodpost", "modrmrm", "mprefix", "mode", \
"dsize", "asize", "auxiliary", "_"]
for i in ilist:
if '3DNOW' in i.Flags:
@ -584,8 +590,11 @@ def group_instructions(ilist):
if "__TYPE__" not in d or d["__TYPE__"] in priorities[-1:]:
d["__TYPE__"] = "mprefix"
elif i.Spec["vendor"]:
if "__TYPE__" not in d or d["__TYPE__"] in priorities[-10:]:
if "__TYPE__" not in d or d["__TYPE__"] in priorities[-11:]:
d["__TYPE__"] = "vendor"
elif i.Spec["feature"]:
if "__TYPE__" not in d or d["__TYPE__"] in priorities[-10:]:
d["__TYPE__"] = "feature"
elif i.Spec["modrm"]["mod"]:
if "__TYPE__" not in d or d["__TYPE__"] in priorities[-9:]:
d["__TYPE__"] = "modrmmod"
@ -749,9 +758,21 @@ def group_instructions(ilist):
# Remove the vendor redirector
if p != "None":
i.Spec["vendor"] = None
elif d["__TYPE__"] == "feature":
if not i.Spec["feature"]:
p = "None"
else:
p = i.Spec["feature"]
if p not in d:
d[p] = [i]
else:
d[p].append(i)
# Remove the vendor redirector
if p != "None":
i.Spec["feature"] = None
else:
print("Don't know what to do!")
raise Exception("WTF???")
raise Exception("Unknwon redirection type.")
return d
@ -884,7 +905,7 @@ def group_instructions_vex_xop_evex(ilist):
i.Spec["w"] = None
else:
print("Don't know what to do!")
raise Exception("WTF???")
raise Exception("Unknown redirection type.")
return d

@ -82,21 +82,21 @@ WBNOINVD nil nil [ a0xF3 0x0F 0x09]
CL1INVMB nil nil [ 0x0F 0x0A] s:SCC, t:SYSTEM
UD2 nil nil [ 0x0F 0x0B] s:PPRO, t:MISC
PREFETCHE Mb nil [ 0x0F 0x0D /0:mem] s:PREFETCH_NOP, t:PREFETCH, w:P
NOP Ev,Gv nil [ 0x0F 0x0D /0:reg] s:PPRO, t:NOP, w:R|R
NOP Ev,Gv nil [ 0x0F 0x0D /0:reg] s:PPRO, t:NOP, w:N|N
PREFETCHW Mb nil [ 0x0F 0x0D /1:mem] s:PREFETCH_NOP, t:PREFETCH, w:P
NOP Ev,Gv nil [ 0x0F 0x0D /1:reg] s:PPRO, t:NOP, w:R|R
NOP Ev,Gv nil [ 0x0F 0x0D /1:reg] s:PPRO, t:NOP, w:N|N
PREFETCHWT1 Mb nil [ 0x0F 0x0D /2:mem] s:PREFETCH_NOP, t:PREFETCH, w:P
NOP Ev,Gv nil [ 0x0F 0x0D /2:reg] s:PPRO, t:NOP, w:R|R
NOP Ev,Gv nil [ 0x0F 0x0D /2:reg] s:PPRO, t:NOP, w:N|N
PREFETCHM Mb nil [ 0x0F 0x0D /3:mem] s:PREFETCH_NOP, t:PREFETCH, w:P
NOP Ev,Gv nil [ 0x0F 0x0D /3:reg] s:PPRO, t:NOP, w:R|R
NOP Ev,Gv nil [ 0x0F 0x0D /3:reg] s:PPRO, t:NOP, w:N|N
PREFETCH Mb nil [ 0x0F 0x0D /4:mem] s:PREFETCH_NOP, t:PREFETCH, w:P
NOP Ev,Gv nil [ 0x0F 0x0D /4:reg] s:PPRO, t:NOP, w:R|R
NOP Ev,Gv nil [ 0x0F 0x0D /4:reg] s:PPRO, t:NOP, w:N|N
PREFETCH Mb nil [ 0x0F 0x0D /5:mem] s:PREFETCH_NOP, t:PREFETCH, w:P
NOP Ev,Gv nil [ 0x0F 0x0D /5:reg] s:PPRO, t:NOP, w:R|R
NOP Ev,Gv nil [ 0x0F 0x0D /5:reg] s:PPRO, t:NOP, w:N|N
PREFETCH Mb nil [ 0x0F 0x0D /6:mem] s:PREFETCH_NOP, t:PREFETCH, w:P
NOP Ev,Gv nil [ 0x0F 0x0D /6:reg] s:PPRO, t:NOP, w:R|R
NOP Ev,Gv nil [ 0x0F 0x0D /6:reg] s:PPRO, t:NOP, w:N|N
PREFETCH Mb nil [ 0x0F 0x0D /7:mem] s:PREFETCH_NOP, t:PREFETCH, w:P
NOP Ev,Gv nil [ 0x0F 0x0D /7:reg] s:PPRO, t:NOP, w:R|R
NOP Ev,Gv nil [ 0x0F 0x0D /7:reg] s:PPRO, t:NOP, w:N|N
FEMMS nil nil [ 0x0F 0x0E] s:3DNOW, t:MMX, c:FEMMS
@ -126,72 +126,83 @@ MOVSHDUP Vx,Wx nil [ 0xF3 0x0F 0x16 /r
MOVHPS Mq,Vq nil [ NP 0x0F 0x17 /r:mem] s:SSE, t:DATAXFER, w:W|R, e:5
MOVHPD Mq,Vq nil [ 0x66 0x0F 0x17 /r:mem] s:SSE2, t:DATAXFER, w:W|R, e:5
PREFETCHNTA Mb nil [ 0x0F 0x18 /0:mem] s:SSE, t:PREFETCH, w:P
NOP Ev nil [ 0x0F 0x18 /0:reg] s:PPRO, t:WIDENOP, w:R
NOP Ev nil [ 0x0F 0x18 /0:reg] s:PPRO, t:WIDENOP, w:N
PREFETCHT0 Mb nil [ 0x0F 0x18 /1:mem] s:SSE, t:PREFETCH, w:P
NOP Ev nil [ 0x0F 0x18 /1:reg] s:PPRO, t:WIDENOP, w:R
NOP Ev nil [ 0x0F 0x18 /1:reg] s:PPRO, t:WIDENOP, w:N
PREFETCHT1 Mb nil [ 0x0F 0x18 /2:mem] s:SSE, t:PREFETCH, w:P
NOP Ev nil [ 0x0F 0x18 /2:reg] s:PPRO, t:WIDENOP, w:R
NOP Ev nil [ 0x0F 0x18 /2:reg] s:PPRO, t:WIDENOP, w:N
PREFETCHT2 Mb nil [ 0x0F 0x18 /3:mem] s:SSE, t:PREFETCH, w:P
NOP Ev nil [ 0x0F 0x18 /3:reg] s:PPRO, t:WIDENOP, w:R
NOP Ev nil [ 0x0F 0x18 /4] s:PPRO, t:WIDENOP, w:R
NOP Ev nil [ 0x0F 0x18 /5] s:PPRO, t:WIDENOP, w:R
NOP Ev nil [ 0x0F 0x18 /6] s:PPRO, t:WIDENOP, w:R
NOP Ev nil [ 0x0F 0x18 /7] s:PPRO, t:WIDENOP, w:R
NOP Ev nil [ 0x0F 0x19 /r] s:PPRO, t:WIDENOP, w:R
NOP Ev nil [ 0x0F 0x18 /3:reg] s:PPRO, t:WIDENOP, w:N
NOP Ev nil [ 0x0F 0x18 /4] s:PPRO, t:WIDENOP, w:N
NOP Ev nil [ 0x0F 0x18 /5] s:PPRO, t:WIDENOP, w:N
NOP Ev nil [ 0x0F 0x18 /6] s:PPRO, t:WIDENOP, w:N
NOP Ev nil [ 0x0F 0x18 /7] s:PPRO, t:WIDENOP, w:N
NOP Ev nil [ 0x0F 0x19 /r] s:PPRO, t:WIDENOP, w:N
# MPX instructions. According to the SDM, MPX instructions have 64 bit op & address size in 64 bit mode, no matter
# if 0x66 or 0x67 prefixes are used. 16 bit addressing cause #UD. However, these checks are not handled here (note
# that Xed doesn't do those checks either).
BNDLDX rBl,Mmib nil [ 0x0F 0x1A /r:mem mib] s:MPX, t:MPX, w:W|R, a:AG|NOA16|NORIPREL|I67
NOP Gv,Ev nil [ 0x0F 0x1A /r:reg] s:PPRO, t:WIDENOP, w:R|R
BNDMOV rBl,mBl nil [ 0x66 0x0F 0x1A /r] s:MPX, t:MPX, w:W|R, a:NOA16|I67
BNDCL rBl,Ey nil [ 0xF3 0x0F 0x1A /r] s:MPX, t:MPX, w:R|R, a:AG|F64|I67
BNDCU rBl,Ey nil [ 0xF2 0x0F 0x1A /r] s:MPX, t:MPX, w:R|R, a:AG|F64|I67
BNDSTX Mmib,rBl nil [ 0x0F 0x1B /r:mem mib] s:MPX, t:MPX, w:W|R, a:AG|NOA16|NORIPREL|I67
NOP Gv,Ev nil [ 0x0F 0x1B /r:reg] s:PPRO, t:WIDENOP, w:R|R
BNDMOV mBl,rBl nil [ 0x66 0x0F 0x1B /r] s:MPX, t:MPX, w:W|R, a:NOA16|I67
BNDMK rBl,My nil [ 0xF3 0x0F 0x1B /r:mem] s:MPX, t:MPX, w:W|R, a:F64|NOA16|NORIPREL|I67
NOP Gv,Ev nil [ 0xF3 0x0F 0x1B /r:reg] s:PPRO, t:WIDENOP, w:R|R
BNDCN rBl,Ey nil [ 0xF2 0x0F 0x1B /r] s:MPX, t:MPX, w:R|R, a:AG|F64|I67
# MPX not used, these guys are wide NOPs.
NOP Gv,Ev nil [ 0x0F 0x1A /r] s:PPRO, t:WIDENOP, w:N|N
NOP Gv,Ev nil [ 0x0F 0x1B /r] s:PPRO, t:WIDENOP, w:N|N
NOP Ev,Gv nil [ 0x0F 0x1C /r] s:PPRO, t:WIDENOP, w:N|N
NOP Ev,Gv nil [ 0x0F 0x1D /r] s:PPRO, t:WIDENOP, w:N|N
NOP Ev,Gv nil [ 0x0F 0x1E /r] s:PPRO, t:WIDENOP, w:N|N
NOP Ev,Gv nil [ 0x0F 0x1F /r] s:PPRO, t:WIDENOP, w:N|N
CLDEMOTE Mb nil [ NP 0x0F 0x1C /0:mem] s:CLDEMOTE, t:CLDEMOTE, w:P
NOP Ev,Gv nil [ 0x66 0x0F 0x1C /0:mem] s:PPRO, t:WIDENOP, w:R|R
NOP Ev,Gv nil [ 0xF3 0x0F 0x1C /0:mem] s:PPRO, t:WIDENOP, w:R|R
NOP Ev,Gv nil [ 0xF2 0x0F 0x1C /0:mem] s:PPRO, t:WIDENOP, w:R|R
NOP Ev,Gv nil [ 0x0F 0x1C /0:reg] s:PPRO, t:WIDENOP, w:R|R
NOP Ev,Gv nil [ 0x0F 0x1C /1] s:PPRO, t:WIDENOP, w:R|R
NOP Ev,Gv nil [ 0x0F 0x1C /2] s:PPRO, t:WIDENOP, w:R|R
NOP Ev,Gv nil [ 0x0F 0x1C /3] s:PPRO, t:WIDENOP, w:R|R
NOP Ev,Gv nil [ 0x0F 0x1C /4] s:PPRO, t:WIDENOP, w:R|R
NOP Ev,Gv nil [ 0x0F 0x1C /5] s:PPRO, t:WIDENOP, w:R|R
NOP Ev,Gv nil [ 0x0F 0x1C /6] s:PPRO, t:WIDENOP, w:R|R
NOP Ev,Gv nil [ 0x0F 0x1C /7] s:PPRO, t:WIDENOP, w:R|R
NOP Ev,Gv nil [ 0x0F 0x1D /r] s:PPRO, t:WIDENOP, w:R|R
# Features that are mapped onto wide NOPs.
NOP Mv,Gv nil [ 0x0F 0x1E /r:mem] s:PPRO, t:WIDENOP, w:R|R
NOP Rv,Gv nil [ 0x0F 0x1E /0:reg] s:PPRO, t:WIDENOP, w:R|R
NOP Rv,Gv nil [ 0x0F 0x1E /1:reg] s:PPRO, t:WIDENOP, w:R|R
NOP Rv,Gv nil [ rexw 0x0F 0x1E /1:reg] s:PPRO, t:WIDENOP, w:R|R
RDSSPD Rd SSP [ a0xF3 0x0F 0x1E /1:reg] s:CET_SS, t:CET, c:RSSSP, w:W|R
RDSSPQ Rq SSP [ a0xF3 rexw 0x0F 0x1E /1:reg] s:CET_SS, t:CET, c:RSSSP, w:W|R
NOP Rv,Gv nil [ 0x0F 0x1E /2:reg] s:PPRO, t:WIDENOP, w:R|R
NOP Rv,Gv nil [ 0x0F 0x1E /3:reg] s:PPRO, t:WIDENOP, w:R|R
NOP Rv,Gv nil [ 0x0F 0x1E /4:reg] s:PPRO, t:WIDENOP, w:R|R
NOP Rv,Gv nil [ 0x0F 0x1E /5:reg] s:PPRO, t:WIDENOP, w:R|R
NOP Rv,Gv nil [ 0x0F 0x1E /6:reg] s:PPRO, t:WIDENOP, w:R|R
NOP Rv,Gv nil [ 0x0F 0x1E /0xF8] s:PPRO, t:WIDENOP, w:R|R
NOP Rv,Gv nil [ 0x0F 0x1E /0xF9] s:PPRO, t:WIDENOP, w:R|R
NOP Rv,Gv nil [ 0x0F 0x1E /0xFA] s:PPRO, t:WIDENOP, w:R|R
NOP Rv,Gv nil [ 0x0F 0x1E /0xFB] s:PPRO, t:WIDENOP, w:R|R
NOP Rv,Gv nil [ 0x0F 0x1E /0xFC] s:PPRO, t:WIDENOP, w:R|R
NOP Rv,Gv nil [ 0x0F 0x1E /0xFD] s:PPRO, t:WIDENOP, w:R|R
NOP Rv,Gv nil [ 0x0F 0x1E /0xFE] s:PPRO, t:WIDENOP, w:R|R
NOP Rv,Gv nil [ 0x0F 0x1E /0xFF] s:PPRO, t:WIDENOP, w:R|R
ENDBR64 nil nil [ a0xF3 0x0F 0x1E /0xFA] s:CET_IBT, t:CET, c:ENDBR
ENDBR32 nil nil [ a0xF3 0x0F 0x1E /0xFB] s:CET_IBT, t:CET, c:ENDBR
# MPX
BNDLDX rBl,Mmib nil [ mpx 0x0F 0x1A /r:mem mib] s:MPX, t:MPX, w:W|R, a:AG|NOA16|NORIPREL|I67
NOP Gv,Ev nil [ mpx 0x0F 0x1A /r:reg] s:PPRO, t:WIDENOP, w:N|N
BNDMOV rBl,mBl nil [ mpx 0x66 0x0F 0x1A /r] s:MPX, t:MPX, w:W|R, a:NOA16|I67
BNDCL rBl,Ey nil [ mpx 0xF3 0x0F 0x1A /r] s:MPX, t:MPX, w:R|R, a:AG|F64|I67
BNDCU rBl,Ey nil [ mpx 0xF2 0x0F 0x1A /r] s:MPX, t:MPX, w:R|R, a:AG|F64|I67
BNDSTX Mmib,rBl nil [ mpx 0x0F 0x1B /r:mem mib] s:MPX, t:MPX, w:W|R, a:AG|NOA16|NORIPREL|I67
NOP Gv,Ev nil [ mpx 0x0F 0x1B /r:reg] s:PPRO, t:WIDENOP, w:N|N
BNDMOV mBl,rBl nil [ mpx 0x66 0x0F 0x1B /r] s:MPX, t:MPX, w:W|R, a:NOA16|I67
BNDMK rBl,My nil [ mpx 0xF3 0x0F 0x1B /r:mem] s:MPX, t:MPX, w:W|R, a:F64|NOA16|NORIPREL|I67
NOP Gv,Ev nil [ mpx 0xF3 0x0F 0x1B /r:reg] s:PPRO, t:WIDENOP, w:N|N
BNDCN rBl,Ey nil [ mpx 0xF2 0x0F 0x1B /r] s:MPX, t:MPX, w:R|R, a:AG|F64|I67
# CLDEMOTE
CLDEMOTE Mb nil [ cldm NP 0x0F 0x1C /0:mem] s:CLDEMOTE, t:CLDEMOTE, w:P
NOP Ev,Gv nil [ cldm 0x66 0x0F 0x1C /0:mem] s:PPRO, t:WIDENOP, w:N|N
NOP Ev,Gv nil [ cldm 0xF3 0x0F 0x1C /0:mem] s:PPRO, t:WIDENOP, w:N|N
NOP Ev,Gv nil [ cldm 0xF2 0x0F 0x1C /0:mem] s:PPRO, t:WIDENOP, w:N|N
NOP Ev,Gv nil [ cldm 0x0F 0x1C /0:reg] s:PPRO, t:WIDENOP, w:N|N
NOP Ev,Gv nil [ cldm 0x0F 0x1C /1] s:PPRO, t:WIDENOP, w:N|N
NOP Ev,Gv nil [ cldm 0x0F 0x1C /2] s:PPRO, t:WIDENOP, w:N|N
NOP Ev,Gv nil [ cldm 0x0F 0x1C /3] s:PPRO, t:WIDENOP, w:N|N
NOP Ev,Gv nil [ cldm 0x0F 0x1C /4] s:PPRO, t:WIDENOP, w:N|N
NOP Ev,Gv nil [ cldm 0x0F 0x1C /5] s:PPRO, t:WIDENOP, w:N|N
NOP Ev,Gv nil [ cldm 0x0F 0x1C /6] s:PPRO, t:WIDENOP, w:N|N
NOP Ev,Gv nil [ cldm 0x0F 0x1C /7] s:PPRO, t:WIDENOP, w:N|N
# CET
NOP Mv,Gv nil [ cet 0x0F 0x1E /r:mem] s:PPRO, t:WIDENOP, w:N|N
NOP Rv,Gv nil [ cet 0x0F 0x1E /0:reg] s:PPRO, t:WIDENOP, w:N|N
NOP Rv,Gv nil [ cet 0x0F 0x1E /1:reg] s:PPRO, t:WIDENOP, w:N|N
NOP Rv,Gv nil [ cet rexw 0x0F 0x1E /1:reg] s:PPRO, t:WIDENOP, w:N|N
RDSSPD Rd SSP [ cet a0xF3 0x0F 0x1E /1:reg] s:CET_SS, t:CET, c:RSSSP, w:W|R
RDSSPQ Rq SSP [ cet a0xF3 rexw 0x0F 0x1E /1:reg] s:CET_SS, t:CET, c:RSSSP, w:W|R
NOP Rv,Gv nil [ cet 0x0F 0x1E /2:reg] s:PPRO, t:WIDENOP, w:N|N
NOP Rv,Gv nil [ cet 0x0F 0x1E /3:reg] s:PPRO, t:WIDENOP, w:N|N
NOP Rv,Gv nil [ cet 0x0F 0x1E /4:reg] s:PPRO, t:WIDENOP, w:N|N
NOP Rv,Gv nil [ cet 0x0F 0x1E /5:reg] s:PPRO, t:WIDENOP, w:N|N
NOP Rv,Gv nil [ cet 0x0F 0x1E /6:reg] s:PPRO, t:WIDENOP, w:N|N
NOP Rv,Gv nil [ cet 0x0F 0x1E /0xF8] s:PPRO, t:WIDENOP, w:N|N
NOP Rv,Gv nil [ cet 0x0F 0x1E /0xF9] s:PPRO, t:WIDENOP, w:N|N
NOP Rv,Gv nil [ cet 0x0F 0x1E /0xFA] s:PPRO, t:WIDENOP, w:N|N
NOP Rv,Gv nil [ cet 0x0F 0x1E /0xFB] s:PPRO, t:WIDENOP, w:N|N
NOP Rv,Gv nil [ cet 0x0F 0x1E /0xFC] s:PPRO, t:WIDENOP, w:N|N
NOP Rv,Gv nil [ cet 0x0F 0x1E /0xFD] s:PPRO, t:WIDENOP, w:N|N
NOP Rv,Gv nil [ cet 0x0F 0x1E /0xFE] s:PPRO, t:WIDENOP, w:N|N
NOP Rv,Gv nil [ cet 0x0F 0x1E /0xFF] s:PPRO, t:WIDENOP, w:N|N
ENDBR64 nil nil [ cet a0xF3 0x0F 0x1E /0xFA] s:CET_IBT, t:CET, c:ENDBR
ENDBR32 nil nil [ cet a0xF3 0x0F 0x1E /0xFB] s:CET_IBT, t:CET, c:ENDBR
NOP Ev,Gv nil [ 0x0F 0x1F /r] s:PPRO, t:WIDENOP, w:R|R
# 0x20 - 0x2F
MOV Ry,Cy nil [ 0x0F 0x20 /r] s:I86, t:DATAXFER, c:MOV_CR, w:W|R, a:LOCKSP|MFR|F64, m:KERNEL|NOV86

Loading…
Cancel
Save