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

📄 common.c

📁 這是一個8051的模擬器 以java寫成
💻 C
📖 第 1 页 / 共 3 页
字号:

/*
 * Disassembler common routines
 * Copyright (C) 1995-2005 by Jeffery L. Post
 * theposts <AT> pacbell <DOT> net
 *
 * common.c - Support routines
 *
 * Version 3.3.6 - 01/18/05
 *
 *	This program is free software; you can redistribute it and/or modify
 *	it under the terms of the GNU General Public License as published by
 *	the Free Software Foundation; either version 2 of the License, or
 *	(at your option) any later version.
 *
 *	This program is distributed in the hope that it will be useful,
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *	GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 */

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

#include	"d52.h"
#include	"common.h"

// Global variables

char	src[FN_LEN], dst[FN_LEN];	// file name buffers
char	baseFileName[FN_LEN];		// source file name without extension
char	ctl[FN_LEN];					// control file name
char	linebuffer[MAX_LINE];		// input line buffer
FILE	*fp;								// dos file struct
int	hexflag;							// append hex flag
int	fileflag;						// file type flag
int	upperflag;						// upper case output flag
int	kcnt;								// output char counter
int	pc;								// current program counter
int	himark;							// highest data adrs
int	offset;							// program counter offset
byte	*pgmmem;							// program data pointer
int	*pgmflags;						// pointer to program flags

#ifdef	EXTENDED_MEM
byte	*epgmmem[EXT_PGM_SEGS];		// extended program memory pointers
int	*epgmflags[EXT_PGM_SEGS];	// extended program flags pointers
#endif

char	string[ASCLIMIT];				// ascii data for defb
int	asc_cnt;							// count for string data
byte	byte_data[BYTELIMIT];		// binary data for defb
int	byte_cnt;						// count for binary data
int	word_data[WORDLIMIT];		// binary data for defw
int	word_cnt;						// count for word data
byte	dump;								// dump just done flag
byte	ascii_flag;						// use ascii string flag
char	defbstr[8];						// string for defined bytes
char	defwstr[8];						// string for defined words
char	ascistr[8];						// string for defined ascii
char	orgstr[] = ".or";				// org pseudo-op string
char	equstr[] = ".eq";				// equ pseudo-op string

struct sym	*sym_tab;					// symbol table pointer
struct sym	*lab_tab;					// label table pointer
struct sym	*name_tab;					// operand names pointer
struct sym	*sym_tab_last;				// last symbol table pointer
struct sym	*lab_tab_last;				// lastlabel table pointer
struct sym	*name_tab_last;			// last name table pointer
int			symbol_count;				// number of symbols
int			label_count;				// number of labels
int			name_count;					// number of operand names

SYM_PTR		*sym_val_index;			// array of pointers
SYM_PTR		*lab_val_index;			//  for binary search
SYM_PTR		*name_val_index;
struct sym	*tail_ptr, *head_ptr;	// sort pointers

struct comment	*comment_list;			// header comment list
struct comment	*icomment_list;		// inline comment list
struct comment	*patch_list;			// patch list

int			newline;						// just output newline flag
struct tm	*date_time;					// disassembly time

//
// Code
//

bool init_memory(void)
{
	int	count;

#ifdef EXTENDED_MEM
	for (count=0; count <EXT_PGM_SEGS; count++)
	{
		epgmmem[count] = NULL;
		epgmflags[count] = NULL;
	}
#endif

	if ((pgmmem = (byte *) malloc(PMEMSIZE)) == NULL)
	{
		printf("INTERNAL ERROR! - Can't allocate program space!\n");
		return FALSE;
	}

	if ((pgmflags = (int *) malloc(PMEMSIZE * sizeof(int))) == NULL)
	{
		printf("INTERNAL ERROR! - Can't allocate flag space!\n");
		return FALSE;
	}

	printf("Initializing program spaces...");

	for (count=WORD_MASK; count; count--)	// fill code space with
	{
		pgmmem[count] = NO_DATA;				// invalidate data
		pgmflags[count] = PF_INIT;				// invalidate flags
	}

	pgmmem[0] = NO_DATA;							// include first location
	pgmflags[0] = PF_INIT;
	return TRUE;
}

#ifdef	EXTENDED_MEM

// Get extended program or flag memory.
// Width = 1 for program memory or 2 for flag memory.

byte *get_extended_mem(int width)
{
	byte	*ptr;

	ptr = (byte *) malloc(PMEMSIZE * width);

	if (!ptr)
		printf("\nCan't allocate extended memory!\n");

	return ptr;
}
#endif

char * makeupper(char *str)
{
	char	*ret = str;

	while (*str)
	{
		*str = toupper(*str);
		str++;
	}

	return ret;
}

