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

📄 dis.c

📁 m68k系列反汇编的C语言源码,供学习编译原理的同学使用。实用!
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *                 Author:  Christopher G. Phillips *              Copyright (C) 1994 All Rights Reserved * *                              NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * The author makes no representations about the suitability of this * software for any purpose.  This software is provided ``as is'' * without express or implied warranty. */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include "dis.h"#define ISASCII(c)	(0x20 <= (c) && (c) <= 0x7e)#ifdef DEBUG#define INITIAL		0x01#define DELETIONS	0x02#define TRY		0x04#define LASTTRY		0x08#define MAKEGOOD	0x10#define OVERLAPS	0x20#define LABELS		0x40int	debug = 0;#endiflong		curoffset;	/* current offset into file */short		flags;		/* flags for current instruction */m68kaddr	required[3];	/* instructions that must be valid for current				   instruction to also be valid */int		pcrelative = 0;	/* used to signal that PC-relative addresses				   referenced by JMP and JSR instructions				   should be stored in ``required'' */extern char	instbuf[];	/* used to store the nibbles of an				   instruction in hexadecimal */extern size_t	leninstbuf;	/* current length of string in instbuf */struct inst	*insts;		/* instruction database */m68kaddr	maxoffset;	/* last offset that may hold an instruction *//* * These macros are used for convenience.  They do the following: * * NREQD(o)	returns the number of instructions instruction ``o'' depends on * JUMP(o)	returns whether instruction ``o'' changes PC unconditionally *		(modulo ``jfile'' instructions) * FETCH(o,s)	returns whether instruction ``o'' is valid and has size ``s'' *		(for ``s'' positive) * DELETE(o)	renders instruction ``o'' invalid * SETLABEL(o)	marks instruction ``o'' as requiring a label in the output */#define NREQD(o)	(insts[o].flags & 3)#define JUMP(o)		(insts[o].flags & (ISBRA | ISRTS | ISJMP | ISJSR))#define FETCH(o,s)	(/* (o) >= 0 && */ (o) <= maxoffset && \			  ((s) == -1 && insts[o].size \			  || insts[o].size == (s)))#define DELETE(o)	do { \				free(insts[o].required); \				insts[o].required = NULL; \				insts[o].size = 0; \				insts[o].flags = 0; \			} while (0);#define SETLABEL(o)	if ((o) >= initialpc && (o) <= initialpc + maxoffset) \				insts[(o) - initialpc].flags |= ISLABELstatic short	longestinstsize;	/* max possible instruction length */static long	gfsize = 0;		/* file size */static m68kaddr	*notinsts = NULL;	/* array of values in ``nfile'' */static size_t	nnotinsts = 0;static m68kaddr	*breaks = NULL;		/* array of values in ``bfile'' */static size_t	nbreaks = 0;#ifndef NOBADstatic m68kaddr	*bad;	/* addresses that cause instructions to be deleted */static m68kaddr	*good;	/* addresses that cause instructions to be accepted			   in the final output */#endif/* * Free dynamically allocated memory * and longjmp back to process the next object file. */static voidjumpfree(void){#ifndef NOBAD	m68kaddr	offset;	for (offset = 0; offset <= maxoffset; offset += (odd ? 1 : WORDSIZE)) {		if (dobad && insts[offset].size == 0)			fprintf(stderr,"%s: Instruction %lx: deleted because of %lx\n",			  sfile, (long)(offset + initialpc), (long)bad[offset]);		if (insts[offset].flags & ISGOOD		  && bad[offset])			fprintf(stderr,"%s: Instruction %lx: assumed good because of %lx, deleted because of %lx\n",			  sfile, (long)(offset + initialpc), (long)good[offset],			  (long)bad[offset]);	}	free(bad);	bad = NULL;	free(good);	good = NULL;#endif	while (gfsize--)		free(insts[gfsize].required);	free(insts);	insts = NULL;	gfsize = 0;	longjmp(jmp, 1);}/* * Search ``p'' for a string of at least ``minlen'' consecutive * printable characters.  Return the index of the start of the string (or -1). */static intfindstring(size_t stored, const unsigned char *p){	int	i;	int	inarow;	for (inarow = i = 0; i < stored; i++, p++)		if (use_isprint && isprint(*p) || !use_isprint && ISASCII(*p)) {			if (++inarow >= minlen)				return i - inarow + 1;		} else			inarow = 0;	return -1;}/* * ``p'' contains the nibbles of a floating-point constant in hexadecimal. * These nibbles are converted into longword values and passed to ``fpoint'' * which formats the floating-point value in ``s'' (in printable form). */static intsfpoint(int type, const unsigned char *p, char *s){	u32bit_t	longwords[3];	size_t		nlongwords;	size_t		i, j;	switch (type) {	case SINGLE:    nlongwords = 1; break;	case DOUBLE:    nlongwords = 2; break;	case EXTENDED: case PACKED:			nlongwords = 3; break;	}	/*	 * Convert string to longs.	 */	for (i = 0; i < nlongwords; i++) {		longwords[i] = 0;		for (j = 0; j < 2 * WORDSIZE; j++)			longwords[i] += (*p++)			  << (CHAR_BIT * (2 * WORDSIZE - 1 - j));	}	return fpoint(longwords, type, s);}/* * Output constants.  Return how many floating-point constants were output. * * todo		number of input bytes to output. * p		nibbles of the constant(s) in hexadecimal. * floattype	floating-point type expected (or 0). * numforce	specifies how many floating-point constants should be output *		regardless of value if ``floattype'' is nonzero, else specifies *		that output must be forced if nonzero. * * Returns the number of bytes output. */static size_tdcflush(size_t todo, const unsigned char *p, int floattype, int numforce){	char		format[BUFSIZ];	int		i;	m68kaddr	value;	size_t		n;	size_t		j;	size_t		length;	int		lflags;	int		first = 1;	int		dofp;	size_t		total = todo;	while (todo) {		lflags = ops2f(1);		if ((length = fsizeof(floattype)) == 0)			floattype = 0;		/*		 * Determine if a floating-point constant should be output.		 * After forced constants are output, we stay with the		 * same type until we get NaN or Denormalized.		 */		dofp = 0;		if (floattype && length <= todo) {			if (sfpoint(floattype, p, format) != -1)				dofp = 1;		}		if (floattype && --numforce >= 0 || dofp) {			dofp = 1;			lflags |= size2f(floattype);		} else if (floattype)			return total - todo;		/*		 * For integral constants, we do 2 words at a time.		 * If the address is odd, we do the first byte by itself.		 */		if (!dofp) {			length = 2 * WORDSIZE;			if (todo < length) {				if (numforce)					length = todo;				else					return total - todo;			}			if (first && (ppc & 1) && length != todo)				length = 1;			if ((length % WORDSIZE) == 0) {				lflags |= size2f(WORD);				for (n = 0, i = 0; i < length / 2; i++) {					for (value = 0, j = 0; j < WORDSIZE;					  j++)						value += p[i * WORDSIZE + j]						  << (CHAR_BIT						  * (WORDSIZE - 1 - j));						value = signextend(value, 16);					if (i)						n += sprintf(format + n, ",");					n += sprintf(format + n, "#%d", value);				}			} else {				lflags |= size2f(BYTE);				for (n = 0, i = 0; i < length; i++) {					if (i)						n += sprintf(format + n, ",");					n += sprintf(format + n, "#%u", p[i]);				}			}		}		leninstbuf = 0;		for (i = 0; i < length; i++)			leninstbuf += sprintf(instbuf + leninstbuf, "%02x",			  p[i]);		pc += length;		instprint(lflags, "DC", format);		todo -= length;		p += length;		first = 0;	}	return total - todo;}/* * Output a string. * Return number of characters output. */static size_tascflush(size_t stored, const unsigned char *p, int force){	char	format[BUFSIZ];	size_t	length;	size_t	i;	size_t	n;	size_t	left;	size_t	nbytes;	for (length = 0; length < stored; length++)		if (use_isprint && !isprint(p[length])		  || !use_isprint && !ISASCII(p[length]))			break;	if (length == stored && !force)		return 0;	format[0] = '\'';	left = length;	while (left) {		n = 1;		leninstbuf = 0;		nbytes = (left > slenprint) ? slenprint : left;		for (i = length - left; i < length - left + nbytes; i++) {			leninstbuf += sprintf(instbuf + leninstbuf, "%02x",			  p[i]);			n += sprintf(format + n, "%c", p[i]);			/*			 * Double single quotes in strings.			 */			if (p[i] == '\'')				format[n++] = '\'';		}		format[n++] = '\'';		format[n++] = '\0';		pc += nbytes;		instprint(ops2f(1) | size2f(BYTE), "DC", format);		left -= nbytes;	}	return length;}/* * Convert a floating-point-label type to a floating-point type. */static intfl2ftype(int lflags){	if (lflags & ISLABEL) {		if (lflags & L_ISSINGLE)			return SINGLE;		if (lflags & L_ISDOUBLE)			return DOUBLE;		if (lflags & L_ISEXTENDED)			return EXTENDED;		if (lflags & L_ISPACKED)			return PACKED;	}	return 0;}/* * Output the ``stored'' input bytes contained in ``consts''. * If flags specifies a floating-point type, output floating-point * constants of that type as long as the input looks like them. * Output strings as appropriate.  Otherwise, output integral constants. * Return number of input bytes *not* output. */static size_tflush(size_t stored, const unsigned char *consts, int lflags, int force){	size_t	length;	int	spos = -2;	int	labelfptype = fl2ftype(lflags);	int	labelfpsize = fsizeof(labelfptype);	int	first = 1;	while (stored) {		spos = findstring(stored, consts);		if (first && labelfpsize && stored >= labelfpsize) {			if (spos == -1)				length = stored / labelfpsize * labelfpsize;			else if (spos > labelfpsize)				length = spos / labelfpsize * labelfpsize;			else				length = labelfpsize;			/*			 * Force a floating-point constant.			 */			length = dcflush(length, consts, labelfptype, 1);			stored -= length;			consts += length;			first = 0;			continue;		}		if (spos) {			int	lforce = 1;			/*			 * Output integral constant(s).			 */			if (spos < 0) {				if (force)					length = stored;				else {					if (stored < minlen)						return stored;					length = stored - minlen + 1;					lforce = 0;				}			} else				length = spos;			if (length > 0) {				if ((length = dcflush(length, consts, 0,				  lforce)) == 0)					return stored;				stored -= length;				consts += length;			} else				return stored;		}		if (spos >= 0) {			/*			 * Output string.			 */			if ((length = ascflush(stored, consts, force)) == 0)				return stored;			stored -= length;			consts += length;		}		first = 0;	}	return 0;}/* * Read a word (and extension words as necessary) from the input file * and determine if it is a possible instruction. * * ``valid'' is set to signal this. */static intvalidinst(void){	m68kword	inst;	valid = 0;	if (nextword(&inst) == 0) {		switch (inst >> 12) {		case 0:			bit_movep_immediate(inst);			break;		case 1:			movebyte(inst);			break;		case 2:			movelong(inst);			break;		case 3:			moveword(inst);			break;		case 4:			misc(inst);			break;		case 5:			addq_subq_scc_dbcc_trapcc(inst);			break;		case 6:			valid = bcc_bsr(inst);			break;		case 7:			moveq(inst);			break;		case 8:			or_div_sbcd(inst);			break;		case 9:			sub_subx(inst);			break;		case 10:			aline(inst);			break;		case 11:			cmp_eor(inst);			break;		case 12:			and_mul_abcd_exg(inst);			break;		case 13:			add_addx(inst);			break;		case 14:			shift_rotate_bitfield(inst);			break;		case 15:			coprocessor(inst);			if (!valid)				fline(inst);			break;		}	}	return valid;}/* * Now that we know where the constants are, make another pass * to determine which of them are referenced using the PC-relative * addressing mode. */static voiddcpass(void){	m68kaddr	offset;	pass = DCLABELSPASS;	if (fseek(infp, 0, SEEK_SET) == -1) {		perror("fseek");		jumpfree();	}	for (curoffset = offset = 0; offset <= maxoffset; )		if (insts[offset].size) {			if (curoffset != offset			  && fseek(infp, curoffset = offset, SEEK_SET) == -1) {				perror("fseek");				jumpfree();			}			flags = 0;			pc = ppc = offset + initialpc;			leninstbuf = 0;			validinst();			offset += insts[offset].size;		} else if (odd)			offset++;		else			offset += WORDSIZE;}/* * Make a pass over the input, outputting things as we currently see them. */static voidprintall(void){	m68kaddr	offset;	unsigned char	consts[BUFSIZ];	size_t		stored = 0;	if (fseek(infp, 0, SEEK_SET) == -1) {		perror("fseek");		jumpfree();	}	pc = ppc = initialpc;	leninstbuf = 0;	pass = DEBUGPASS;	for (curoffset = offset = 0; offset < gfsize /* = maxoffset */;	  offset += (odd ? 1 : WORDSIZE)) {		/*		 * Determine if there might be a valid instruction		 * which has the bytes at ``offset'' as operands.		 */		if (insts[offset].size == 0) {			int	i = 0;			size_t	size;			for (size = odd ? 1 : WORDSIZE; size <= longestinstsize			  && size <= offset; size += (odd ? 1 : WORDSIZE))				if (size < insts[offset - size].size) {					i = 1;					break;				}			if (i)				continue;		}		if (curoffset != offset		  && fseek(infp, curoffset = offset, SEEK_SET) == -1) {

⌨️ 快捷键说明

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