?? picddxhi-tech.c
字號:
/*
說明:
用HI-TECH 的 PIC C 編譯器生成的目標文件可以打開編譯選項Generate assembler listings,使得輸出文件包括了*.HEX 文件和*.LST 文件. 其中*.HEX 文件用來在Proteus 里當作機器碼執行. 而調試時需要*.LST 文件. 可是PICC 生成的*.LST 文件不能被Proteus 識別. 所以需要用PICddxHI-TECH.exe 將*.LST 翻譯成Proteus 能識別的*.SDI 文件.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
//全局常量
//#define _PUTINFO
//數據結構
typedef struct tagSYMBOITEM{ //符號表項結構
char name[128];
long address;
} SYMBOITEM;
typedef struct tagASSIGNEDITEM{ //符號置換項
char symbo[128];
char variable[128];
} ASSIGNEDITEM;
typedef struct tagPARRAY PARRAY;
//全局變量
FILE *lstfile; //Input stream of file.
FILE *sdifile; //Output stream of file.
PARRAY gSymboTable; //符號表
PARRAY gAssignedTable; //符號置換表
HANDLE Heap1;
//初始化指針數組
#define SYM_GRAIN 32 //指針數組分配粒度
typedef struct tagPARRAY{ //指針數組結構
void **p; //指針數組首指針
long max; //指針數組元素容量
long cnt; //指針數組元素數
} PARRAY;
int PArrayInit(PARRAY *pPArray)
{
pPArray->max =SYM_GRAIN;
pPArray->p =HeapAlloc(Heap1,0,sizeof(void *)*pPArray->max);
if(!pPArray->p){
fprintf(stderr, "Can't alloc memory.");
return 0;
}
pPArray->cnt =0;
return 1;
}
//向指針數組增加一個元素
int PArrayAdd(PARRAY *pPArray, void *p)
{
if(pPArray->cnt >=pPArray->max){
//若需要更多元素則修改指針數組空間
pPArray->max +=SYM_GRAIN;
pPArray->p =
HeapReAlloc(Heap1, 0, pPArray->p, sizeof(void *)*pPArray->max);
if(!pPArray->p) return 0;
}
pPArray->p[pPArray->cnt] =p;
pPArray->cnt++;
return 1;
}
//回收元素空間
//僅對指向元素執行HeapFree操作,若元素數據域包括其他動態分配空間需另行處理
int PArrayClear(PARRAY *pPArray)
{
unsigned long i;
for(i =0; i <pPArray->cnt; i++){
HeapFree(Heap1, 0, pPArray->p[i]);
}
pPArray->cnt =0;
pPArray->max =SYM_GRAIN;
pPArray->p =
HeapReAlloc(Heap1, 0, pPArray->p, sizeof(void *)*pPArray->max);
return 1;
}
void Usage(char *programName)
{
fprintf(stderr,"\
PIC Debug Data Extractin for HI-TECH PIC C compiler.\n\
\n\
Useage: PICddxHT lst1 lst2 lst3 ... \n\
"); /* Modify here to add your usage message when the program is
* called without arguments */
}
/* returns the index of the first argument that is not an option; i.e.
does not start with a dash or a slash
*/
int HandleOptions(int argc,char *argv[])
{
int i,firstnonoption=0;
for (i=1; i< argc;i++) {
if (argv[i][0] == '/' || argv[i][0] == '-') {
switch (argv[i][1]) {
/* An argument -? means help is requested */
case '?':
Usage(argv[0]);
break;
case 'h':
case 'H':
if (!stricmp(argv[i]+1,"help")) {
Usage(argv[0]);
break;
}
/* If the option -h means anything else
* in your application add code here
* Note: this falls through to the default
* to print an "unknow option" message
*/
/* add your option switches here */
default:
fprintf(stderr,"unknown option %s\n",argv[i]);
break;
}
}
else {
firstnonoption = i;
break;
}
}
return firstnonoption;
}
//從文本文件里得到一行數據
/*
buffer 保存從文件里讀到的數據,不小于1024字節
inflie 文件流指針
返回讀到的字符數,若沒讀到數據則返回0
*/
int fgetline(FILE *infile, char *buffer)
{
char *r;
r = fgets(buffer, 1024, infile);
if(r == NULL){
buffer[0] =0; //清除緩沖區串
return 0; //文件結束返回0
}
else return strlen(buffer);
}
//判斷字符串是不是一個16進制數(大寫)。返回1表示是16進制串,0則不是。
int IsHex(char *p)
{
int i;
for(i =0; i <strlen(p); i++){
if(p[i] !=0x20) break;
}
if(i >=strlen(p)) return 0;
for(; i <strlen(p); i++){
if(!((p[i] >='0' && p[i] <='9')||
(p[i] >='A' && p[i] <='F'))) return 0;
}
return 1;
}
//判斷字符串是不是一個10進制數。返回1表示是10進制串,0則不是。
int IsDec(char *p)
{
int i;
for(i =0; i <strlen(p); i++){
if(p[i] !=0x20) break;
}
if(i >=strlen(p)) return 0;
for(; i <strlen(p); i++){
if(!(p[i] >='0' && p[i] <='9')) return 0;
}
return 1;
}
/****分析一行文本****/
/*
返回值代表此行文本格式,可能得值如下:
0 無效
1 指令,文本包括:行號,地址,機器碼,指令
2 跳轉標號,文本包括:行號,地址,標識符
3 陳述,文本包括:行號,陳述
4 接上一行,文本包括:起始空格,文本
5 說明,文本包括:無起始空格的說明
6 equ定義,文本包括:行號,地址,equ定義
7 FNSIZE定義,文本包括:行號,FNSIZE定義
輸入參數:
str 被分析的文本行
輸出參數:
material 分析結果。
這是一個MATERIAL數據結構,其中包括了:
行號,地址,機器碼,指令(或陳述及說明)
說明:此函數用if語句實現二叉樹選擇
*/
typedef struct tagMATERIAL{
long LineNumber; //行號
long Address; //地址
char Code[64]; //機器碼
char Text[256]; //指令(或陳述及說明)
} MATERIAL;
long AnalyseLine(char *str, MATERIAL *material)
{
const char scmp1[] ="FNSIZE";
char *p;
char s1[1024];
int a;
a=strlen(str);
if(strlen(str)==0) return 0;
strcpy(s1, str);
p = strtok(s1, " \t\n");
if(!p) return 0;
if(IsDec(p)){ //檢查有無行號(首段字符是不是數字)
material->LineNumber =atol(p);
p = strtok(NULL, " \t\n");
if(!p) return 0;
if(!IsHex(p)){ //檢查是不是陳述(無地址)
p[strlen(p)] ='\t';
strcpy(material->Text, p);
if(!strncmp(material->Text, scmp1, strlen(scmp1))) return 7; //是否是FNSIZE陳述
else return 3;
}else{
material->Address =strtol(p, NULL, 16);
if(material->Address ==0){ //檢查是不是equ定義
p = strtok(NULL, " \t\n");
if(!p) return 0;
p[strlen(p)] ='\t';
strcpy(material->Text, p);
return 6;
}
p = strtok(NULL, " \t\n");
if(!p) return 0;
if(IsHex(p)){ //檢查是不是指令
strcpy(material->Code, p);
strcat(material->Code, " ");
while(1){ //檢查接著有沒有多個機器碼
p = strtok(NULL, " \t\n");
if(!p) return 0;
if(!IsHex(p)) break;
strcat(material->Code, p);
strcat(material->Code, " ");
}
p[strlen(p)] ='\t';
strcpy(material->Text, " ");
strcat(material->Text, p);
return 1;
}else{ //跳轉標號
p[strlen(p)] =' ';
strcpy(material->Text, p);
return 2;
}
}
}else{
if(p -s1 >=33 && p[0]!=' '){ //檢查是不是接上一行
p[strlen(p)] =' ';
strcpy(material->Text, p);
return 4;
}
else{
p[strlen(p)] =' ';
strcpy(material->Text, p);
return 5; //是說明
}
}
}
//獲得.LST文件的起始地址
long fGetFirstAddress(FILE *infile, char *buffer)
{
long n;
MATERIAL material;
while(!feof(infile)){
fgetline(infile, buffer);
n =AnalyseLine(buffer, &material);
if( n ==1) return material.Address;
}
return -1;
}
//獲得.LST文件的符號表
/*
infile 輸入文件流
spSymboTable 符號表指針數組結構指針
返回1表示得到符號表,0表示沒得到符號表
*/
int fGetSymboTable(FILE *infile, PARRAY *SymboTable)
{
const char scmp[] ={"Symbol Table"};
char buf[1024];
int rt;
char *sp;
int i;
SYMBOITEM *p;
int symf; //符號表開始標志
fseek(infile, 0, SEEK_SET);
i =0;
//尋找符號表,符號表以"Symbol Table"開始
while(!feof(infile)){
rt =fgetline(infile, buf);
if(!strnicmp(buf, scmp, strlen(scmp))){
i =1; //置符號表有效標志
break;
}
}
symf =0;
if(i){
i =0; //i的作用改為SymboTable->p[]下標
while(!feof(infile)){
rt =fgetline(infile, buf);
sp =strtok(buf, " \t\n");
if(symf) //避開符號表開始的幾行空白
if(!sp) return 1; //符號表以空白行結束
do{ //行內符號檢查
if(sp){
symf =1; //置符號表開始標志
//增加一個元素
p =HeapAlloc(Heap1,0,sizeof(SYMBOITEM)); //分配保存符號表項的空間
i++;
strcpy(p->name, sp);
sp =strtok(NULL, " \t\n");
p->address =strtol(sp, NULL, 16);
if(!PArrayAdd(SymboTable, p)){
fprintf(stderr, "Can't alloc memory.");
exit(2);
}
}
sp =strtok(NULL, " \t\n");
}while(sp);
}
return 1;
}
return 0;
}
//輸出符號表到顯示設備上
int PutSymboTable(PARRAY *SymboTable)
{
const char sout[] ="%s %04lX\n";
long i;
SYMBOITEM **p;
p =SymboTable->p;
for(i =0; i <SymboTable->cnt; i++){
fprintf(stderr, sout, p[i]->name, p[i]->address);
}
return 0;
}
//輸出置換表到顯示設備上
int PutAssignedTable(PARRAY *Table)
{
const char sout[] ="%s %s\n";
long i;
ASSIGNEDITEM **p;
p =Table->p;
for(i =0; i <Table->cnt; i++){
fprintf(stderr, sout, p[i]->variable, p[i]->symbo);
}
return 0;
}
//分析一個陳述文本
/*返回值表示陳述包括的注釋類型:
0 未知注釋
1 普通注釋
2 line注釋
3 assigned注釋
4 stored注釋
*/
int AnalyseComment(char *str)
{
char *bp;
if(str[0] ==';'){ //判斷是不是一個注釋陳述(以';'開頭)
bp =strstr(str, " assigned to ");
if(bp) return 3;
bp =strstr(str, " stored from ");
if(bp) return 4;
bp =strstr(str, "line\t");
if(bp) return 2;
return 1;
}
return 0;
}
//翻譯一個assigned注釋到ASSIGNEDITEM數據結構
int TranslateAssignedToItem(char *instr, PARRAY *table, ASSIGNEDITEM *item)
{
const char scmp[] =" assigned to ";
char *p, *p1;
char *buf;
long i;
SYMBOITEM *symp;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -