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

📄 emitter.c

📁 MCS51系列单片机的汇编器
💻 C
字号:
/* ---------------------------------------------------------------------- * FILE: emitter.c * PACKAGE: as31 - 8031/8051 Assembler. * * DESCRIPTION: *	This file contains the code to generate various *	object code formats. Provisions exist to *	support many types of output formats within the *	same executable. * * REVISION HISTORY: *	Jan. 19, 1990 - Created. (Ken Stauffer) *	Jan. 29, 1990 - Added S-records (Theo Deraadt) * * * AUTHOR: *	All code in this file written by Ken Stauffer (University of Calgary). *	January, 1990. */#include <stdio.h>#include <stdlib.h>#include "as31.h"/* ---------------------------------------------------------------------- * DECLARE your own open(), close(), addr(), and byte() routines here. * */static int open_tdr(const char *file, const char *ftype, const char *arg);static void close_tdr(void);static void addr_tdr(unsigned long a);static void byte_tdr(unsigned char b);static int open_byte(const char *file, const char *ftype, const char *arg);static void close_byte(void);static void addr_byte(unsigned long a);static void byte_byte(unsigned char b);static int open_od(const char *file, const char *ftype, const char *arg);static void close_od(void);static void addr_od(unsigned long a);static void byte_od(unsigned char b);static int open_srec(const char *file, const char *ftype, const char *arg);static void close_srec(void);static void addr_srec(unsigned long a);static void byte_srec(unsigned char b);static int open_hex(const char *file, const char *ftype, const char *arg);static void close_hex(void);static void addr_hex(unsigned long a);static void byte_hex(unsigned char b);static int open_bin(const char *file, const char *ftype, const char *arg);static void close_bin(void);static void addr_bin(unsigned long a);static void byte_bin(unsigned char b);/* ---------------------------------------------------------------------- * ADD an entry to this table to register your * output format routines. Give your object format * a name to be specified with the -F option. * */static int format;static struct {	char *name;	char *extension;	char *description;	int (*e_open)(const char *file, const char *ftype, const char *arg);	void (*e_close)(void);	void (*e_addr)(unsigned long a);	void (*e_byte)(unsigned char b);} formtab[] = {	{ "hex",   "hex",  "Intel-Hex (.hex)",  open_hex,  close_hex,  addr_hex,  byte_hex },	{ "bin",   "bin",  "Binary (.bin)",  open_bin,  close_bin,  addr_bin,  byte_bin },	{ "tdr",   "tdr",  "TDR Format (.tdr)", open_tdr,  close_tdr,  addr_tdr,  byte_tdr },	{ "byte",  "byte", "BYTE list (.byte)",  open_byte, close_byte, addr_byte, byte_byte },	{ "od",    "od",   "Octal Dump (.od)", open_od,   close_od,   addr_od,   byte_od },	{ "srec2", "srec", "S Record, 16 bit Address (.srec)", open_srec, close_srec, addr_srec, byte_srec },	{ "srec3", "srec", "S Record, 24 bit Address (.srec)", open_srec, close_srec, addr_srec, byte_srec },	{ "srec4", "srec", "S Record, 32 bit Address (.srec)", open_srec, close_srec, addr_srec, byte_srec }};#define FORMTABSIZE	(sizeof(formtab)/sizeof(formtab[0]))void emitusage(void){	int i;	fprintf(stderr, "\tfmt is one of:");	for(i=0; i<FORMTABSIZE; ) {		fprintf(stderr, "%s", formtab[i].name);		if( ++i < FORMTABSIZE)			fprintf(stderr, ", ");	}	fprintf(stderr, ".\n");}const char *emit_extension(const char *ftype){	int i;	if (ftype) {		for(i=0; i<FORMTABSIZE; i++ ) {			if (!strcmp(formtab[i].name, ftype))				return formtab[i].extension;		}	}	return formtab[0].extension;}const char *emit_desc_lookup(int num){	if (num >= 0 && num < FORMTABSIZE)		return formtab[num].description;	return NULL;}const char *emit_desc_to_name_lookup(const char *desc){	int i;	if (desc) {		for(i=0; i<FORMTABSIZE; i++ ) {			if (!strcmp(formtab[i].description, desc))				return formtab[i].name;		}	}	return NULL;}int emitopen(const char *file, const char *ftype, const char *arg){	int i;	if( ftype ) {		for(i=0; i<FORMTABSIZE; i++ ) {			if( !strcmp(formtab[i].name,ftype) ) {				format = i;				return (*formtab[format].e_open)					(file,ftype,arg);			}		}		mesg_f("no format \"%s\", using \"%s\"\n",			ftype, formtab[0].name);	}	/*	 * 0th entry is the default format type	 */	format = 0;	return (*formtab[format].e_open)(file, ftype, arg);}void emitclose(void){	(*formtab[format].e_close)();}void emitaddr(unsigned long a){	(*formtab[format].e_addr)(a);}void emitbyte(int b){	(*formtab[format].e_byte)(b);}/* ---------------------------------------------------------------------- * Individual file format routines appear here: *	Each file format must define the following routines: *		open()	- Called ONCE before any of the others. *			It is passed with a filename and a format *			specific argument. * *		close() - Called ONCE when no more emit_byte() *			function calls will be made. * *		addr() - Called when ever a new address has been set *			in the assembler (ie. .org, .skip). *			This routine is also called once when the *			location counter is set to 0 at the very start of *			assembling. *  *		byte() - Called with each byte to be outputed. * */static unsigned long addr;static FILE *fout=NULL;static long int offset;static int newaddr;static int pos=-666;static unsigned char bytes[16];/*----------------------------------------------------------------------- * "hex" format.  Intel HEX format expected by many EPROM programmers */void hexdump(void)     /* dumps one line into file */{	int i, sum;	if (fout == NULL) return;	fprintf(fout,":%02X%04lX00", pos, addr & 0xFFFF);	sum = pos + ((addr>>8)&0xff) + (addr&0xff) ;	for (i=0; i < pos; i++) {		fprintf(fout,"%02X", bytes[i] & 0xFF );		sum += bytes[i]&0xff;	}	fprintf(fout, "%02X\n", (-sum)&0xff);	addr += pos;	pos = 0;}static int open_hex(const char *file, const char *ftype, const char *arg){	if (file == NULL) fout = stdout;	else fout = fopen(file, "w");	if( fout == NULL ) {		mesg_f("Cannot open %s for writing.\n", file);		return -1;	}	pos = 0;	return 0;}static void close_hex(void){	if (fout == NULL) return;	if ( pos > 0 ) hexdump();	fprintf(fout, ":00000001FF\n");  /* end of file marker */	fclose(fout);}static void addr_hex(unsigned long a){	if ( pos > 0 ) hexdump();	addr = a;}static void byte_hex(unsigned char b){	bytes[pos] = b;	pos += 1;	if ( pos == 16) hexdump();}/*----------------------------------------------------------------------- * "bin" format.  Raw binary data */static int open_bin(const char *file, const char *ftype, const char *arg){	if (file == NULL) fout = stdout;	else fout = fopen(file, "w");	if( fout == NULL ) {		mesg_f("Cannot open %s for writing.\n", file);		return -1;	}	addr = 0;	return 0;}static void close_bin(void){	if (fout == NULL) return;	fclose(fout);}static void addr_bin(unsigned long a){	long i;	if (fout == NULL) return;	if (a > addr) {		for (i=0; i < a - addr; i++) {			fprintf(fout, "%c", 0);		}		addr = a;		return;	}	if (a < addr) {		error("address changed to %lX, from %lX", a, addr);		error("binary output format can't write backwards");		addr = a;		return;	}}static void byte_bin(unsigned char b){	if (fout == NULL) return;	fprintf(fout, "%c", b & 0xFF);	addr++;}/* ---------------------------------------------------------------------- * "tdr" format. For tdr's 68008 system. Generates a * script file readable by a debugger. *      [addr] : [byte] [byte] .. * * arg: This is a number in decimal which specifies *      the offset, -Ftdr -A0000 * *      These options specifies the tdr format, with an argument *      of 0. This becomes the offset used in generating the *      script file. The default if no A is present is 0x10000. *  */static int open_tdr(const char *file, const char *ftype, const char *arg){	if (file == NULL) fout = stdout;	else fout = fopen(file,"w");	if( fout == NULL ) {		mesg_f("Cannot open %s for writing.\n",file);		return -1;	}	if (arg) {		offset = atoi(arg);	} else {		offset = 0x10000;	}	return 0;}static void close_tdr(void){	if (fout == NULL) return;	if( pos != 15 ) fprintf(fout,"\n");	fclose(fout);}static void addr_tdr(unsigned long a){	addr = a;	newaddr = 1;}static void byte_tdr(unsigned char b){	if (fout == NULL) return;	if( newaddr ) {		if( pos != -666 ) fprintf(fout,"\n");		newaddr = 0;		pos = 15;		fprintf(fout,"%06lx: ", (addr + offset) & 0xFFFFFF);	} else if( pos == 15 ) {		fprintf(fout,"%06lx: ", (addr + offset) & 0xFFFFFF);	}	fprintf(fout,"%02x ", b & 0xFF );	if( pos-- == 0 ) {		fprintf(fout, "\n");		pos = 15;	}	addr += 1;}/* ---------------------------------------------------------------------- * "byte" format. *	Like "tdr" but each byte is on a line by itself. *	This is nice for debugging. No -A is used. */static int open_byte(const char *file, const char *ftype, const char *arg){	if (file == NULL) fout = stdout;	else fout = fopen(file,"w");	if( fout == NULL ) {		mesg_f("Cannot open %s for writing.\n", file);		return -1;	}	return 0;}static void close_byte(void){	if (fout == NULL) return;	fclose(fout);}static void addr_byte(unsigned long a){	addr = a;}static void byte_byte(unsigned char b){	if (fout == NULL) return;	fprintf(fout,"%04lX: %02X\n", addr & 0xFFFF, b & 0xFF );	addr += 1;}/* ---------------------------------------------------------------------- * "od", this format shows 16 bytes per line, with address. *	It also includes ascii on one side. * * The format is similar to the od(1) program under Unix. * */static int od_pos;static unsigned char od_buf[16];static unsigned long saveaddr;void dumpline(unsigned long a, unsigned char *b, int len){	int i;	if (fout == NULL) return;	if(len <= 0 ) return;	fprintf(fout,"%04lx: ", a & 0xFFFF);	for(i=0; i<8; i++ ) {		if( i <= len )			fprintf(fout,"%02x ",b[i]);		else			fprintf(fout,"   ");	}	fprintf(fout,"- ");	for(i=8; i<16; i++ ) {		if( i <= len )			fprintf(fout,"%02x ",b[i]);		else			fprintf(fout,"   ");	}	fprintf(fout,"   ");	for(i=0; i<16; i++ ) {		if( i <= len )			fprintf(fout,"%c",				(b[i]>=' ' && b[i]<='~') ? b[i] : '.' );		else			break;	}	fprintf(fout,"\n");}static int open_od(const char *file, const char *ftype, const char *arg){	if (file == NULL) fout = stdout;	else fout = fopen(file,"w");	if( fout == NULL ) {		mesg_f("Cannot open %s for writing.\n",file);		return -1;	}	return 0;}static void close_od(void){	if (fout == NULL) return;	dumpline(saveaddr, od_buf, od_pos-1);	fclose(fout);}static void addr_od(unsigned long a){	newaddr = 1;	addr = a;}static void byte_od(unsigned char b){	if( newaddr ) {		dumpline(saveaddr, od_buf, od_pos-1);		od_pos = 0;		newaddr = 0;		saveaddr = addr;	} else if( od_pos == 16 ) {		dumpline(saveaddr, od_buf, od_pos-1);		od_pos = 0;		saveaddr = addr;	}	od_buf[od_pos++] = b & 0x00ff;	addr += 1;}/* ---------------------------------------------------------------------- * srecord format. This is called with "-Fsrec2", "-Fsrec3", or * "-Fsrec4"... * * arg: This is a number in decimal which specifies *	the offset, -Fsrec3 -A0000 * *	These options specifies the tdr format, with an argument *	of 0. This becomes the offset used in generating the *	script file. The default if no A is present is 0x0000. *  */#define SREC_BYTESPERLINE 32static int srec_format;static int srec_check, srec_index;static char srec_buf[SREC_BYTESPERLINE];static long srec_address;void srec_finishline(void){	int i;	if (fout == NULL) return;	srec_check = srec_index + (srec_address & 0xff) + ((srec_address>>8) & 0xff) + 4;	switch(srec_format) {	case 2:		fprintf(fout, "S1%02X%04lX", srec_index + 4,			srec_address & 0xFFFF);		break;	case 3:		fprintf(fout, "S2%02X%06lX", srec_index + 6,			srec_address & 0xFFFFFF);		srec_check += ((srec_address>>16) & 0xff) + 2;		break;	case 4:		fprintf(fout, "S3%02X%08lX", srec_index + 8, srec_address);		srec_check += ((srec_address>>16) & 0xff) +			((srec_address>>24) & 0xff) + 4;		break;	}	for(i=0; i<srec_index; i++) {		fprintf(fout, "%02X", srec_buf[i] & 0xff);		srec_check += srec_buf[i];	}	fprintf(fout, "%02X\n", (~srec_check & 0xff) );	srec_index = 0;}static int open_srec(const char *file, const char *ftype, const char *arg){	if (ftype == NULL) {		mesg_f("No S Record Format\n");		return -1;	}	if (sscanf(ftype, "srec%d", &srec_format) != 1) {		mesg_f("Illegal S Record format \"%s\", must be \"srec2\", \"srec3\", or \"srec4\"\n", ftype);		return -1;	}	if (srec_format < 2 || srec_format > 4) {		mesg_f("Illegal S Record format %d %s (must be 2, 3, or 4)\n",			srec_format, ftype);		return -1;	}	if (file == NULL) fout = stdout;	else fout = fopen(file,"w");	if( fout == NULL ) {		mesg_f("Cannot open %s for writing.\n",file);		return -1;	}	if(arg)	offset = atoi(arg);	else	offset = 0;	fprintf(fout, "S0030000%02X\n", (~3 & 0xff) );	return 0;}static void close_srec(void){	if (fout == NULL) return;	if(srec_index)		srec_finishline();	switch(srec_format) {	case 2:		fprintf(fout, "S9030000%02X\n", ~3 & 0xff);		break;	case 3:		fprintf(fout, "S804000000%02X\n", ~4 & 0xff);		break;	case 4:		fprintf(fout, "S70500000000%02X\n", ~5 & 0xff);		break;	}	fclose(fout);}static void addr_srec(unsigned long a){	if(srec_index>0)		srec_finishline();	srec_address = a + offset;}static void byte_srec(unsigned char b){	srec_buf[srec_index++] = b;	if(srec_index==SREC_BYTESPERLINE) {		srec_finishline();		srec_address += SREC_BYTESPERLINE;	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -