📄 jdevdisassemblydialog.pas
字号:
//////////////////////////////////////////////////////////////////////
// //
// jdevDisassemblyDialog.pas: Scripted disassembly dialog //
// This provides an interface for the user to save a disasm of //
// multiple sections of memory in different modes. //
// //
// The contents of this file are subject to the Bottled Light //
// Public License Version 1.0 (the "License"); you may not use this //
// file except in compliance with the License. You may obtain a //
// copy of the License at http://www.bottledlight.com/BLPL/ //
// //
// Software distributed under the License is distributed on an //
// "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or //
// implied. See the License for the specific language governing //
// rights and limitations under the License. //
// //
// The Original Code is the Mappy VM User Interface, released //
// April 1st, 2003. The Initial Developer of the Original Code is //
// Bottled Light, Inc. Portions created by Bottled Light, Inc. are //
// Copyright (C) 2001-2003 Bottled Light, Inc. All Rights Reserved. //
// //
// Author(s): //
// Michael Noland (joat), michael@bottledlight.com //
// //
// Changelog: //
// 1.0: First public release (April 1st, 2003) //
// //
// Notes: //
// Needs rewriting to make the output directly recompile in GAS. //
// //
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
unit jdevDisassemblyDialog; //////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
interface ////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, StdCtrls, console, Menus, arm_disass, nexus,
AddressSpace;
//////////////////////////////////////////////////////////////////////
type
TOnDDialogClose = procedure (executed: boolean) of object;
TjdevDisasmDialog = class(TForm)
eDestFile: TEdit;
browseButton: TButton;
lDestination: TLabel;
saveDialog: TSaveDialog;
tasks: TListView;
lCommands: TLabel;
okButton: TButton;
cancelButton: TButton;
rTargetARM: TRadioButton;
rTargetGAS: TRadioButton;
lTargetASM: TLabel;
addButton: TButton;
removeButton: TButton;
eLabel: TEdit;
eMode: TComboBox;
eSize: TEdit;
eAddress: TEdit;
mainMenu: TMainMenu;
mFile: TMenuItem;
mLoadScript: TMenuItem;
mSaveScript: TMenuItem;
openDialog: TOpenDialog;
procedure addButtonClick(Sender: TObject);
procedure removeButtonClick(Sender: TObject);
procedure browseButtonClick(Sender: TObject);
procedure okButtonClick(Sender: TObject);
procedure cancelButtonClick(Sender: TObject);
procedure tasksCompare(Sender: TObject; Item1, Item2: TListItem; Data: Integer; var Compare: Integer);
procedure FormCreate(Sender: TObject);
procedure LoadScript(Sender: TObject);
procedure SaveScript(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
procedure AddEntry(title, address, size, mode: string);
end;
//////////////////////////////////////////////////////////////////////
var
jdevDisasmDialog: TjdevDisasmDialog;
//////////////////////////////////////////////////////////////////////
implementation ///////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
{$R *.DFM}
//////////////////////////////////////////////////////////////////////
procedure TjdevDisasmDialog.AddEntry(title, address, size, mode: string);
var
item: TListItem;
st: string;
base, count: uint32;
begin
// Get the address
st := Trim(address);
if Length(st) < 1 then begin
Beep;
Exit;
end;
if st[1] <> '$' then st := '$' + st;
base := StrToInt(st);
// Get the size
st := Trim(size);
if Length(st) < 1 then begin
Beep;
Exit;
end;
count := StrToInt(st);
// Add the item
item := tasks.Items.Add;
item.Caption := title;
item.SubItems.Add('$'+IntToHex(base and not 1, 8));
item.SubItems.Add(IntToStr(count));
// Get the mode
if Uppercase(mode) = 'ARM' then
item.SubItems.Add('ARM')
else if Uppercase(mode) = 'THUMB' then
item.SubItems.Add('Thumb')
else
item.SubItems.Add('Data');
// Sort the list
tasks.CustomSort(nil, 0);
end;
//////////////////////////////////////////////////////////////////////
procedure TjdevDisasmDialog.addButtonClick(Sender: TObject);
begin
AddEntry(eLabel.Text, eAddress.Text, eSize.Text, eMode.Text)
end;
//////////////////////////////////////////////////////////////////////
procedure TjdevDisasmDialog.removeButtonClick(Sender: TObject);
begin
if Assigned(tasks.Selected) then tasks.Selected.Delete;
end;
//////////////////////////////////////////////////////////////////////
procedure TjdevDisasmDialog.browseButtonClick(Sender: TObject);
begin
saveDialog.DefaultExt := 'asm';
saveDialog.Filter := 'Assembler File|*.asm;*.s|All Files|*.*';
if saveDialog.Execute then
eDestFile.Text := saveDialog.FileName;
end;
//////////////////////////////////////////////////////////////////////
procedure TjdevDisasmDialog.okButtonClick(Sender: TObject);
var
item: TListItem;
i, k: uint32;
text: TStringList;
count, base: uint32;
st: string;
begin
if eDestFile.Text = '' then begin
Beep;
Exit;
end;
disassembler.showJunk := false;
disassembler.useTabs := true;
// Create the disasm file and write a prologue
text := TStringList.Create;
text.Add('Disassembly produced by Mappy VM');
text.Add('Created on ' + DateTimeToStr(Now));
// Add the labels to the disassembler first
for i := 0 to tasks.Items.Count - 1 do begin
item := tasks.Items.Item[i];
base := StrToIntDef(item.SubItems.Strings[0], 0);
disassembler.AddMapping(base, item.Caption);
end;
// Disassemble all the tasks in the list
for i := 0 to tasks.Items.Count - 1 do begin
// Get a new task
item := tasks.Items.Item[i];
// Parse the label, base address, length, and CPU mode of the entry
base := StrToIntDef(item.SubItems.Strings[0], 0);
count := StrToIntDef(item.SubItems.Strings[1], 0);
disassembler.thumbMode := Uppercase(item.SubItems.Strings[2]) = 'THUMB';
// Disassemble this task
if count > 0 then begin
text.Add('');
if Uppercase(item.SubItems.Strings[2]) = 'DATA' then begin
k := 0;
st := item.Caption + ' ';
while k < count do begin
if k and 7 = 0 then begin
Delete(st, Length(st)-1, 2);
text.Add(st);
st := IntToHex(base, 8) + #9'DCD'#9;
end;
st := st + '$' + IntToHex(vmReadWord(base), 8) + ', ';
Inc(base, 4);
Inc(k);
end;
if count and 7 <> 0 then begin
Delete(st, Length(st)-1, 2);
text.Add(st);
end;
end else begin
// text.Add(item.Caption + #9);
disassembler.Emulate(base, count, text);
end;
end;
end;
// Save the disassembly to a file
text.SaveToFile(eDestFile.Text);
text.Free;
// Clear the task list
// tasks.Items.Clear;
disassembler.showJunk := true;
disassembler.useTabs := false;
end;
//////////////////////////////////////////////////////////////////////
procedure TjdevDisasmDialog.cancelButtonClick(Sender: TObject);
begin
Close;
end;
//////////////////////////////////////////////////////////////////////
procedure TjdevDisasmDialog.tasksCompare(Sender: TObject; Item1, Item2: TListItem; Data: Integer; var Compare: Integer);
begin
if (Item2.SubItems.Count > 0) and (Item2.SubItems.Count > 0) then begin
Compare := StrComp(PChar(Item1.SubItems.Strings[0]), PChar(Item2.SubItems.Strings[0]));
if Compare = 0 then Compare := StrComp(PChar(Item1.Caption), PChar(Item2.Caption));
end else
Compare := 0;
end;
//////////////////////////////////////////////////////////////////////
procedure TjdevDisasmDialog.FormCreate(Sender: TObject);
begin
HelpContext := LinkHelp('disassembler_script.html');
eDestFile.Text := '';
eMode.ItemIndex := 0;
end;
//////////////////////////////////////////////////////////////////////
procedure TjdevDisasmDialog.LoadScript(Sender: TObject);
function HaxorLeft(var st: string): string;
var
i: integer;
begin
i := Pos(#9, st);
if i = 0 then i := Length(st)+1;
Result := Copy(st, 1, i-1);
Delete(st, 1, i);
end;
var
index: integer;
items: TStringList;
line, a, b, c, d: string;
begin
openDialog.DefaultExt := 'asr';
openDialog.Filter := 'Assembly Script Resource|*.asr;*.s|All Files|*.*';
if openDialog.Execute then begin
// Load the file
items := TStringList.Create;
items.LoadFromFile(openDialog.FileName);
// A touch of da crude error checking
if (items.Count = 0) or (Copy(Uppercase(items.Strings[0]), 1, 4) <> 'ASR1') then begin
Beep;
Exit;
end;
// Add the entries to the task list
index := 1;
tasks.Items.Clear;
while index < items.Count do begin
line := items.Strings[index];
a := HaxorLeft(line);
b := HaxorLeft(line);
c := HaxorLeft(line);
d := HaxorLeft(line);
AddEntry(a, b, c, d);
Inc(index);
end;
// Close the file
items.Free;
end;
end;
//////////////////////////////////////////////////////////////////////
procedure TjdevDisasmDialog.SaveScript(Sender: TObject);
var
index: integer;
items: TStringList;
item: TListItem;
begin
saveDialog.DefaultExt := 'asr';
saveDialog.Filter := 'Assembly Script Resource|*.asr;*.s|All Files|*.*';
if saveDialog.Execute then begin
// Create a string file
items := TStringList.Create;
items.Add('ASR1 - Generated by Mappy VM');
// Copy the task list to the file
for index := 0 to tasks.Items.Count-1 do begin
item := tasks.Items.Item[index];
items.Add(Format('%s'#9'%s'#9'%s'#9'%s', [item.Caption, item.SubItems.Strings[0], item.SubItems.Strings[1], item.SubItems.Strings[2]]));
end;
// Save and close it
items.SaveToFile(saveDialog.FileName);
items.Free;
end;
end;
//////////////////////////////////////////////////////////////////////
end.
//////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -