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

📄 format_disasm.c

📁 Avr系列单片机反汇编器源代码.GCC编译
💻 C
字号:
/* * vAVRdisasm - AVR program disassembler. * Version 1.0 - January 2007. * Written by Vanya A. Sergeev - <vsergeev@gmail.com> * * Copyright (C) 2007 Vanya A. Sergeev * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.  * * format_disasm.c - Formatting of disassembled instructions, with regard to the *  several formatting features this disassembler supports. * */#include <stdio.h>#include <string.h>#include <stdlib.h>#include "format_disasm.h"/* Formats a disassembled operand with its prefix (such as 'R' to indicate a register) into the * pointer to a C-string strOperand, which must be free'd after it has been used. * I decided to format the disassembled operands individually into strings for maximum flexibility, * and so that the printing of the formatted operand is not hard coded into the format operand code. * If an addressLabelPrefix is specified in formattingOptions (option is set and string is not NULL),  * it will print the relative branch/jump/call with this prefix and the destination address as the label. */static int formatDisassembledOperand(char **strOperand, int operandNum, const disassembledInstruction dInstruction, formattingOptions fOptions);/* Prints a disassembled instruction, formatted with options set in the formattingOptions structure. */int printDisassembledInstruction(FILE *out, const disassembledInstruction dInstruction, formattingOptions fOptions) {	int retVal, i;	char *strOperand;		/* If we just found a long instruction, there is nothing to be printed yet, since we don't	 * have the entire long address ready yet. */	if (AVR_Long_Instruction == AVR_LONG_INSTRUCTION_FOUND)		return 0;		/* If address labels are enabled, then we use an address label prefix as set in the	 * string addressLabelPrefix, because labels need to start with non-numerical character	 * for best compatibility with AVR assemblers. */		if (fOptions.options & FORMAT_OPTION_ADDRESS_LABEL) 		retVal = fprintf(out, "%s%0*X: %s ", fOptions.addressLabelPrefix, fOptions.addressFieldWidth, dInstruction.address, dInstruction.instruction->mnemonic);	/* Just print the address that the instruction is located at, without address labels. */	else if (fOptions.options & FORMAT_OPTION_ADDRESS) 		retVal = fprintf(out, "%4X:\t%s ", dInstruction.address, dInstruction.instruction->mnemonic);	else 		retVal = fprintf(out, "%s ", dInstruction.instruction->mnemonic);	if (retVal < 0)		return ERROR_FILE_WRITING_ERROR;	for (i = 0; i < dInstruction.instruction->numOperands; i++) {		/* If we're not on the first operand, but not on the last one either, print a comma separating		 * the operands. */		if (i > 0 && i != dInstruction.instruction->numOperands) {			if (fprintf(out, ", ") < 0)				return ERROR_FILE_WRITING_ERROR;		}		/* Format the disassembled operand into the string strOperand, and print it */		retVal = formatDisassembledOperand(&strOperand, i, dInstruction, fOptions);		if (retVal < 0)			return retVal;		/* Print the operand and free if it's not NULL */		if (strOperand != NULL) {			fprintf(out, "%s", strOperand);			free(strOperand);		}	}	/* If we want a comment specifying what address the rjmp or rcall would take us,	 * i.e. rcall .+4 ; 0x56	 */	if (fOptions.options & FORMAT_OPTION_DESTINATION_ADDRESS_COMMENT) {		for (i = 0; i < dInstruction.instruction->numOperands; i++) {			/* This is only done for operands with relative addresses,			 * where the destination address is relative from the address 			 * the PC is on. */			if (dInstruction.instruction->operandTypes[i] == OPERAND_BRANCH_ADDRESS ||				dInstruction.instruction->operandTypes[i] == OPERAND_RELATIVE_ADDRESS) {					if (fprintf(out, "%1s\t; %s%X", "", OPERAND_PREFIX_ABSOLUTE_ADDRESS, dInstruction.address+dInstruction.operands[i]+2) < 0)						return ERROR_FILE_WRITING_ERROR;					/* Stop after one relative address operand */					break;			}		}	}		fprintf(out, "\n");	return 0;}/* Formats a disassembled operand with its prefix (such as 'R' to indicate a register) into the * pointer to a C-string strOperand, which must be free'd after it has been used. * I decided to format the disassembled operands individually into strings for maximum flexibility, * and so that the printing of the formatted operand is not hard coded into the format operand code. * If an addressLabelPrefix is specified in formattingOptions (option is set and string is not NULL),  * it will print the relative branch/jump/call with this prefix and the destination address as the label. */int formatDisassembledOperand(char **strOperand, int operandNum, const disassembledInstruction dInstruction, formattingOptions fOptions) {	char binary[8];	int retVal;	switch (dInstruction.instruction->operandTypes[operandNum]) {		case OPERAND_NONE:		case OPERAND_REGISTER_GHOST:			retVal = asprintf(strOperand, "");			break;		case OPERAND_REGISTER:		case OPERAND_REGISTER_STARTR16:		case OPERAND_REGISTER_EVEN_PAIR_STARTR24:		case OPERAND_REGISTER_EVEN_PAIR:			retVal = asprintf(strOperand, "%s%d", OPERAND_PREFIX_REGISTER, dInstruction.operands[operandNum]);			break;		case OPERAND_DATA:		case OPERAND_COMPLEMENTED_DATA:			if (fOptions.options & FORMAT_OPTION_DATA_BIN) {				int i;				for (i = 7; i >= 0; i--) {					if (dInstruction.operands[operandNum] & (1<<i))						binary[7-i] = '1';					else						binary[7-i] = '0';				}				binary[8] = '\0'; 				retVal = asprintf(strOperand, "%s%s", OPERAND_PREFIX_DATA_BIN, binary);			} else if (fOptions.options & FORMAT_OPTION_DATA_DEC) {				retVal = asprintf(strOperand, "%s%d", OPERAND_PREFIX_DATA_DEC, dInstruction.operands[operandNum]);			} else {				retVal = asprintf(strOperand, "%s%02X", OPERAND_PREFIX_DATA_HEX, dInstruction.operands[operandNum]);			}			break;		case OPERAND_BIT:			retVal = asprintf(strOperand, "%s%d", OPERAND_PREFIX_BIT, dInstruction.operands[operandNum]);			break;		case OPERAND_BRANCH_ADDRESS:		case OPERAND_RELATIVE_ADDRESS:			/* If we have an address label, print it, otherwise just print the			 * relative distance to the destination address. */			if ((fOptions.options & FORMAT_OPTION_ADDRESS_LABEL) && fOptions.addressLabelPrefix != NULL) { 				retVal = asprintf(strOperand, "%s%0*X", fOptions.addressLabelPrefix, fOptions.addressFieldWidth, dInstruction.address+dInstruction.operands[operandNum]+2);			} else {				/* Check if the operand is greater than 0 so we can print the + sign. */				if (dInstruction.operands[operandNum] > 0) {					retVal = asprintf(strOperand, "%s+%d", OPERAND_PREFIX_BRANCH_ADDRESS, dInstruction.operands[operandNum]);				} else {				/* Since the operand variable is signed, the negativeness of the distance				 * to the destination address has been taken care of in disassembleOperands() */					retVal = asprintf(strOperand, "%s%d", OPERAND_PREFIX_BRANCH_ADDRESS, dInstruction.operands[operandNum]);				}			}			break;		case OPERAND_LONG_ABSOLUTE_ADDRESS:			retVal = asprintf(strOperand, "%s%0*X", OPERAND_PREFIX_ABSOLUTE_ADDRESS, fOptions.addressFieldWidth, AVR_Long_Address);			break;		case OPERAND_IO_REGISTER:			retVal = asprintf(strOperand, "%s%02X", OPERAND_PREFIX_IO_REGISTER, dInstruction.operands[operandNum]);			break;			case OPERAND_WORD_DATA:			retVal = asprintf(strOperand, "%s%0*X", OPERAND_PREFIX_WORD_DATA, fOptions.addressFieldWidth, dInstruction.operands[operandNum]);			break;		case OPERAND_YPQ:			retVal = asprintf(strOperand, "Y+%d", dInstruction.operands[operandNum]);			break;		case OPERAND_ZPQ:			retVal = asprintf(strOperand, "Z+%d", dInstruction.operands[operandNum]);			break;		case OPERAND_X:			retVal = asprintf(strOperand, "X");			break;		case OPERAND_XP:			retVal = asprintf(strOperand, "X+");			break;		case OPERAND_MX:			retVal = asprintf(strOperand, "-X");			break;		case OPERAND_Y:			retVal = asprintf(strOperand, "Y");			break;		case OPERAND_YP:			retVal = asprintf(strOperand, "Y+");			break;		case OPERAND_MY:			retVal = asprintf(strOperand, "-Y");			break;		case OPERAND_Z:			retVal = asprintf(strOperand, "Z");			break;		case OPERAND_ZP:			retVal = asprintf(strOperand, "Z+");			break;		case OPERAND_MZ:			retVal = asprintf(strOperand, "-Z");			break;		/* This is impossible by normal operation. */		default:			return ERROR_UNKNOWN_OPERAND; 	}	if (retVal < 0)		return ERROR_MEMORY_ALLOCATION_ERROR;	return 0;}

⌨️ 快捷键说明

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