diff --git a/SharpDisasm.Tests/Decode64bitTests.cs b/SharpDisasm.Tests/Decode64bitTests.cs
index 7b490f4..122ceca 100644
--- a/SharpDisasm.Tests/Decode64bitTests.cs
+++ b/SharpDisasm.Tests/Decode64bitTests.cs
@@ -31,9 +31,8 @@ public void Disp64Test()
//0000000000000018 4c03849800000080 add r8, [rax+rbx*4-0x80000000]
//0000000000000020 48a1000000000080 mov rax, [0x800000000000]
- Instruction insn = null;
- insn = disasm.NextInstruction();
+ var insn = disasm.NextInstruction();
Assert.AreEqual("mov ax, [eax-0x10]", insn.ToString());
insn = disasm.NextInstruction();
@@ -61,9 +60,8 @@ public void NegativeRIPAddress()
0xFF, 0x15, 0xF7, 0xFF, 0xFF, 0xFF, // call qword [rip-0x9]
}, ArchitectureMode.x86_64);
- Instruction insn = null;
- insn = disasm.NextInstruction();
+ var insn = disasm.NextInstruction();
Assert.AreEqual("mov rax, [rip-0x9]", insn.ToString());
insn = disasm.NextInstruction();
diff --git a/SharpDisasm.Tests/DisassemblerTests.cs b/SharpDisasm.Tests/DisassemblerTests.cs
index 792a356..e66a105 100644
--- a/SharpDisasm.Tests/DisassemblerTests.cs
+++ b/SharpDisasm.Tests/DisassemblerTests.cs
@@ -20,7 +20,7 @@ public void DisassembleBytesDecoded()
0x00, 0x67, // invalid
}, ArchitectureMode.x86_32, 0, false);
- foreach (SharpDisasm.Instruction instruction in disasm.Disassemble())
+ foreach (SharpDisasm.IInstruction instruction in disasm.Disassemble())
{
Assert.IsTrue(instruction.Length > 0);
}
@@ -55,7 +55,7 @@ where insn.Length > 5
select insn).First().ToString());
- foreach (SharpDisasm.Instruction instruction in results)
+ foreach (SharpDisasm.IInstruction instruction in results)
{
Assert.IsFalse(instruction.Error);
Assert.IsTrue(instruction.Length > 0);
diff --git a/SharpDisasm.nuspec b/SharpDisasm.nuspec
new file mode 100644
index 0000000..abd6522
--- /dev/null
+++ b/SharpDisasm.nuspec
@@ -0,0 +1,70 @@
+
+
+
+ SharpDisasm
+ $version$
+ SharpDisasm
+ Justin Stenning
+ Justin Stenning
+ true
+ https://github.com/spazzarama/SharpDisasm/blob/master/LICENSE.md
+ https://github.com/spazzarama/SharpDisasm
+ SharpDisam is a disassembler written in C# able to decode the x86 and x86-64 instruction set architectures.
+
+It features:
+ * a full C# port of the libudis86 C library
+ * a set of simple C# classes wrapping the udis86 API
+ * support for x86 16-bit, 32-bit and 64-bit instruction set architectures
+ * support for outputting in Intel and AT&T syntax
+ * support for all x86 and x86-64 (AMD64) General purpose and System instructions.
+ * support for the following ISA extensions:
+ - MMX, FPU (x87), AMD 3DNow
+ - SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AES,
+ - AMD-V, INTEL-VMX, SMX
+ * instructions are defined in an XML document that is consumed by a T4 template to generate opcode tables for performance.
+ * the XML instructions document is exactly the same as that found within the udis86 project. The generated C# opcode tables is also very similar except in syntax to those generated by the Python script in the libudis86 C-library.
+ * able to decode more than 4 million 64-bit instructions per second (with an average instruction size of 7-bytes)
+
+Usage: http://sharpdisasm.codeplex.com/documentation
+ A C# port of the udis86 x86 disassembler.
+ $version$
+1. Added ability to resolve RIP relative addresses in ASM outputting
+2. 64-bit definition fixes for a number of instructions
+3. Support for .NET Standard target
+
+1. Added support for offset into IAssemblyCode
+2. Fix exceptions on invalid instructions (contributed by ste-art)
+3. Fix ATT syntax for enter/bound mnemonics being dropped
+4. Translator internals refactored (better code reuse)
+5. A few Debug.Asserts replaced with exceptions for Translator and Instruction.ToString
+1.1.5
+1. Use of unsafe replaced with an assembly code reader interface
+1.0.2
+1. Full port of udis86 C-library into C#
+2. Wrapper class Disassembler for those not familiar with the libudis86 C-library
+ Copyright (c) 2015 Justin Stenning
+ ASM disassembler x86 x86-64 instructions opcodes decoder AMD Intel
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/SharpDisasm/Disassembler.cs b/SharpDisasm/Disassembler.cs
index 2a40ea5..82f1f26 100644
--- a/SharpDisasm/Disassembler.cs
+++ b/SharpDisasm/Disassembler.cs
@@ -40,6 +40,7 @@
using System.Text;
using SharpDisasm.Helpers;
+using SharpDisasm.Factory;
namespace SharpDisasm
{
@@ -86,6 +87,8 @@ public sealed class Disassembler : IDisposable
///
private Udis86.ud _u = new Udis86.ud();
+ private readonly IInstructionFactory _instructionFactory;
+
#endregion
///
@@ -98,8 +101,8 @@ public sealed class Disassembler : IDisposable
///
public int BytesDecoded { get; private set; }
- ///
- /// Initializes a new instance of the class.
+
+ /// Initializes a new instance of the class.
///
/// The code.
/// The architecture.
@@ -107,7 +110,12 @@ public sealed class Disassembler : IDisposable
/// The address.
/// if set to true [copy binary to instruction].
/// The vendor.
- public Disassembler(IAssemblyCode code, ArchitectureMode architecture, ulong offset = 0x0, ulong address = 0x0, bool copyBinaryToInstruction = false, Vendor vendor = Vendor.Any)
+ /// instruction factory, when null
+ /// class is created
+ public Disassembler(IAssemblyCode code, ArchitectureMode architecture,
+ ulong offset = 0x0, ulong address = 0x0,
+ bool copyBinaryToInstruction = false, Vendor vendor = Vendor.Any,
+ IInstructionFactory instructionFactory = null)
{
this.Code = code;
@@ -115,13 +123,23 @@ public Disassembler(IAssemblyCode code, ArchitectureMode architecture, ulong off
this.Address = address;
this.CopyBinaryToInstruction = copyBinaryToInstruction;
this.Vendor = vendor;
- this.Offset = offset;
+ if (instructionFactory == null)
+ {
+ _instructionFactory = new InstructionFactory();
+ }
+ else
+ {
+ _instructionFactory = instructionFactory;
+ }
InitUdis86();
}
///
- /// Prepares a new disassembler instance for the code provided. The instructions can then be disassembled with a call to . The base address used to resolve relative addresses should be provided in .
+ /// Prepares a new disassembler instance for the code provided.The instructions
+ /// can then be disassembled with a call to .
+ /// The base address used to resolve relative addresses should be provided
+ /// in .
///
/// The code to be disassembled
/// The target x86 instruction set architecture of the code (e.g. 64-bit, 32-bit or 16-bit).
@@ -129,8 +147,15 @@ public Disassembler(IAssemblyCode code, ArchitectureMode architecture, ulong off
/// Keeps a copy of the binary code for the instruction. This will increase the memory usage for each instruction. This is necessary if planning on using the option.
/// What vendor instructions to support during disassembly, default is Any. Other options are AMD or Intel.
/// The offset.
- public Disassembler(byte[] code, ArchitectureMode architecture, ulong address = 0x0, bool copyBinaryToInstruction = false, Vendor vendor = Vendor.Any, ulong offset = 0)
- : this(new AssemblyCodeArray(code), architecture, offset, address, copyBinaryToInstruction, vendor)
+ /// instruction factory, when null
+ /// class is created
+ public Disassembler(byte[] code, ArchitectureMode architecture,
+ ulong address = 0x0, bool copyBinaryToInstruction = false,
+ Vendor vendor = Vendor.Any, ulong offset = 0,
+ IInstructionFactory instructionFactory = null)
+ : this(new AssemblyCodeArray(code),architecture, offset,
+ address, copyBinaryToInstruction,
+ vendor,instructionFactory)
{
}
@@ -139,12 +164,24 @@ public Disassembler(byte[] code, ArchitectureMode architecture, ulong address =
///
/// A pointer to memory to be disassembled.
/// The maximum length to be disassembled.
- /// The architecture of the code (e.g. 64-bit, 32-bit or 16-bit).
- /// The address of the first byte of code. This value is used to resolve relative addresses into absolute addresses while disassembling.
- /// Keeps a copy of the binary code for the instruction. This will increase the memory usage for each instruction. This is necessary if planning on using the option.
- /// What vendors to support for disassembly, default is Any. Other options are AMD or Intel.
- public Disassembler(IntPtr codePtr, int codeLength, ArchitectureMode architecture, ulong address = 0x0, bool copyBinaryToInstruction = false, Vendor vendor = Vendor.Any)
- : this(new AssemblyCodeMemory(codePtr, codeLength), architecture, 0, address, copyBinaryToInstruction, vendor)
+ /// The architecture of the code
+ ///
+ /// (e.g. 64-bit, 32-bit or 16-bit).
+ /// The address of the first byte of code.
+ /// This value is used to resolve relative addresses into absolute addresses while disassembling.
+ /// Keeps a copy of the binary code for the
+ /// instruction. This will increase the memory usage for each instruction.
+ /// This is necessary if planning on using the
+ /// option.
+ /// What vendors to support for disassembly, default is Any.
+ /// Other options are AMD or Intel.
+ /// instruction factory, when null
+ /// class is created
+ public Disassembler(IntPtr codePtr, int codeLength, ArchitectureMode architecture,
+ ulong address = 0x0, bool copyBinaryToInstruction = false,
+ Vendor vendor = Vendor.Any,IInstructionFactory instructionFactory = null)
+ : this(new AssemblyCodeMemory(codePtr, codeLength), architecture,
+ 0, address, copyBinaryToInstruction, vendor,instructionFactory)
{
if (codePtr == IntPtr.Zero)
throw new ArgumentOutOfRangeException("codePtr");
@@ -175,10 +212,10 @@ private void InitUdis86()
/// Disassemble instructions and yield the result. Breaking out of the enumerator will prevent further instructions being disassembled.
///
/// An IEnumerable collection of disassembled instructions
- public IEnumerable Disassemble()
+ public IEnumerable Disassemble()
{
Reset();
- Instruction instruction = null;
+ IInstruction instruction = null;
while ((instruction = NextInstruction()) != null)
{
yield return instruction;
@@ -199,12 +236,12 @@ public void Reset()
/// Decodes a single instruction and increments buffer position.
///
///
- public Instruction NextInstruction()
+ public IInstruction NextInstruction()
{
int length = 0;
if ((length = Udis86.udis86.ud_disassemble(ref _u)) > 0)
{
- var instruction = new Instruction(ref _u, CopyBinaryToInstruction);
+ var instruction = _instructionFactory.Create(ref _u, CopyBinaryToInstruction);
if (!instruction.Error)
{
BytesDecoded += length;
diff --git a/SharpDisasm/Factory/IInstructionFactory.cs b/SharpDisasm/Factory/IInstructionFactory.cs
new file mode 100644
index 0000000..860e75f
--- /dev/null
+++ b/SharpDisasm/Factory/IInstructionFactory.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+
+namespace SharpDisasm.Factory
+{
+ ///
+ /// interface for instruction factory
+ ///
+ public interface IInstructionFactory
+ {
+ ///
+ /// The create method of the factory
+ ///
+ /// the internal instruction parser
+ /// To copy the binary bytes to instruction
+ /// Instructuion instance
+ IInstruction Create(ref Udis86.ud u, bool keepBinary);
+ }
+}
diff --git a/SharpDisasm/Factory/InstructionFactory.cs b/SharpDisasm/Factory/InstructionFactory.cs
new file mode 100644
index 0000000..e422183
--- /dev/null
+++ b/SharpDisasm/Factory/InstructionFactory.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+
+namespace SharpDisasm.Factory
+{
+ ///
+ /// Instruction factory
+ ///
+ public class InstructionFactory : IInstructionFactory
+ {
+ ///
+ /// The create method of the factory
+ ///
+ /// the internal instruction parser
+ /// To copy the binary bytes to instruction
+ /// Instructuion instance
+ public IInstruction Create(ref Udis86.ud u, bool keepBinary)
+ {
+ return new Instruction( ref u, keepBinary);
+ }
+ }
+}
diff --git a/SharpDisasm/IInstruction.cs b/SharpDisasm/IInstruction.cs
new file mode 100644
index 0000000..a9650b4
--- /dev/null
+++ b/SharpDisasm/IInstruction.cs
@@ -0,0 +1,54 @@
+using SharpDisasm.Udis86;
+
+namespace SharpDisasm
+{
+ ///
+ /// instruction interface
+ ///
+ public interface IInstruction
+ {
+ ///
+ /// Instruction Offset
+ ///
+ byte[] Bytes { get; }
+
+ ///
+ /// Indicates whether the instruction was successfully decoded.
+ ///
+ bool Error { get; }
+
+ ///
+ /// The reason an instruction was not successfully decoded.
+ ///
+ string ErrorMessage { get; }
+
+ ///
+ /// The length of the instruction in bytes
+ ///
+ int Length { get; }
+
+ ///
+ /// Mnemonic
+ ///
+ ud_mnemonic_code Mnemonic { get; }
+
+ ///
+ /// Instruction offset
+ ///
+ ulong Offset { get; }
+
+ ///
+ /// Instruction Operends (maximum 3)
+ ///
+ Operand[] Operands { get; }
+
+ ///
+ /// Program counter
+ ///
+ ulong PC { get; }
+
+
+
+
+ }
+}
\ No newline at end of file
diff --git a/SharpDisasm/Instruction.cs b/SharpDisasm/Instruction.cs
index 3d74ce7..f87bea2 100644
--- a/SharpDisasm/Instruction.cs
+++ b/SharpDisasm/Instruction.cs
@@ -47,47 +47,47 @@ namespace SharpDisasm
///
/// Represents a decoded instruction.
///
- public class Instruction
+ public class Instruction : IInstruction
{
///
/// Instruction Offset
///
- public ulong Offset { get; private set; }
+ public ulong Offset { get; protected set; }
///
/// Program counter
///
- public ulong PC { get; private set; }
+ public ulong PC { get; protected set; }
///
/// Will contain a copy of the original binary instruction if is true.
///
- public byte[] Bytes { get; private set; }
+ public byte[] Bytes { get; protected set; }
///
/// Mnemonic
///
- public SharpDisasm.Udis86.ud_mnemonic_code Mnemonic { get; private set; }
+ public SharpDisasm.Udis86.ud_mnemonic_code Mnemonic { get; protected set; }
///
/// The instruction operands (maximum 3)
///
- public Operand[] Operands { get; private set; }
+ public Operand[] Operands { get; protected set; }
///
/// The length of the instruction in bytes
///
- public int Length { get; private set; }
+ public int Length { get; protected set; }
///
/// Indicates whether the instruction was successfully decoded.
///
- public bool Error { get; private set; }
+ public bool Error { get; protected set; }
///
/// The reason an instruction was not successfully decoded.
///
- public string ErrorMessage { get; private set; }
+ public string ErrorMessage { get; protected set; }
#region Low-level instruction information
diff --git a/SharpDisasm/SharpDisasm.csproj b/SharpDisasm/SharpDisasm.csproj
index d120d62..8eb17c4 100644
--- a/SharpDisasm/SharpDisasm.csproj
+++ b/SharpDisasm/SharpDisasm.csproj
@@ -3,6 +3,8 @@
netstandard2.0;net45;net4;net35
..\bin\$(Configuration)\
+ ..\bin\$(Configuration)\$(TargetFramework)\SharpDisasm.xml
+
diff --git a/SharpDisasmPack.bat b/SharpDisasmPack.bat
new file mode 100644
index 0000000..c9ebed8
--- /dev/null
+++ b/SharpDisasmPack.bat
@@ -0,0 +1,2 @@
+nuget pack SharpDisasm.nuspec -Symbols -Version VERSIONHERE
+pause
\ No newline at end of file