HEX file?

10 отговора 257 прегледа
#1

HEX file?

Zdrasti na vsichki,
Sega prava edin programator na PIC-ove. Problema mi e che ne moga da namera info za strukturata na HEX failovete deto gi generirat kompilatorite. Niakoi znae li Unit na Delphi za taia cel ili pone info za strukturata im?

Mersi

Отговор
в отговор на Kid #2

Re: HEX file?

Има различни формати за HEX файловете - INHX8S, INHX8M, INHX16, INHX32... Кой точно ти трябва?
Виж тук и тук.

Отговор
в отговор на Kid #3

Най-добре да поддържаш всички формати.

Едва ли ще намериш юнити за Паскал, но като изчетеш алгоритмите лесно ще си ги направиш.

Сега гледам от 1996 едни мои юнити на Паскал, ако искаш да ти пратя на мейла:

function IntelHexStringToLine(var S: string; Config: pConfig; flWord: boolean): boolean;
function SaveBufToIntelHexFile(var Buf; Len: word; Config: pConfig; flWord: boolean; FileName: string):boolean;

Отговор
в отговор на Kid #4

Re: HEX file?

Mersi za otgovorite! Informaciata naistina mi svarshi rabota i si napravih nujnite proceduri


Отговор
в отговор на Kid #5

Re: HEX file?

Препоръчвам ти да си направиш тия функциики на Ц++. Правих си асм декомпилатор на делфи за пик, после го написах на Ц++ и да ти кажа разликата беше голяма. Не искам да обидя делфи-то (най вече щот си го харесвам) но не е много удобно за работа на ниво байт/бит. Ако желаеш мога да ти пратя сорса и на двете.

Отговор
в отговор на DVMSoft #6

Re: HEX file?

Здравей!
Кой е този проблем който си имал с делфито а си решил така лесно със си-то?
Хубаво е когато изказваш някакво мнение да можеш да го защитиш с факти!
Венцислав Александрийски

Отговор
в отговор на DVMSoft #7

Mnogo te molia!

Da be i na men mi e mnogo interesno. Sto ne postnesh i dvata source, che da vidim nesto, koeto na CPP stava po gotino ot na Pascal!
Mnogo te molia!

Отговор
в отговор на NikB #8

Човека донякъде е прав...

операциите с битове на C са по лесни и кода(разбирай сорса) става по-компактен т.е. малък, но това не го прави по-четим - най вероятно следващия който ще се мъчи да го разчете ще има да ругае ;-)))). Аз също съм правил "красиви" изпълнения и ми е трябвало доста време да си разбера собствените писания - точно при операции с битове и цикли ;-))))
Няма смисъл да се заяждате - двата езика имат достатъчно различни синтактични конструкции - C -то е оптимизирано точно за да дава по-компактен код - при подобни ситуации.

---
Отговор
в отговор на PhantomAS #9

Re: Човека донякъде е прав...

Ще се поразровя из архивите си и ще ви ги постна щом толкова настоявате

Отговор
в отговор на Kid #10

Делфи код

unit main;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, ComCtrls, XPMan;

type
TMainForm = class(TForm)
Code: TRichEdit;
StatusBar: TStatusBar;
MainPanel: TPanel;
OpenButton: TButton;
GoButton: TButton;
SaveButton: TButton;
AboutButton: TButton;
XButton: TButton;
Progress: TProgressBar;
OpenDialog: TOpenDialog;
SaveDialog: TSaveDialog;
XPManifest: TXPManifest;
procedure XButtonClick(Sender: TObject);
procedure OpenButtonMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure GoButtonMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure MainPanelMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure CodeMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure SaveButtonMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure AboutButtonClick(Sender: TObject);
procedure OpenButtonClick(Sender: TObject);
procedure GoButtonClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure SaveButtonClick(Sender: TObject);
private
{ Private declarations }
public
procedure ParseLine(l:integer);
function HexToInt(x:string):integer;
procedure DoCommand(l:integer);
function IntToBin(Value: LongInt;Size: Integer): String;
function BinToInt(Value: String): LongInt;
end;

var
MainForm: TMainForm;
HEXL:TStringList;
errmsg,msg:string;
errdetect:boolean;
total:integer;
implementation
uses abt;
{$R *.dfm}


