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

📄 source.c

📁 AVR反汇编,对ATMEGA8有效
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
  Program: revava - Atmel Dis-Assembler
  File: Source.C, Copyright (C) 2001 Daniel J. Winker

  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.

  CHANGES:
  14-Mar-2001, Dan Winker
  Added op_code_addr.  See Bug_0001 in CHANGES.
*/

#include <stdio.h>
#include <string.h>

#include "Avr.h"
#include "Error.h"
#include "Flash.h"
#include "Source.h"

#define FALSE 0
#define TRUE  (!FALSE)

//#define DEBUG

char* m8_IO_register_name[] = {
						"TWBR",
						"TWSR",
						"TWAR", 
						"TWDR",    
						"ADCL", 
						"ADCH",
						"ADCSRA",
						"ADMUX",
						"ACSR ",
						"UBRRL",
						"UCSRB",
						"UCSRA",
						"UDR",
						"SPCR",
						"SPSR",
						"SPDR",
						"PIND",
						"DDRD",
						"PORTD",
						"PINC",
						"DDRC",
						"PORTC",
						"PINB",
						"DDRB",
						"PORTB",
						"Reserved",
						"Reserved",
						"Reserved",
						"EECR",
						"EEDR",
						"EEARL",
						"EEARH",
						"UBRRH",
						"WDTCR",
						"ASSR",
						"OCR2",
						"TCNT2",
						"TCCR2",
						"ICR1L",
						"ICR1H",
						"OCR1BL",
						"OCR1BH",
						"OCR1AL",
						"OCR1AH",
						"TCNT1L",
						"TCNT1H",
						"TCCR1B",
						"TCCR1A",
						"SFIOR",
						"OSCCAL",
						"TCNT0",
						"TCCR0",
						"MCUCSR",
						"MCUCR",
						"TWCR",
						"SPMCR",
						"TIFR",
						"TIMSK",
						"GIFR",
						"GICR",
						"Reserved",
						"SPL",
						"SPH",
						"SREG"

				};

