📄 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 + -