Merge 3a2fb20479178415cec01fce9aa256898ba3bd9f into 4290ea753912378913b1f3f54e0fc5720afeda5d
This commit is contained in:
commit
04c1b5bdcf
@ -8,6 +8,34 @@ import Operation from "../Operation.mjs";
|
||||
import * as disassemble from "../vendor/DisassembleX86-64.mjs";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
|
||||
/**
|
||||
* Parses a hexadecimal address value used by the disassembler.
|
||||
*
|
||||
* The underlying disassembler interprets both the code segment and the offset as
|
||||
* hexadecimal, and renders them back as hexadecimal, so these arguments accept the
|
||||
* common ways of writing a hex literal: bare (`ABC`), prefixed (`0xABC`) or suffixed
|
||||
* (`ABCh`).
|
||||
*
|
||||
* @param {string} value
|
||||
* @param {string} name - Argument name, used in the error message.
|
||||
* @param {number} [padTo=0] - Left-pad the result with zeroes to this many digits.
|
||||
* @returns {string} The bare hex digits, ready to be passed to SetBasePosition.
|
||||
*
|
||||
* @throws {OperationError} if the value is not a valid hexadecimal number.
|
||||
*/
|
||||
function parseHexAddress(value, name, padTo = 0) {
|
||||
const trimmed = value.toString().trim();
|
||||
const hex = trimmed.replace(/^0x/i, "").replace(/h$/i, "");
|
||||
|
||||
if (hex === "" || !/^[\da-f]+$/i.test(hex)) {
|
||||
throw new OperationError(`Invalid ${name}: '${trimmed}' is not a hexadecimal number.`);
|
||||
}
|
||||
|
||||
// SetBasePosition reads the code segment from the last four characters it is given,
|
||||
// so shorter values must be padded to avoid losing their leading digits.
|
||||
return hex.padStart(padTo, "0");
|
||||
}
|
||||
|
||||
/**
|
||||
* Disassemble x86 operation
|
||||
*/
|
||||
@ -46,13 +74,15 @@ class DisassembleX86 extends Operation {
|
||||
},
|
||||
{
|
||||
"name": "Code Segment (CS)",
|
||||
"type": "number",
|
||||
"value": 16
|
||||
"type": "string",
|
||||
"value": "16",
|
||||
"hint": "Hexadecimal, e.g. 16, 0xABC or ABCh"
|
||||
},
|
||||
{
|
||||
"name": "Offset (IP)",
|
||||
"type": "number",
|
||||
"value": 0
|
||||
"type": "string",
|
||||
"value": "0",
|
||||
"hint": "Hexadecimal, e.g. 0, 0x1000 or 1000h"
|
||||
},
|
||||
{
|
||||
"name": "Show instruction hex",
|
||||
@ -122,7 +152,10 @@ class DisassembleX86 extends Operation {
|
||||
break;
|
||||
}
|
||||
|
||||
disassemble.SetBasePosition(codeSegment + ":" + offset);
|
||||
disassemble.SetBasePosition(
|
||||
parseHexAddress(codeSegment, "Code Segment (CS)", 4) + ":" +
|
||||
parseHexAddress(offset, "Offset (IP)")
|
||||
);
|
||||
disassemble.setShowInstructionHex(showInstructionHex);
|
||||
disassemble.setShowInstructionPos(showInstructionPos);
|
||||
disassemble.LoadBinCode(input.replace(/\s/g, ""));
|
||||
|
||||
89
tests/operations/tests/DisassembleX86.mjs
Normal file
89
tests/operations/tests/DisassembleX86.mjs
Normal file
@ -0,0 +1,89 @@
|
||||
/**
|
||||
* Disassemble x86 tests.
|
||||
*
|
||||
* @author arjun2075
|
||||
*
|
||||
* @copyright Crown Copyright 2026
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../lib/TestRegister.mjs";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "Disassemble x86: default code segment is unchanged",
|
||||
input: "90",
|
||||
expectedMatch: /0016:0000\s+NOP/,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Disassemble x86",
|
||||
args: ["16", "Full x86 architecture", "16", "0", false, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Disassemble x86: hex code segment with 0x prefix",
|
||||
input: "90",
|
||||
expectedMatch: /0ABC:0000\s+NOP/,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Disassemble x86",
|
||||
args: ["16", "Full x86 architecture", "0xABC", "0", false, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Disassemble x86: hex code segment with h suffix",
|
||||
input: "90",
|
||||
expectedMatch: /0ABC:0000\s+NOP/,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Disassemble x86",
|
||||
args: ["16", "Full x86 architecture", "ABCh", "0", false, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Disassemble x86: bare hex code segment",
|
||||
input: "90",
|
||||
expectedMatch: /0ABC:0000\s+NOP/,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Disassemble x86",
|
||||
args: ["16", "Full x86 architecture", "ABC", "0", false, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Disassemble x86: hex offset with 0x prefix",
|
||||
input: "90",
|
||||
expectedMatch: /0016:1000\s+NOP/,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Disassemble x86",
|
||||
args: ["16", "Full x86 architecture", "16", "0x1000", false, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Disassemble x86: invalid code segment is rejected",
|
||||
input: "90",
|
||||
expectedOutput: "Invalid Code Segment (CS): 'wibble' is not a hexadecimal number.",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Disassemble x86",
|
||||
args: ["16", "Full x86 architecture", "wibble", "0", false, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Disassemble x86: invalid offset is rejected",
|
||||
input: "90",
|
||||
expectedOutput: "Invalid Offset (IP): 'wibble' is not a hexadecimal number.",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Disassemble x86",
|
||||
args: ["16", "Full x86 architecture", "16", "wibble", false, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
Loading…
x
Reference in New Issue
Block a user