Skip to content

Commit

Permalink
Implement pointer disassembly
Browse files Browse the repository at this point in the history
  • Loading branch information
TollyH committed May 17, 2024
1 parent 88c18c8 commit 0e6109a
Show file tree
Hide file tree
Showing 7 changed files with 335 additions and 182 deletions.
20 changes: 20 additions & 0 deletions Disassembler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,25 @@ public static string DisassembleProgram(byte[] program, DisassemblerOptions opti
totalBytes += 8;
break;
case OperandType.Pointer:
#if DISPLACEMENT
DisplacementMode mode = Pointer.GetDisplacementMode(instruction[(int)totalBytes]);
if (mode.GetByteCount() + totalBytes >= (ulong)instruction.Length)
{
fallbackToDat = true;
break;
}

Pointer pointer = new(instruction[(int)totalBytes..], out ulong pointerBytes);
if (!Enum.IsDefined(pointer.Mode) || !Enum.IsDefined(pointer.PointerRegister)
|| !Enum.IsDefined(pointer.OtherRegister) || !Enum.IsDefined(pointer.ReadSize)
|| !Enum.IsDefined(pointer.OtherRegisterMultiplier))
{
fallbackToDat = true;
break;
}
operandStrings.Add(pointer.ToString());
totalBytes += pointerBytes;
#else
if (Enum.IsDefined((Register)instruction[(int)totalBytes]))
{
operandStrings.Add("*" + (Register)instruction[(int)totalBytes]);
Expand All @@ -209,6 +228,7 @@ public static string DisassembleProgram(byte[] program, DisassemblerOptions opti
{
fallbackToDat = true;
}
#endif
break;
default:
fallbackToDat = true;
Expand Down
29 changes: 29 additions & 0 deletions Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,34 @@ public static void SetContentTo<T>(this Stack<T> target, Stack<T> source)
{
return new Stack<T>(stack.Select(i => (T)i.Clone()).Reverse());
}

#if DISPLACEMENT
public static string GetMultiplierString(this DisplacementMultiplier multiplier)
{
return multiplier switch
{
DisplacementMultiplier.x2 => "2",
DisplacementMultiplier.x4 => "4",
DisplacementMultiplier.x8 => "8",
DisplacementMultiplier.x16 => "16",
DisplacementMultiplier.x32 => "32",
DisplacementMultiplier.x64 => "64",
DisplacementMultiplier.x128 => "128",
_ => "?" // Invalid value - won't assemble
};
}

public static ulong GetByteCount(this DisplacementMode mode)
{
return mode switch
{
DisplacementMode.NoDisplacement => 1,
DisplacementMode.Constant => 9,
DisplacementMode.Register => 2,
DisplacementMode.ConstantAndRegister => 10,
_ => 0
};
}
#endif
}
}
112 changes: 104 additions & 8 deletions Structs.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Buffers.Binary;
using System.Text;

namespace AssEmbly
{
Expand Down Expand Up @@ -224,25 +225,49 @@ public Pointer(Register pointerRegister, PointerReadSize readSize, long displace
OtherRegisterMultiplier = otherRegisterMultiplier;
}

public Pointer(Span<byte> encodedBytes, out ulong byteCount)
{
Mode = GetDisplacementMode(encodedBytes[0]);
ReadSize = (PointerReadSize)((encodedBytes[0] >> 4) & 0b11);
PointerRegister = (Register)(encodedBytes[0] & 0b1111);

byteCount = Mode.GetByteCount();

switch (Mode)
{
case DisplacementMode.NoDisplacement:
default:
return;
case DisplacementMode.Constant:
DisplacementConstant = BinaryPrimitives.ReadInt64LittleEndian(encodedBytes[1..]);
return;
case DisplacementMode.Register:
OtherRegisterMultiplier = (DisplacementMultiplier)((encodedBytes[1] >> 4) & 0b111);
OtherRegister = (Register)(encodedBytes[1] & 0b1111);
SubtractOtherRegister = (encodedBytes[1] & 0b10000000) != 0;
return;
case DisplacementMode.ConstantAndRegister:
DisplacementConstant = BinaryPrimitives.ReadInt64LittleEndian(encodedBytes[1..]);
OtherRegisterMultiplier = (DisplacementMultiplier)((encodedBytes[9] >> 4) & 0b111);
OtherRegister = (Register)(encodedBytes[9] & 0b1111);
SubtractOtherRegister = (encodedBytes[9] & 0b10000000) != 0;
return;
}
}

/// <summary>
/// Get the byte representation of this pointer to store in an AssEmbly program.
/// </summary>
public byte[] GetBytes()
{
byte[] bytes = new byte[Mode switch
{
DisplacementMode.NoDisplacement => 1,
DisplacementMode.Constant => 9,
DisplacementMode.Register => 2,
DisplacementMode.ConstantAndRegister => 10,
_ => 1
}];
byte[] bytes = new byte[Mode.GetByteCount()];
Span<byte> byteSpan = bytes.AsSpan();

bytes[0] = (byte)(((byte)Mode << 6) | ((byte)ReadSize << 4) | (byte)PointerRegister);
switch (Mode)
{
case DisplacementMode.NoDisplacement:
default:
break;
case DisplacementMode.Constant:
BinaryPrimitives.WriteInt64LittleEndian(byteSpan[1..], DisplacementConstant);
Expand All @@ -267,6 +292,11 @@ public byte[] GetBytes()
return bytes;
}

public static DisplacementMode GetDisplacementMode(byte firstByte)
{
return (DisplacementMode)(firstByte >> 6);
}

public bool Equals(Pointer other)
{
if (Mode != other.Mode)
Expand Down Expand Up @@ -323,6 +353,72 @@ public override int GetHashCode()
{
return !left.Equals(right);
}

public override string ToString()
{
StringBuilder sb = new();

// Read size ('Q' is the default so can be omitted)
if (ReadSize != PointerReadSize.QuadWord)
{
_ = sb.Append(ReadSize switch
{
PointerReadSize.DoubleWord => 'D',
PointerReadSize.Word => 'W',
PointerReadSize.Byte => 'B',
_ => '?' // Invalid value - won't assemble
});
}

// Main register
_ = sb.Append('*').Append(PointerRegister);

// Displacement component
switch (Mode)
{
case DisplacementMode.NoDisplacement:
break;
case DisplacementMode.Constant:
_ = sb.Append('[')
.Append(DisplacementConstant)
.Append(']');
break;
case DisplacementMode.Register:
_ = sb.Append('[');
if (SubtractOtherRegister)
{
_ = sb.Append('-');
}
_ = sb.Append(OtherRegister);
if (OtherRegisterMultiplier != DisplacementMultiplier.x1)
{
_ = sb.Append(" * ")
.Append(OtherRegisterMultiplier.GetMultiplierString());
}
_ = sb.Append(']');
break;
case DisplacementMode.ConstantAndRegister:
_ = sb.Append('[');
if (SubtractOtherRegister)
{
_ = sb.Append('-');
}
_ = sb.Append(OtherRegister);
if (OtherRegisterMultiplier != DisplacementMultiplier.x1)
{
_ = sb.Append(" * ").Append(OtherRegisterMultiplier.GetMultiplierString());
}
_ = sb.Append(DisplacementConstant >= 0 ? " + " : " - ")
.Append(Math.Abs(DisplacementConstant))
.Append(']');
break;
default:
_ = sb.Append("[?]"); // Invalid value - won't assemble
break;
}

return sb.ToString();
}
}

public readonly struct AddressReference : IEquatable<AddressReference>
Expand Down
90 changes: 46 additions & 44 deletions Test/KitchenSink.Disassembled.FullBase.asm
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,13 @@ HLT
%PAD 6
%DAT "Hello, world"
SUB rg4, 8367799640999031621
%DAT "est complete\"Still string"
HLT
%DAT "BE"
%DAT 150
CAL :0x4D21083B99F34, *rpo ; Address does not align to a disassembled instruction
HLT
%PAD 3
%DAT "est complete\"Still strin"
ORR rpo, *rsb[1189998819991197253]
WFN :0xD200000000000004 ; Address does not align to a disassembled instruction
JEQ :0x4FF000000000000 ; Address does not align to a disassembled instruction
%DAT 17
JEQ :0x4D2000000000000 ; Address does not align to a disassembled instruction
HLT
%PAD 5
ASMX_CLF
CFL
CFL
NOP
Expand All @@ -46,23 +43,28 @@ SUB rrv, rpo
HLT
%PAD 4
%DAT "ii4"
%DAT 139
JLT :0x8ABEED000005292C ; Address does not align to a disassembled instruction
%DAT 247
MVW rg2, W*rg6
%DAT ")"
JEQ *rpo
HLT
%DAT 237
RET *rg4[-rg1 * 128]
%DAT ">"
%DAT 3
POP rpo
JMP W*rrv[rpo]
MVQ rg0, :0x123456789 ; Address does not align to a disassembled instruction
MVQ :0x123456789, 4664385274516035810 ; Address does not align to a disassembled instruction
HLT
%DAT 240
%DAT 159
MVW :0x8D9FF000000000AD, 9836955600246800557 ; Address does not align to a disassembled instruction
MVQ *rg7[-rg7 * 4], 12505827593418702848
HLT
%PAD 4
DFL :0x700000000008883 ; Address does not align to a disassembled instruction
JLT :0x305C0B09A99BE20C ; Address does not align to a disassembled instruction
%PAD 3
DFL :0xE300000000008883 ; Address does not align to a disassembled instruction
%DAT 131
MVW rpo, rpo
HLT
%PAD 2
JNE *rg2
JGT :0x305C0B09A99BE2 ; Address does not align to a disassembled instruction
%DAT ",, ,,)"
HLT
%DAT "$0"
Expand Down Expand Up @@ -113,35 +115,13 @@ JMP :0x204030403040301 ; Address does not align to a disassembled instruction
WFX 16478
OFL :0x140000000000003F ; Address does not align to a disassembled instruction
%DAT "\@"
%DAT 190
%DAT 159
%DAT 26
RET D*rg9[rg4 * 2]
%DAT "/"
WFC 12575268
%DAT 184
%DAT 129
%DAT 192
%DAT 211
%DAT 255
%DAT 255
%DAT 255
%DAT 255
%DAT 255
%DAT 255
%DAT 255
CAL *rso[-rpo * 16], :0xFFFFFFFFFFFFFFD3 ; Address does not align to a disassembled instruction
%DAT "*Tv"
%DAT 152
%DAT 15
%DAT 219
%DAT "u"
%DAT 22
%DAT "i"
%DAT 27
%DAT 254
%DAT 254
%DAT 253
%DAT 254
%DAT 253
JGE D*rg5[-rg7 * 128 - 72621651633039755]
%DAT 253
%DAT 254
%DAT 253
Expand Down Expand Up @@ -204,5 +184,27 @@ WFC 12575268
%DAT 253
%DAT 253
%DAT 254
HLT
MVQ rg0, *rg1
MVQ rg1, *rg2
MVQ rg2, D*rg3
MVQ rg3, W*rg4
MVQ rg4, B*rg5
MVQ *rg1[1], rg0
MVQ *rg2[-2], rg1
MVQ D*rg3[3], rg2
MVQ W*rg4[-4], rg3
MVQ B*rg5[5], rg4
MVQ rg0, *rg1[rg9]
MVQ rg1, *rg2[-rg8 * 8]
MVQ rg2, D*rg3[rg7 * 128]
MVQ rg3, W*rg4[-rg6]
MVQ rg4, B*rg5[rg5 * 4]
MVQ *rg1[rg9 - 1], rg0
MVQ *rg2[-rg8 * 8 + 2], rg1
MVQ D*rg3[rg7 * 128 - 3], rg2
MVQ W*rg4[-rg6 + 4], rg3
MVQ B*rg5[rg5 * 4 - 5], rg4
HLT
NOP
%DAT 255
Loading

0 comments on commit 0e6109a

Please sign in to comment.