TSourceOut::TSourceOut( const char* OutFile, TFlash* pFlash ){
	TAvr               Avr;
	TAvr::TInstruction Instruction;
	int                Index;
	int                line_count;
	FILE*              pOutFile;
	TSourceString*     pSourceString_temp;
	TSourceString*     pSourceString_head;
	TSourceString*     pSourceString_tail;
	int                last_line_was_blank = FALSE;
	int                look_for_new_segment = TRUE;
	int                code_seg_num = 0;
	unsigned short     code_word;
	unsigned short     temp_short;
	unsigned long      temp_long;
	int                addr;
	int                op_code_addr;
	int                dest = 0;
	int                have_dest;
	int                high_byte_written;
	int                low_byte_written;
	char               temp_string[ 80 ]; // FIXME - Magic Number
	char               temp_string2[ 80 ]; // FIXME - Magic Number
	char*              pLastTab;
	char*              tabs;

	prolog_head = NULL;
	prolog_tail = NULL;
	body_head   = NULL;
	body_tail   = NULL;

	if( 0 == strcmp( "stdout", OutFile ) ){
		pOutFile = stdout;
	} else {
		pOutFile = fopen( OutFile, "w" );
	}

	if( NULL == pOutFile )
		throw TFileError( "Cannot open file for writing:", OutFile );

	// FIXME - This probably doesn't belong burried deep withing a function.
	// This probably should be much more configurable.
	//push_prolog( "#arch AT90S8515" );
	push_prolog( "#include \"m8def.inc\" ");
	//push_prolog( "#include \"avr.inc\"" );

	for( addr = 0; addr < FLASH_SIZE; addr += 2 ){

		// Sometimes addr will get bumped because of a double word
		// instruction, but we still want to report the address of the
		// first word of the instruction.  op_code_addr is what is
		// reported.
		op_code_addr = addr;

		code_word = pFlash->get_flash_word(
			addr,
			&high_byte_written,
			&low_byte_written );

		#ifdef DEBUG_1
			printf( "DEBUG - SourceOut: ##############################\n" );
			printf( "DEBUG - SourceOut: addr              = %04X\n", addr );
			printf( "DEBUG - SourceOut: code_word         = %04X\n", code_word );
			printf( "DEBUG - SourceOut: high_byte_written = %04X\n", high_byte_written );
			printf( "DEBUG - SourceOut: low_byte_written  = %04X\n", low_byte_written );
		#endif

		if( high_byte_written != low_byte_written ){
			sprintf(
				temp_string,
				"TSourceOut: Word Address: %04X: high_byte_written != low_byte_written.",
				addr );
			throw TGenericError( temp_string ); 
		}


		if( high_byte_written ){

			if( look_for_new_segment ){
				#ifdef DEBUG
					printf( "DEBUG - SourceOut: Need Org Statement For: %04X\n", addr );
				#endif

				//sprintf( temp_string, "\tseg abs=0x%X flash.code%d", addr, code_seg_num );
				sprintf( temp_string, "\t.org 0x%X", addr/2);
				push_body( "" );
				push_body( temp_string );
				push_body( "" );
				last_line_was_blank = TRUE;

				code_seg_num++;
				look_for_new_segment = FALSE;
			}

			// First Time Through
			pSourceString_head = NULL;
			pSourceString_tail = NULL;
			Index = 0;
			while( 0 != ( Index = Avr.Word2Instruction(
				&Instruction,
				code_word,
				Index ))){

				#ifdef DEBUG
					printf( "DEBUG - SourceOut: Index                   = %d\n", Index);
					printf( "DEBUG - SourceOut: Addr:OpCode             = %04X:%04X\n", addr, code_word );
					printf( "DEBUG - SourceOut: Instruction.name        = %s\n",   Instruction.name );
					printf( "DEBUG - SourceOut: Instruction.arg0_format = %c\n",   Instruction.arg0_format );
					printf( "DEBUG - SourceOut: Instruction.arg1_format = %c\n",   Instruction.arg1_format );
					printf( "DEBUG - SourceOut: Instruction.arg0_type   = %d\n",   Instruction.arg0_format );
					printf( "DEBUG - SourceOut: Instruction.arg1_type   = %d\n",   Instruction.arg1_format );
					printf( "DEBUG - SourceOut: Instruction.arg0        = %04X\n", Instruction.arg0 );
					printf( "DEBUG - SourceOut: Instruction.arg1        = %04X\n", Instruction.arg1 );
				#endif

				have_dest = FALSE;

				if( TAvr::ARG_longCall == Instruction.arg0_type ){

					// These arg types are special because they also use the
					// next word as part of the opcode.

					// A really paranoid programmer would do a bounds check
					// on addr here.
					addr += 2;
					temp_short = pFlash->get_flash_word(
						addr,
						&high_byte_written,
						&low_byte_written );

					if( !high_byte_written || !low_byte_written ){
						sprintf(
							temp_string,
							"TSourceOut: Word Address: %04X: Needed Entire Word Written",
							addr );
						throw TGenericError( temp_string ); 
					}

					temp_long =
						( (unsigned long)Instruction.arg0 << 16 ) |
						( (unsigned long)temp_short );

					sprintf(
						temp_string,
						"\t%s\t0x%04lX",
						Instruction.name,
						temp_long );

				} else if(
					TAvr::ARG_neg64_63   == Instruction.arg0_type ||
					TAvr::ARG_neg2KB_2KB == Instruction.arg0_type ) {

					// We insist that arg types of ARG_neg64_63 and
					// ARG_neg2KB_2KB have an arg format of 'k'.
					if( 'k' != Instruction.arg0_format ){

						sprintf(
							temp_string,
							"TSourceOut:\n"
							"\t%s instruciton has arg0_type = ARG_neg64_63 or ARG_neg2KB_2KB\n"
							"\twith 'k' != ( arg0_format = '%c' )",
							Instruction.name,
							Instruction.arg0_format );
				
						throw TGenericError( temp_string ); 
					}

					// We also insist that arg0 types of ARG_neg64_63 and
					// ARG_neg2KB_2KB do not have an arg1.
					if( TAvr::ARG_none != Instruction.arg1_type ){

						sprintf(
							temp_string,
							"TSourceOut:\n"
							"\t%s instruciton has arg0_type = ARG_neg64_63 or ARG_neg2KB_2KB\n"
							"\twith ARG_none != arg1_type",
							Instruction.name );
				
						throw TGenericError( temp_string ); 
					}

					sprintf(
						temp_string,
						"\t%s\t%d",
						Instruction.name,
						(short)Instruction.arg0 );

					have_dest = TRUE;
					//there is a special case;
					if(Instruction.arg0<0 && Instruction.arg0<-2*1024){
						unsigned int offset = 0;
						offset = addr + 2 + 0x2000 + Instruction.arg0;
						offset = offset &0x0000FFFF;
						dest = offset;
					}else{
						dest = addr + 2 + (short)Instruction.arg0;
					}

				} else if (TAvr::ARG_0_PAIR==Instruction.arg0_type){
						sprintf(
								temp_string,
								"\t%s\tr%d:r%d",
								Instruction.name,
								Instruction.arg0*2+1,Instruction.arg0*2);
				}else{

					switch( Instruction.arg0_format ){

						case '\0':

							// No args to this instruction
							sprintf(
								temp_string,
								"\t%s",
								Instruction.name );

							break;

						case 'd':
						case 'r':
							//change register name
							char r_name[4];
							sprintf(r_name,"r%d",Instruction.arg0);
							switch(Instruction.arg0){
								case 26:
									strcpy(r_name,"XL");
									break;
								case 27:
									strcpy(r_name,"XH");
									break;
								case 28:
									strcpy(r_name,"YL");
									break;
								case 29:
									strcpy(r_name,"YH");
									break;
								case 30:
									strcpy(r_name,"ZL");
									break;
								case 31:
									strcpy(r_name,"ZH");
									break;

							}
							sprintf(
								temp_string,
								"\t%s\t%s",
								Instruction.name,
								r_name );

							break;

						case 'k':
						case 's':

							sprintf(
								temp_string,
								"\t%s\t%d",
								Instruction.name,
								(short)Instruction.arg0 );

							break;

						case 'P':
						case 'p':
							//need to translate to I/O register name;

							/*sprintf(
								temp_string,
								"\t%s\t0x%X",
								Instruction.name,
								Instruction.arg0 );*/
							sprintf(
								temp_string,
								"\t%s\t%s",
								Instruction.name,
								m8_IO_register_name[Instruction.arg0] );

							break;

						case 'X':
						case 'Y':
						case 'Z':

							if( 0 == strcmp( "std", Instruction.name )){
								sprintf(
									temp_string,
									"\t%s\t%c+%d",
									Instruction.name,
									Instruction.arg0_format,
									Instruction.arg0 );

							} else {

								// It's a little convoluted how we get the
								// information back from TAvr::AdjustArg about
								// whether to us "X", "X+", or "-X".  In this
								// arg_format is 'X'.  We differentiate by
								// setting the value of arg (which is an
								// (unsigned short)) to one of ' ', '+' or '-'.
								switch( (char)Instruction.arg0 ){

									case ' ':

										sprintf(
											temp_string,
											"\t%s\t%c",
											Instruction.name,
											Instruction.arg0_format );

										break;

									case '+':

										sprintf(
											temp_string,
											"\t%s\t%c+",
											Instruction.name,
											Instruction.arg0_format );

										break;

									case '-':

										sprintf(
											temp_string,
											"\t%s\t-%c",
											Instruction.name,
											Instruction.arg0_format );

										break;

									default:

										sprintf(
											temp_string,
											"TSourceOut:\n"
											"\t%s instruction has special arg0_format: '%c'\n"
											"\twith unknown arg0 of: 0x%X",
											Instruction.name,
											Instruction.arg0_format,
											Instruction.arg0 );
				
										throw TGenericError( temp_string ); 

										break;

								}
							}

⌨️ 快捷键说明

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