function TMainForm.IntToBin(Value: LongInt;Size: Integer): String;
var
i: Integer;
begin
Result:='';
for i:=Size downto 0 do begin
if Value and (1 shl i)<>0 then
begin
Result:=Result+'1';
end
else
begin
Result:=Result+'0';
end;
end;
end;

function TMainForm.BinToInt(Value: String): LongInt;
var
i,Size: Integer;
begin
Result:=0;
Size:=Length(Value);
for i:=Size downto 0 do
begin
if Copy(Value,i,1)='1' then
begin
Result:=Result+(1 shl i);
end;
end;
end;


procedure TMainForm.DoCommand(l:integer);
var i,x,a,y:integer;
tmp,t,b1,b2,at:string;
begin
msg:='!!!Unknow code!!!';
tmp:=Copy(HEXL.Strings[l],10,Length(HEXL.Strings[l])-11);
Progress.Position:=Progress.Position+1;
if tmp = '' then exit;
total := total + Length(tmp);
a:=1;
for i := 1 to (Length(tmp) div 4) do
begin
t:= copy (tmp,a,4);
a:=a+4;
//ShowMessage('Command '+t);
//Code.Lines.Add(t);
if t = '0000' then
Code.Lines.Add(#9+'NOP');
if t = '0800' then
Code.Lines.Add(#9+'RETURN');
if t = '6200' then
Code.Lines.Add(#9+'OPTION');
if t = '6400' then
Code.Lines.Add(#9+'CLRWDT');
if t = '0900' then
Code.Lines.Add(#9+'RETFIE');
if t = '6300' then
Code.Lines.Add(#9+'SLEEP');
b1:=copy(t,1,2);
b2:=copy(t,3,2);
//ShowMessage(b2+b1);
if copy(b2,1,1) = '3' then
begin
if (b2='3E') or (b2='3F') then
msg:=Format('ADDLW 0x%s',[b1]);
if b2='39' then
msg:=Format('ANDLW 0x%s',[b1]);
if b2='34' then
msg:=Format('RETLW 0x%s',[b1]);
if b2='3C' then
msg:=Format('SUBLW 0x%s',[b1]);
if b2='30' then
msg:=Format('MOVLW 0x%s',[b1]);
if b2='3A' then
msg:=Format('XORLW 0x%s',[b1]);
if b2='38' then
msg:=Format('IORLW 0x%s',[b1]);
Code.Lines.Add(#9+msg);
end;
if copy(b2,1,1) = '0' then
begin
if b2='07' then
begin
x:=HexToInt(b1);
if x >= 128 then
msg:=Format('ADDWF 0x%s,0x1',[IntToHex(x-128,2)])
else
msg:=Format('ADDWF 0x%s,0x0',[IntToHex(x,2)]);
end;
if b2='05' then
begin
x:=HexToInt(b1);
if x >= 128 then
msg:=Format('ANDWF 0x%s,0x1',[IntToHex(x-128,2)])
else
msg:=Format('ANDWF 0x%s,0x0',[IntToHex(x,2)]);
end;
if (b2='01')and (copy(b1,1,1) = '8') then
begin
x:=HexToInt(b1);
msg:=Format('CLRF 0x%s',[IntToHex(x-128,2)])
end;
if b2='09' then
begin
x:=HexToInt(b1);
if x >= 128 then
msg:=Format('COMF 0x%s,0x1',[IntToHex(x-128,2)])
else
msg:=Format('COMF 0x%s,0x0',[IntToHex(x,2)]);
end;
if b2='03' then
begin
x:=HexToInt(b1);
if x >= 128 then
msg:=Format('DECF 0x%s,0x1',[IntToHex(x-128,2)])
else
msg:=Format('DECF 0x%s,0x0',[IntToHex(x,2)]);
end;
if b2='0B' then
begin
x:=HexToInt(b1);
if x >= 128 then
msg:=Format('DECFSZ 0x%s,0x1',[IntToHex(x-128,2)])
else
msg:=Format('DECFSZ 0x%s,0x0',[IntToHex(x,2)]);
end;
if b2='0A' then
begin
x:=HexToInt(b1);
if x >= 128 then
msg:=Format('INCF 0x%s,0x1',[IntToHex(x-128,2)])
else
msg:=Format('INCF 0x%s,0x0',[IntToHex(x,2)]);
end;
if b2='0F' then
begin
x:=HexToInt(b1);
if x >= 128 then
msg:=Format('INCFSZ 0x%s,0x1',[IntToHex(x-128,2)])
else
msg:=Format('INCFSZ 0x%s,0x0',[IntToHex(x,2)]);
end;
if b2='04' then
begin
x:=HexToInt(b1);
if x >= 128 then
msg:=Format('IORWF 0x%s,0x1',[IntToHex(x-128,2)])
else
msg:=Format('IORWF 0x%s,0x0',[IntToHex(x,2)]);
end;
if b2='08' then
begin
x:=HexToInt(b1);
if x >= 128 then
msg:=Format('MOVF 0x%s,0x1',[IntToHex(x-128,2)])
else
msg:=Format('MOVF 0x%s,0x0',[IntToHex(x,2)]);
end;
if (b2='00')and(copy(b1,1,1)='8') then
begin
x:=HexToInt(b1);
msg:=Format('MOVWF 0x%s',[IntToHex(x-128,2)])
end;
if b2='0D' then
begin
x:=HexToInt(b1);
if x >= 128 then
msg:=Format('RLF 0x%s,0x1',[IntToHex(x-128,2)])
else
msg:=Format('RLF 0x%s,0x0',[IntToHex(x,2)]);
end;
if b2='0C' then
begin
x:=HexToInt(b1);
if x >= 128 then
msg:=Format('RRF 0x%s,0x1',[IntToHex(x-128,2)])
else
msg:=Format('RRF 0x%s,0x0',[IntToHex(x,2)]);
end;
if b2='02' then
begin
x:=HexToInt(b1);
if x >= 128 then
msg:=Format('SUBWF 0x%s,0x1',[IntToHex(x-128,2)])
else
msg:=Format('SUBWF 0x%s,0x0',[IntToHex(x,2)]);
end;
if b2='0E' then
begin
x:=HexToInt(b1);
if x >= 128 then
msg:=Format('SWAPF 0x%s,0x1',[IntToHex(x-128,2)])
else
msg:=Format('SWAPF 0x%s,0x0',[IntToHex(x,2)]);
end;
if b2='06' then
begin
x:=HexToInt(b1);
if x >= 128 then
msg:=Format('XORWF 0x%s,0x1',[IntToHex(x-128,2)])
else
msg:=Format('XORWF 0x%s,0x0',[IntToHex(x,2)]);
end;
Code.Lines.Add(#9+msg);
end;
if (copy(b2,1,1) = '1')and(b2[2] in ['0'..'3']) then
begin
at:=IntToBin(HexToInt(b2) xor 16,2);
//ShowMessage(at);
x:=HexToInt(b1);
if x>=128 then
begin
at:= at + '1';
x:=x - 128;
end;
//ShowMessage(IntToHex(BinToInt(at),1));
msg:=Format('BCF 0x%s,0x0%s',[IntToHex(x,2),IntTostr(BinToInt(at))]);
Code.Lines.Add(#9+msg);
end;
if (copy(b2,1,1) = '1')and(b2[2] in ['4'..'7']) then
begin
x:=HexToInt(b1);
if x>=128 then
begin
x:=x-128;
y:= HexToInt(b2)-16;
case y of
0:y:=1;
1:y:=3;
2:y:=5;
3:y:=7;
end;

end
else
begin
y:= HexToInt(b2)-16;
case y of
0:y:=0;
1:y:=2;
2:y:=4;
3:y:=6;
end;
end;
msg:=Format('BSF 0x%s,0x0%s',[IntToHex(x,2),IntToHex(y,1)]);
Code.Lines.Add(#9+msg);
end;
if (copy(b2,1,1) = '1')and(b2[2] in ['8','9','A','B']) then
begin
x:=HexToInt(b1);
if x>=128 then
begin
x:=x-128;
y:= HexToInt(b2)-16;
case y of
0:y:=1;
1:y:=3;
2:y:=5;
3:y:=7;
end;

end
else
begin
y:= HexToInt(b2)-16;
case y of
0:y:=0;
1:y:=2;
2:y:=4;
3:y:=6;
end;
end;
msg:=Format('BTFSC 0x%s,0x0%s',[IntToHex(x,2),IntToHex(y,1)]);
Code.Lines.Add(#9+msg);
end;
if (copy(b2,1,1) = '1')and(b2[2] in ['C'..'F']) then
begin
x:=HexToInt(b1);
if x>=128 then
begin
x:=x-128;
y:= HexToInt(b2)-16;
case y of
0:y:=1;
1:y:=3;
2:y:=5;
3:y:=7;
end;

end
else
begin
y:= HexToInt(b2)-16;
case y of
0:y:=0;
1:y:=2;
2:y:=4;
3:y:=6;
end;
end;
msg:=Format('BTFSS 0x%s,0x0%s',[IntToHex(x,2),IntToHex(y,1)]);
Code.Lines.Add(#9+msg);
end;
if (copy(b2,1,1) = '2')and(b2[2] in ['0'..'7']) then
begin
x:=HexToInt(b2+b1) - 10240;
msg:=Format('CALL 0x%s',[IntToHex(x,3)]);
Code.Lines.Add(#9+msg);
end;
if (copy(b2,1,1) = '2')and(b2[2] in ['8'..'9','A'..'F']) then
begin
x:=HexToInt(b2+b1) - 10240;
msg:=Format('GOTO 0x%s',[IntToHex(x,3)]);
Code.Lines.Add(#9+msg);
end;
end;
end;

function TMainForm.HexToInt(x:string):integer;
const HEX : array['A'..'F'] of integer = (10,11,12,13,14,15);
var Int,
i : integer;
Begin
Int := 0;
for i := 1 to Length(x) do
if x < 'A' then Int := Int * 16 + ORD(x) - 48
else Int := Int * 16 + HEX[x];
Result:= int;
end;
procedure TMainForm.ParseLine(l:integer);
var i,a,b,c:integer;
t:char;
tmp:string;
begin
Progress.Position:=Progress.Position +1;
if HEXL.Strings[l] = '' then exit;
if Length(HEXL.Strings[l]) < 11 then
begin
errmsg:=format('Error! line %d - Invalid line length (%d chars).',[l+1,Length(HEXL.Strings[l])]);
Code.Lines.Add(errmsg);
errdetect:=true;
end;
if not (HEXL.Strings[l][1] = ':') then
begin
errmsg:=format('Error! Line %d - `:` expected, but `%s` found',[l+1,HEXL.Strings[l][1]]);
Code.Lines.Add(errmsg);
errdetect:=true;
end;
for i := 1 to Length(HEXL.Strings[l]) do
begin
t:=HEXL.Strings[l];
if not (t in ['0'..'9','A'..'F','a'..'f',':']) then
begin
errmsg:=format('Error! Line %d contain illegal character `%s`',[l+1,HEXL.Strings[l]]);
Code.Lines.Add(errmsg);
errdetect:=true;
end;
end;
if errdetect then exit;
Application.ProcessMessages;
i:= HexToInt(Copy(HEXL.Strings[l],2,2));
//ShowMessage(IntToStr(i)+' bytes on this line.');
if (i*2+11) <> Length(HEXL.Strings[l]) then
begin
errdetect:=true;
errmsg:=format('Error! line %d - Invalid line length `%d`, must be %d',[l+1,Length(HEXL.Strings[l]),(i*2+11)]);
Code.Lines.Add(errmsg);
end;
b:=2;c:=0;
for a:= 1 to (Length(HEXL.Strings[l]) div 2)-1 do
begin
tmp:= copy(HEXL.Strings[l],b,1);
tmp:= tmp +copy(HEXL.Strings[l],b+1,1);
//Code.Lines.Add('line '+IntToStr(l)+' Bytes N'+IntToStr(a)+':'+tmp);
b:=b+2;
c:=c + HexToInt(tmp);
//ShowMessage('tmp='+tmp);
end;
//ShowMessage(IntToStr(c));
if c < 256 then
begin
a:= 256 - c;
//ShowMessage('Checksum = '+IntToHex(a,2));
end
else
begin
tmp:=IntToHex(c,6);
//ShowMessage('All='+tmp);
tmp:= copy (tmp,Length(tmp)-1,2);
//ShowMessage('Cut='+tmp);
//if HexToInt(tmp) > 256 then tmp:=tmp[Length(tmp)-1];
a:= HexToInt(tmp);
//ShowMessage('Checksum = '+IntToHex(a,2));
end;
{ if not (a = HexToInt(copy(HEXL.Strings[l],Length(HEXL.Strings[l])-1,2))) then
begin
errdetect:=true;
ShowMessage('tmp = '+tmp+' '+IntToStr(a)+', a trqbva da bude '+copy(HEXL.Strings[l],Length(HEXL.Strings[l])-1,2));
errmsg:=format('Error! Broken CRC at line %d',[l+1]);
Code.Lines.Add(errmsg);
end;}

end;

procedure TMainForm.XButtonClick(Sender: TObject);
begin
Close;
end;

procedure TMainForm.OpenButtonMouseMove(Sender: TObject;
Shift: TShiftState; X, Y: Integer);
begin
StatusBar.Panels[0].Text := 'Open HEX file to be disassembled.';
end;

procedure TMainForm.GoButtonMouseMove(Sender: TObject; Shift: TShiftState;
X, Y: Integer);
begin
StatusBar.Panels[0].Text := 'Click here to start disassembling.';
end;

procedure TMainForm.MainPanelMouseMove(Sender: TObject; Shift: TShiftState;
X, Y: Integer);
begin
StatusBar.Panels[0].Text := '';
end;

procedure TMainForm.CodeMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
StatusBar.Panels[0].Text := '';
end;

procedure TMainForm.SaveButtonMouseMove(Sender: TObject;
Shift: TShiftState; X, Y: Integer);
begin
StatusBar.Panels[0].Text := 'Saving current result to file.';
end;

procedure TMainForm.AboutButtonClick(Sender: TObject);
begin
AboutForm.ShowModal;
end;

procedure TMainForm.OpenButtonClick(Sender: TObject);
begin
if (OpenDialog.Execute)and(OpenDialog.FileName <> '') then
begin
//ShowMessage('succ opened!');
Progress.Position:=0;
Code.Lines.Clear;
HEXL:=TStringList.Create;
HEXL.LoadFromFile(OpenDialog.FileName);
GoButton.Enabled:=true;
end;
end;

procedure TMainForm.GoButtonClick(Sender: TObject);
var lines:Integer;
begin
Progress.Position:=0;
Code.Lines.Clear;
total:=0;
errdetect:=false;
Progress.Max:=HEXL.Count;
for lines := 0 to HEXL.Count-1 do
ParseLine(lines);
Progress.Position:=0;
if not errdetect then
begin
for lines := 0 to HEXL.Count-1 do
DoCommand(lines);
total:=total div 2;
msg:= format('Total: %d bytes of code.',[total]);
if total > 1024 then
begin
total:=total div 1024;
msg:= format('Total: %d Kb of code.',[total]);
end;
Code.Lines.Add(msg);
StatusBar.Panels[0].Text:='I`m done!';
Application.ProcessMessages;
end;

end;

procedure TMainForm.FormCreate(Sender: TObject);
begin
errdetect:=false;
end;

procedure TMainForm.SaveButtonClick(Sender: TObject);
begin
SaveDialog.FileName:=ExtractFileName(OpenDialog.FileName);
if SaveDialog.Execute then
begin

Code.Lines.SaveToFile(SaveDialog.FileName);
end;
end;

end.

Отговор
в отговор на DVMSoft #11

Ц код

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

char usage[] = "usage: PICDIS {options} input-file [control-file]\n\n"
"options: -a produce output suitable for an assembler\n"
" -b binary input file (default: Intel hex16)\n";

#define COMMANDS 36

struct cmdmask {
unsigned pattern;
unsigned mask;
int type; /* 0=-; 1=f; 2=f,d; 3=f,b; 4=k(8-bit); 5=k(11-bit) */
char mnemonic[7];
} cmdlist[COMMANDS] = {
0x0700, 0xff00, 2, "ADDWF",
0x0500, 0xff00, 2, "ANDWF",
0x0180, 0xff80, 1, "CLRF",
0x0100, 0xff80, 0, "CLRW",
0x0900, 0xff00, 2, "COMF",
0x0300, 0xff00, 2, "DECF",
0x0b00, 0xff00, 2, "DECFSZ",
0x0a00, 0xff00, 2, "INCF",
0x0f00, 0xff00, 2, "INCFSZ",
0x0400, 0xff00, 2, "IORWF",
0x0800, 0xff00, 2, "MOVF",
0x0080, 0xff80, 1, "MOVWF",
0x0000, 0xff9f, 0, "NOP",
0x0d00, 0xff00, 2, "RLF",
0x0c00, 0xff00, 2, "RRF",
0x0200, 0xff00, 2, "SUBWF",
0x0e00, 0xff00, 2, "SWAPF",
0x0600, 0xff00, 2, "XORWF",
0x1000, 0xfc00, 3, "BCF",
0x1400, 0xfc00, 3, "BSF",
0x1800, 0xfc00, 3, "BTFSC",
0x1c00, 0xfc00, 3, "BTFSS",
0x3e00, 0xfe00, 4, "ADDLW",
0x3900, 0xff00, 4, "ANDLW",
0x2000, 0xf800, 5, "CALL",
0x0064, 0xffff, 0, "CLRWDT",
0x2800, 0xf800, 5, "GOTO",
0x3800, 0xff00, 4, "IORLW",
0x3000, 0xfc00, 4, "MOVLW",
0x0009, 0xffff, 0, "RETFIE",
0x3400, 0xfc00, 4, "RETLW",
0x0008, 0xffff, 0, "RETURN",
0x0063, 0xffff, 0, "SLEEP",
0x3c00, 0xfe00, 4, "SUBLW",
0x3a00, 0xff00, 4, "XORLW",
0x0062, 0xffff, 0, "OPTION"
};


#define CTL_LIST_SIZE 256

struct ctl_entry {
unsigned address;
char type[3];
char *text;
struct ctl_entry *next;
} *(ctl_list[CTL_LIST_SIZE]);

long checksum = -1;
int binary = 0;
int for_assembler = 0;
FILE *fin; /* input file */
char *fnin = NULL; /* input file name */
unsigned int input_address = -1; /* input file address counter */
int hex_left = 0; /* remaining words in this hex input file line */
char hex_line[1032];

#define ROM_SIZE 0x800
int ref_count[ROM_SIZE]; /* number of references to an address */


/*
* Disassemble a single command word
*/
int command(unsigned cmd, char *line)
{
int i;

line[0] = 0;

/* special commands */
if ((cmd & 0xfff8) == 0x0068) {
sprintf(line, "TRIS 0x%x", cmd & 7);
return -1;
}

for (i = 0; i < COMMANDS; i++)
if ((cmd & cmdlist.mask) == cmdlist.pattern) break;
if (i >= COMMANDS) {
sprintf(line, "???");
return -1;
} else
switch (cmdlist.type) {
case 0:
sprintf(line, "%s", cmdlist.mnemonic);
break;
case 1:
sprintf(line, "%s 0x%02x", cmdlist.mnemonic, cmd & 0x7f);
break;
case 2:
sprintf(line, "%s 0x%02x,%d", cmdlist.mnemonic, cmd & 0x7f,
(cmd & 0x80) != 0);
break;
case 3:
sprintf(line, "%s 0x%02x,%d", cmdlist.mnemonic, cmd & 0x7f,
(cmd >> 7) & 7);
break;
case 4:
sprintf(line, "%s 0x%02x", cmdlist.mnemonic, cmd & 0xff);
break;
case 5:
if (for_assembler)
sprintf(line, "%s L%c%03X", cmdlist.mnemonic,
'A' - 1 + ref_count[cmd & 0x7ff], cmd & 0x7ff);
else
sprintf(line, "%s 0x%03x", cmdlist.mnemonic, cmd & 0x7ff);
break;
default:
fprintf(stderr, "Internal error (cmdlist[].type)!\n");
exit(1);
}
return cmdlist.type;
}


/*
* Read in control file and store it in a hash data structure
*/
void read_ctl(char *fn)
{
FILE *fin;
char line[200], type[3];
int i, pos;
unsigned addr;
struct ctl_entry *entry;
char *text;

fin = fopen(fn, "r");
if (!fin) {
fprintf(stderr, "Can't open control file '%s", fn);
perror("'");
exit(1);
}
i = 0;
type[2] = 0;
while (!feof(fin)) {
fgets(line, 199, fin);
i++;
while (*line && (isspace(line[strlen(line)-1])
|| line[strlen(line)-1] == '\n'))
line[strlen(line)-1] = 0;
type[0] = tolower(line[0]);
type[1] = tolower(line[1]);
if (!strcmp(type, "pr")) {
printf(" ; %s\n", line + 3);
continue;
}
if (strlen(line) < 3) continue;
if (sscanf(line + 2, "%x %n", &addr, &pos) != 1) {
fprintf(stderr, "Syntax error in line %d of '%s':\n%s\n",
i, fn, line);
exit(1);
}
if (!strcmp(type, "cs")) {
checksum = addr;
continue;
}
entry = (struct ctl_entry *) malloc(sizeof(struct ctl_entry));
text = (char *) malloc(sizeof(char) * (strlen(line) - pos + 1));
if (!entry || !text) {
fprintf(stderr, "Sorry, not enough memory for this control file.\n");
exit(1);
}
strcpy(text, line + pos + 2);
strcpy(entry->type, type);
entry->address = addr;
entry->text = text;
entry->next = ctl_list[addr % CTL_LIST_SIZE];
ctl_list[addr % CTL_LIST_SIZE] = entry;
}
fclose(fin);
return;
}


/*
* Search a control file entry in hash data structure
*/
char *find_entry(unsigned address, char *type)
{
struct ctl_entry *ctl;

ctl = ctl_list[address % CTL_LIST_SIZE];
while (ctl) {
if (ctl->address == address && !strcmp(ctl->type, type))
return ctl->text;
ctl = ctl->next;
}
return NULL;
}


/*
* Rewind input file
*/
void rewind_input(void)
{
rewind(fin);
hex_left = 0;
input_address = -1;
return;
}


/*
* hexadecimal to integer conversion
*/
unsigned int htoi(char *hex, int length)
{
int i;
unsigned int v = 0;

for (i = 0; i < length; i++) {
v <<= 4;
if (hex >= '0' && hex <= '9') v += hex - '0';
else if (hex >= 'a' && hex <= 'f') v += hex - 'a' + 10;
else if (hex >= 'A' && hex <= 'F') v += hex - 'A' + 10;
else {
fprintf(stderr, "Error: '%.4s' doesn't look very hexadecimal, right?\n",
hex);
exit(1);
}
}

return v;
}


/*
* Read next word from input file. Returns 0 if EOF has been reached,
* 1 otherwise.
*/
int get_word(unsigned int *value)
{
static hex_count = 0;
int i, sum;

if (binary) {
*value = getc(fin) << 8;
*value |= getc(fin);
} else {
if (hex_left < 1) {
do {
fgets(hex_line, 1031, fin);
} while (!feof(fin) && (strlen(hex_line) < 9 || hex_line[0] != ':'));
hex_left = hex_count = htoi(hex_line + 1, 2);
if (strlen(hex_line) - 11 < hex_count * 4) {
fprintf(stderr, "Intel hex16 line too short:\n%s\n", hex_line);
exit(1);
}
input_address = htoi(hex_line + 3, 4) - 1;
sum = 0;
for (i = 1; i <= hex_count*4 + 9; i += 2)
sum += htoi(hex_line + i, 2);
if ((sum & 0xff) != 0) {
fprintf(stderr, "Intel hex16 checksum error in line:\n%s\n",
hex_line);
exit(1);
}
if (htoi(hex_line + 7, 2) == 1) return 0;
if (htoi(hex_line + 7, 2) != 0) {
fprintf(stderr, "Unknown Intel hex16 type code 0x%02x!\n",
htoi(hex_line + 7, 2));
exit(1);
}
}
*value = htoi(hex_line + 9 + (hex_count - hex_left) * 4, 4);
hex_left--;
}
input_address++;

return !feof(fin);
}



int main(int argc, char **argv)
{
char *fnctl = NULL;
unsigned expected_address, cmd = 0;
char line[100], comment[300], *text;
const char indent[] = " ";
unsigned sum = 0;
int i, j, count = 0;
int references, type;

fprintf(stderr, "PICDIS 1.1 -- PIC16C84 Disassembler -- Markus Kuhn\n\n");
for (i = 0; i < CTL_LIST_SIZE; i++)
ctl_list = NULL;

/* parse command line */
for (i = 1; i < argc; i++)
if (argv[0] == '-')
for (j = 1; argv[j]; j++)
switch (argv[j]) {
case 'a':
case 'A':
for_assembler = 1;
break;
case 'b':
case 'B':
binary = 1;
break;
default:
fprintf(stderr, usage);
exit(1);
}
else if (fnin == NULL) fnin = argv;
else if (fnctl == NULL) fnctl = argv;
else {
fprintf(stderr, usage);
exit(1);
}
if (fnin == NULL) {
fprintf(stderr, usage);
exit(1);
}

/* open input files */
fin = fopen(fnin, binary ? "rb" : "r");
if (!fin) {
fprintf(stderr, "Can't open input file '%s", fnin);
perror("'");
exit(1);
}
if (fnctl)
read_ctl(fnctl);

/* first pass (find references for labels) */
for (i = 0; i < ROM_SIZE; i++) ref_count = 0;
rewind_input();
while (get_word(&cmd))
if ((cmd & 0xf000) == 0x2000) {
/* cmd is CALL or GOTO */
ref_count[cmd & 0x7ff]++;
}
for (i = 0; i < ROM_SIZE; i++)
if (ref_count > 26) ref_count = 26; /* we have only 'A' - 'Z' */

expected_address = 0;
rewind_input();
/* main loop */
while (get_word(&cmd)) {
sum = sum ^ cmd;
sum = ((sum << 1) | (sum >> 15)) & 0xffff;
type = command(cmd, line);
text = find_entry(input_address, "hd");
if (text) {
printf("%s;\n", indent);
printf("%s; %s\n", indent, text);
printf("%s;\n", indent);
}
text = find_entry(input_address, "sc");
if (text)
printf("%s; %s\n", indent, text);
/* default comment */
comment[0] = 0;
if (type == 3) {
/* bit operation */
text = find_entry(((cmd >> 7) & 7) | ((cmd & 0x7f) << 4), "bt");
if (text)
sprintf(comment, "%s", text);
}
if (cmd == 0x1683) sprintf(comment, "switch to page 1");
if (cmd == 0x1283) sprintf(comment, "switch to page 0");
if ((cmd & 0xf000) == 0x2000) {
/* cmd is CALL or GOTO */
text = find_entry(cmd & 0x7ff, "hd");
if (text)
sprintf(comment, "%s", text);
} else if ((cmd & 0xfc00) == 0x3400) {
/* cmd is RETLW */
if ((cmd & 0xff) >= 32 && (cmd & 0xff) < 127)
sprintf(comment, "'%c'", cmd & 0xff);
}
text = find_entry(input_address, "cc");
if (text && *text)
sprintf(comment, "%s", text);
if (for_assembler && expected_address != input_address)
printf("%sORG 0x%04x\n", indent, input_address);
references = ref_count[input_address & 0x7ff];
if (for_assembler) {
if (references)
printf("L%c%03X ", 'A' - 1 + references,
input_address & 0x7ff);
else
printf("%s", indent);
} else
printf("%04x%c %04x ", input_address,
references ? 'A' - 1 + references : ' ', cmd);
printf("%s", line);
if (*comment)
printf("%*s; %s", 20-strlen(line), "", comment);
putchar('\n');
expected_address = input_address + 1;
count++;
}
sum = (sum + count) & 0xff;
if (for_assembler)
printf("%sEND\n", indent);
putchar('\n');

if (checksum != -1 && sum != checksum)
fprintf(stderr, "Warning: Checksum in control file (0x%04lx) is not "
"equal to\n checksum of '%s' which is 0x%04x.\n",
checksum, fnin, sum);

return 0;
}

Отговор