// Parse file name. Put file name without extension in
// baseFileName, and return:
//		EITHERFILE		if no extension provided
//		BINFILE			if extension is '.bin'
//		HEXFILE			if extension is '.hex'
//		CPMFILE			if extension is '.com'

int parseFileName(char *str, char *ext)
{
	int	i, type;
	char	*cptr;

	type = EITHERFILE;
	strcpy(baseFileName, str);
	strcpy(src, str);
	cptr = strrchr(str, '.');

	if (!cptr)						// if '.' not found, then use eitherfile
	{
		strcat(src, ".hex");
	}
	else
	{
		i = (int) (cptr - str);	// get offset of '.' character

		if (!strncasecmp(cptr, ".hex", 4))
		{
			baseFileName[i] = '\0';
			type =  HEXFILE;
		}
		else if (!strncasecmp(cptr, ".bin", 4))
		{
			baseFileName[i] = '\0';
			type = BINFILE;
		}
		else if (!strncasecmp(cptr, ".com", 4) && !strcmp(ext, ".z80"))
		{
			baseFileName[i] = '\0';
			offset = 0x100;
			type = CPMFILE;
		}
		else
			strcat(src, ".hex");
	}

	strcpy(dst, baseFileName);
	strcat(dst, ext);
	strcpy(ctl, baseFileName);
	strcat(ctl, ".ctl");

	return type;
}

//
// Read bin, hex, or com file into program memory.
//

int readfile(char *filename)
{
	int	i, j, rectype, page, line, readsize;

// open source file

	switch (fileflag)
	{
		case EITHERFILE:				// if no type specified...
			fp = fopen(src, "r");	// search for hex file first

			if (fp == NULL)			// if not found, search for bin file
			{
				fileflag = BINFILE;
				strcpy(src, baseFileName);
				strcat(src, ".bin");
				fp = fopen(src, "rb");

				if (fp == NULL)
				{
					printf("\n* Can't open either '%s.hex' nor '%s.bin' *\n\n",
							baseFileName, baseFileName);
					exit(FILE_ERROR);
				}
				else
					fileflag = BINFILE;
			}
			break;

		case HEXFILE:					// force hex file
			fp = fopen(src, "r");
			break;

		case BINFILE:					// force bin file
		case CPMFILE:					// CP/M .com file
			fp = fopen(src, "rb");
			break;
	}

	if (fp == NULL)					// if file not found...
	{
		printf("\n* Can't open file '%s' *\n\n", src);
		exit(FILE_ERROR);
	}

// read input file and set up data array

	himark = 0;
	line = 0;
	pc = offset;
	printf("\nreading %s\n", src);

	if (fileflag == BINFILE || fileflag == CPMFILE)	// if binary file...
	{
		while (!feof(fp))								// until end of file...
		{
			if (pc >= PMEMSIZE)						// exceeded 64K limit
			{
				printf("\nInput file too large!\n\n");
				break;
			}

			if ((pc + MAX_LINE) >= PMEMSIZE)		// if next read would exceed limit
				readsize = PMEMSIZE - pc;			// reduce read byte count
			else
				readsize = MAX_LINE;

			i = fread(linebuffer, 1, readsize, fp);	// read a block of data

			for (j=0; j<i; j++)
			{
				pgmmem[pc] = linebuffer[j];		// copy to program space
				pgmflags[pc] = PF_DATA;
				pc++;

				if ((pc & 0xff) == 0)
					printf("\r%04x", pc);			// show progress
			}

			if (pc & WORD_MASK)
				himark = pc;
			else
				himark = WORD_MASK;					// flag highest location
		}
	}

	else													// else hex file...
	{
		page = 0;
		rectype = 0;

		while (!feof(fp))								// until end of file...
		{
			*linebuffer = '\0';						// clear previous line
			fgets(linebuffer, MAX_LINE - 1, fp);// read one line
			line++;

			if (sscanf(linebuffer, "%*c%2x%4x%2x", &i, &pc, &rectype) != EOF)
			{												// get count and address
				pc += offset;							// add offset to address
				pc += page;								// add segment to address

				if ((pc + i) >= PMEMSIZE)
				{
					printf("\nInput file too large!\n\n");
//					exit(FILE_ERROR);
					break;
				}

				if (rectype == 1)
					break;								// done if end of hex record

				if (rectype == 2)						// extended segment address record
				{
					sscanf((char *) &linebuffer[9], "%4x", &page);
					page <<= 4;
				}
				else if (rectype == 0)				// data record
				{
					if (i > 64)							// oops! line too long
					{
						printf("invalid count (%d) in line %d:\n", i, line);
						printf("%s", linebuffer);
						exit(FILE_ERROR);
					}

					for (j=0; j<i ; j++)				// now move data to program area
					{
						getcode(linebuffer + 9 + j * 2, &pgmmem[pc]);	// code to program space
						pgmflags[pc] = PF_DATA;		// flag valid data
						pc++;

						if ((pc & 0xff) == 0)		// show progress
							printf("\r%04x", pc);
					}

					if (pc > himark)
						himark = pc;
				}
			}
		}
	}

	fclose(fp);										// done reading input file
	printf("\rHighest location = ");			// show last location

	if (himark == WORD_MASK)
		printf("%04x\n", himark);
	else
		printf("%04x\n", himark - 1);

	return 0;
}

