⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 picddxhi-tech.c

📁 利用HI-TECH_PICC生成的*.lst文件在Proteus_里调试PIC单片机的.ddx翻译程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
  说明:
    用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 + -