| 1 | unit UDisassembler;
|
|---|
| 2 |
|
|---|
| 3 | {$mode delphi}
|
|---|
| 4 |
|
|---|
| 5 | interface
|
|---|
| 6 |
|
|---|
| 7 | uses
|
|---|
| 8 | Classes, SysUtils, UMemory, fgl, UCpu, UInstructionReader, Math, UOpcode;
|
|---|
| 9 |
|
|---|
| 10 | type
|
|---|
| 11 | TDisassemblerLine = class
|
|---|
| 12 | Address: Integer;
|
|---|
| 13 | Opcode: string;
|
|---|
| 14 | Instruction: string;
|
|---|
| 15 | end;
|
|---|
| 16 |
|
|---|
| 17 | { TDisassembler }
|
|---|
| 18 |
|
|---|
| 19 | TDisassembler = class(TInstructionReader)
|
|---|
| 20 | private
|
|---|
| 21 | OpcodeDefs: TOpcodeDefs;
|
|---|
| 22 | public
|
|---|
| 23 | Output: TFPGObjectList<TDisassemblerLine>;
|
|---|
| 24 | procedure Process;
|
|---|
| 25 | constructor Create;
|
|---|
| 26 | destructor Destroy; override;
|
|---|
| 27 | end;
|
|---|
| 28 |
|
|---|
| 29 |
|
|---|
| 30 | implementation
|
|---|
| 31 |
|
|---|
| 32 | { TDisassembler }
|
|---|
| 33 |
|
|---|
| 34 | procedure TDisassembler.Process;
|
|---|
| 35 | var
|
|---|
| 36 | Opcode: Byte;
|
|---|
| 37 | Line: TDisassemblerLine;
|
|---|
| 38 | MemorySize: Integer;
|
|---|
| 39 | Data: QWord;
|
|---|
| 40 | Address: TAddress;
|
|---|
| 41 | AddressRel: TAddressSigned;
|
|---|
| 42 | Reg: TRegIndex;
|
|---|
| 43 | OpcodeDef: TOpcodeDef;
|
|---|
| 44 | begin
|
|---|
| 45 | Init;
|
|---|
| 46 | Output.Clear;
|
|---|
| 47 |
|
|---|
| 48 | MemorySize := MemSize(Cpu.Memory);
|
|---|
| 49 | while IP < MemorySize do begin
|
|---|
| 50 | Prefix := False;
|
|---|
| 51 | Opcode := Read8;
|
|---|
| 52 | if Opcode <= Integer(High(TOpcode)) then begin
|
|---|
| 53 | OpcodeDef := OpcodeDefs.SearchByOpcode(TOpcode(Opcode));
|
|---|
| 54 | Prefix := OpcodeDef.Prefix;
|
|---|
| 55 | case TOpcode(Opcode) of
|
|---|
| 56 | opDataPrefix8: DataSize := bw8;
|
|---|
| 57 | opDataPrefix16: DataSize := bw16;
|
|---|
| 58 | opDataPrefix32: DataSize := bw32;
|
|---|
| 59 | opDataPrefix64: DataSize := bw64;
|
|---|
| 60 | opAddrPrefix8: AddrSize := bw8;
|
|---|
| 61 | opAddrPrefix16: AddrSize := bw16;
|
|---|
| 62 | opAddrPrefix32: AddrSize := bw32;
|
|---|
| 63 | opAddrPrefix64: AddrSize := bw64;
|
|---|
| 64 | end;
|
|---|
| 65 | Line := TDisassemblerLine.Create;
|
|---|
| 66 | Line.Address := IP - 1;
|
|---|
| 67 | Line.Opcode := IntToHex(Opcode, 2);
|
|---|
| 68 | Line.Instruction := OpcodeDef.Name;
|
|---|
| 69 | case OpcodeDef.Param1 of
|
|---|
| 70 | prReg: begin
|
|---|
| 71 | Reg := Read8;
|
|---|
| 72 | Line.Opcode := Line.Opcode + ' ' + IntToHex(Reg, 2);
|
|---|
| 73 | Line.Instruction := Line.Instruction + ' R' + IntToStr(Reg);
|
|---|
| 74 | end;
|
|---|
| 75 | prData: begin
|
|---|
| 76 | Data := ReadData;
|
|---|
| 77 | Line.Opcode := Line.Opcode + ' ' + IntToHex(Data, BitWidthBytes[DataSize] * 2);
|
|---|
| 78 | Line.Instruction := Line.Instruction + ' ' + IntToHexEx(Data, -1, '$');
|
|---|
| 79 | end;
|
|---|
| 80 | prAddr: begin
|
|---|
| 81 | Address := ReadAddress;
|
|---|
| 82 | Line.Opcode := Line.Opcode + ' ' + IntToHex(Address, BitWidthBytes[AddrSize] * 2);
|
|---|
| 83 | Line.Instruction := Line.Instruction + ' ' + IntToHexEx(Address, -1, '$');
|
|---|
| 84 | end;
|
|---|
| 85 | prAddrRel: begin
|
|---|
| 86 | AddressRel := ReadAddressSigned;
|
|---|
| 87 | Line.Opcode := Line.Opcode + ' ' + IntToHexEx(QWord(AddressRel), BitWidthBytes[AddrSize] * 2);
|
|---|
| 88 | Line.Instruction := Line.Instruction + ' ' + IntToHexEx(AddressRel, -1, '$');
|
|---|
| 89 | end;
|
|---|
| 90 | end;
|
|---|
| 91 | case OpcodeDef.Param2 of
|
|---|
| 92 | prReg: begin
|
|---|
| 93 | Reg := Read8;
|
|---|
| 94 | Line.Opcode := Line.Opcode + ' ' + IntToHex(Reg, 2);
|
|---|
| 95 | Line.Instruction := Line.Instruction + ', R' + IntToStr(Reg);
|
|---|
| 96 | end;
|
|---|
| 97 | prData: begin
|
|---|
| 98 | Data := ReadData;
|
|---|
| 99 | Line.Opcode := Line.Opcode + ' ' + IntToHexEx(Data, BitWidthBytes[DataSize] * 2);
|
|---|
| 100 | Line.Instruction := Line.Instruction + ', ' + IntToHexEx(Data, -1, '$');
|
|---|
| 101 | end;
|
|---|
| 102 | prAddr: begin
|
|---|
| 103 | Address := ReadAddress;
|
|---|
| 104 | Line.Opcode := Line.Opcode + ' ' + IntToHex(Address, BitWidthBytes[AddrSize] * 2);
|
|---|
| 105 | Line.Instruction := Line.Instruction + ', ' + IntToHexEx(Address, -1, '$');
|
|---|
| 106 | end;
|
|---|
| 107 | prAddrRel: begin
|
|---|
| 108 | AddressRel := ReadAddressSigned;
|
|---|
| 109 | Line.Opcode := Line.Opcode + ' ' + IntToHex(QWord(AddressRel), BitWidthBytes[AddrSize] * 2);
|
|---|
| 110 | Line.Instruction := Line.Instruction + ', ' + IntToHexEx(AddressRel, -1, '$');
|
|---|
| 111 | end;
|
|---|
| 112 | end;
|
|---|
| 113 | case OpcodeDef.Param3 of
|
|---|
| 114 | prReg: begin
|
|---|
| 115 | Reg := Read8;
|
|---|
| 116 | Line.Opcode := Line.Opcode + ' ' + IntToHex(Reg, 2);
|
|---|
| 117 | Line.Instruction := Line.Instruction + ', R' + IntToStr(Reg);
|
|---|
| 118 | end;
|
|---|
| 119 | prData: begin
|
|---|
| 120 | Data := ReadData;
|
|---|
| 121 | Line.Opcode := Line.Opcode + ' ' + IntToHex(Data, BitWidthBytes[DataSize] * 2);
|
|---|
| 122 | Line.Instruction := Line.Instruction + ', ' + IntToHexEx(Data, -1, '$');
|
|---|
| 123 | end;
|
|---|
| 124 | prAddr: begin
|
|---|
| 125 | Address := ReadAddress;
|
|---|
| 126 | Line.Opcode := Line.Opcode + ' ' + IntToHex(Address, BitWidthBytes[AddrSize] * 2);
|
|---|
| 127 | Line.Instruction := Line.Instruction + ', ' + IntToHexEx(Address, -1, '$');
|
|---|
| 128 | end;
|
|---|
| 129 | prAddrRel: begin
|
|---|
| 130 | AddressRel := ReadAddressSigned;
|
|---|
| 131 | Line.Opcode := Line.Opcode + ' ' + IntToHex(QWord(AddressRel), BitWidthBytes[AddrSize] * 2);
|
|---|
| 132 | Line.Instruction := Line.Instruction + ', ' + IntToHexEx(AddressRel, -1, '$');
|
|---|
| 133 | end;
|
|---|
| 134 | end;
|
|---|
| 135 | Output.Add(Line);
|
|---|
| 136 | if not Prefix then begin
|
|---|
| 137 | DataSize := DataSizeBase;
|
|---|
| 138 | AddrSize := AddrSizeBase;
|
|---|
| 139 | end;
|
|---|
| 140 | end else begin
|
|---|
| 141 | {Line := TDisassemblerLine.Create;
|
|---|
| 142 | Line.Address := IP;
|
|---|
| 143 | Line.Opcode := IntToHex(Opcode, 2);
|
|---|
| 144 | Line.Instruction := '';
|
|---|
| 145 | Output.Add(Line);
|
|---|
| 146 | }
|
|---|
| 147 | end;
|
|---|
| 148 | end;
|
|---|
| 149 | end;
|
|---|
| 150 |
|
|---|
| 151 | constructor TDisassembler.Create;
|
|---|
| 152 | begin
|
|---|
| 153 | OpcodeDefs := TOpcodeDefs.Create;
|
|---|
| 154 | Output := TFPGObjectList<TDisassemblerLine>.Create;
|
|---|
| 155 | end;
|
|---|
| 156 |
|
|---|
| 157 | destructor TDisassembler.Destroy;
|
|---|
| 158 | begin
|
|---|
| 159 | FreeAndNil(Output);
|
|---|
| 160 | FreeAndNil(OpcodeDefs);
|
|---|
| 161 | inherited Destroy;
|
|---|
| 162 | end;
|
|---|
| 163 |
|
|---|
| 164 |
|
|---|
| 165 | end.
|
|---|
| 166 |
|
|---|