//
//	Put ascii hex data into binary array
//

void getcode(char *from, byte *loc)
{
	byte	c, i;

	c = *from++ - 0x30;
	c = (c > 10) ? c - 7 : c;
	i = c << 4;
	c = *from++ - 0x30;
	c = (c > 10) ? c - 7 : c;
	*loc = i | c;
}

//
// Get hexadecimal number from line in control file.
// Return updated character pointer.
//

char *get_adrs(char *text, int *val)
{
	int	result, start;
	char	c;

	result = start = 0;
	c = toupper(*text);

	while (c)
	{
		if (c == ';')			// beginning of comment, ignore all else
			break;

		if (c == '\n')			// necessary because isspace() includes \n
			break;

		if (isspace(c))		// skip leading whitespace
		{
			text++;
			if (start)			// if result already begun...
				break;
		}
		else if (!isxdigit(c))		// done if not hexadecimal character
			break;
		else
		{
			start = 1;			// flag beginning of result conversion
			c = (c > '9') ? c - 0x37 : c - 0x30;
			result <<= 4;
			result |= ((int) c & 0xf);
			text++;
		}

		c = toupper(*text);
	}

	*val = result;				// pass number back to caller
	return(text);				// and return updated text pointer
}

void error(char *str1, char *str2)			// fatal error trap
{
	printf("\n%s%s", str1, str2);
	exit(FILE_ERROR);
}

//			Sort label or symbol table
//	First sort by name so that we can check for duplicates,
//	then sort by value, check for duplicates, and set up
//	pointer array for binary search.
//

struct sym *sort(struct sym *list, SYM_PTR *array, int count)
{
	int	i;
	struct sym	*sptr, *temp;

	sptr = sort_by_name(list);

	if (list == name_tab)
		chk_dup_op_name(sptr, count);
	else
		chk_dup_name(sptr, count);

	sptr = sort_by_value(sptr);
	chk_dup_value(sptr, count);
	temp = sptr;

	for (i=0; i<count; i++)		// set up array of pointers sorted by value
	{
		array[i] = temp;
		temp = temp->next;
	}

	return(sptr);
}

//
// In-place non-recursive merge sort using label text as key
//

struct sym *sort_by_name(struct sym *list)
{
	int			i, n;
	struct sym	*a, *b, *todo, *t;

	head_ptr = (struct sym *) malloc(sizeof(struct sym));
	head_ptr->next = list;
	a = tail_ptr;

	for (n=1; a != head_ptr->next; n = n + n)
	{
		todo = head_ptr->next;
		list = head_ptr;

		while (todo != tail_ptr)
		{
			t = todo;
			a = t;

			for (i=1; i<n; i++)
				t = t->next;

			b = t->next;
			t->next = tail_ptr;
			t = b;

			for (i=1; i<n; i++)
				t = t->next;

			todo = t->next;
			t->next = tail_ptr;
			list->next = merge_by_name(a, b);

			for (i=1; i<=n+n; i++)
				list = list->next;
		}
	}

	return(head_ptr->next);
}

//
// In-place non-recursive merge sort using value as key
//

struct sym *sort_by_value(struct sym *list)
{
	int			i, n;
	struct sym	*a, *b, *todo, *t;

	head_ptr = (struct sym *) malloc(sizeof(struct sym));
	head_ptr->next = list;
	a = tail_ptr;

	for (n=1; a != head_ptr->next; n = n + n)
	{
		todo = head_ptr->next;
		list = head_ptr;

		while (todo != tail_ptr)
		{
			t = todo;
			a = t;

			for (i=1; i<n; i++)
				t = t->next;

			b = t->next;
			t->next = tail_ptr;
			t = b;

			for (i=1; i<n; i++)
				t = t->next;

			todo = t->next;
			t->next = tail_ptr;
			list->next = merge_by_value(a, b);

			for (i=1; i<=n+n; i++)
				list = list->next;
		}
	}

	return(head_ptr->next);
}

//
// Merge sub-lists by text field
//

struct sym *merge_by_name(struct sym *a, struct sym *b)
{
	int			i;
	struct sym	*c;

	c = tail_ptr;

	do
	{
		i = strcasecmp(a->name, b->name);

		if (i <= 0)
		{
			c->next = a;
			c = a;
			a = a->next;
		}
		else
		{
			c->next = b;
			c = b;
			b = b->next;

⌨️ 快捷键说明

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