📄 dispass3.c
字号:
/*
* Pass 3 for Disassemblers
* Copyright (C) 1995-2005 by Jeffery L. Post
* theposts <AT> pacbell <DOT> net
*
* 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 <ctype.h>
#include "common.h"
//
// Defined Constants
//
/*
This ugly looking thing is used in pass 3 to determine whether
a miscellaneous equate statement should be generated. The equate
statement will be written to the disassembly file if the location
is referenced by some instruction and either it is a split reference
or the location is uninitialized and the location does not have an
entry in the label table. If the above requirements are met except
that the location has an entry in the label table, then an equate
statement will be generated as a label equate.
*/
#define MISC_EQU_TAG ((pflag & PF_REF) && !(pflag & PF_CLREF) && ((pflag & PF_SPLIT) | (pflag & PF_NOINIT)))
bool isnumeric(char *str);
//
// Global variables
//
/* none */
// Return TRUE if string is a simple expression based on a defined
// symbol, label, or operand name, eg: label+10 or symbol*4
bool isnumexpression(char *str)
{
int i, len;
bool arith = FALSE, valid = FALSE;
char name[MAX_LINE];
len = strlen(str);
for (i=0; i<len && !arith; i++)
{
switch (str[i])
{
case '+':
case '-':
case '*':
case '/':
arith = TRUE;
name[i] = '\0';
break;
default:
name[i] = str[i];
break;
}
}
name[i] = '\0';
if (arith) // appears to be an arithmetic expression
{
if (find_name(name, label_count, lab_val_index)) // is it a valid label?
valid = TRUE;
else if (find_name(name, symbol_count, sym_val_index)) // is it a valid symbol?
valid = TRUE;
else if (find_name(name, name_count, name_val_index)) // is it a valid operand name?
valid = TRUE;
}
if (arith && valid) // arithmetic expression based on a defined label, symbol, or name
return TRUE;
return FALSE;
}
// Return TRUE if string is purely numeric (eg: "0800h" or "1024" or "10110b")
bool isnumeric(char *str)
{
bool result = TRUE;
bool hex = FALSE;
bool binary = FALSE;
int i, len;
len = strlen(str);
if (toupper(str[len - 1]) == 'H')
{
hex = TRUE;
--len;
}
else if (toupper(str[len - 1]) == 'B')
{
binary = TRUE;
--len;
}
i = 0;
if (!hex && !binary) // if decimal number
{
if (str[0] == '-' && len > 1) // allow negative
i = 1;
}
for ( ; i<len; i++)
{
if (!str[i] || str[i] == '\n')
break;
if (hex) // hexadecimal number
{
if (!isxdigit(str[i]))
{
result = FALSE;
break;
}
}
else if (binary) // binary number
{
if (str[i] != '0' && str[i] != '1')
{
result = FALSE;
break;
}
}
else // decimal number
{
if (!isdigit(str[i]))
{
result = isnumexpression(str); // allow expressions in decimal data, eg: symbol+100
break;
}
}
}
return result;
}
//
// Pass three of disassembly
//
// Search for references to un-initialized data or split references
// and, if found, generate EQU statements for them.
//
void pass3(void)
{
int i, j, k, index, val, adrs, next_adrs, next_val, ok;
struct sym *ptr = NULL;
char *cptr;
int pflag;
bool isnum = FALSE;
printf("\nPass 3 0000");
// Sort tables by name for checking numeric entries
if (label_count)
{
lab_tab = sort_by_name(lab_tab);
ptr = lab_tab;
for (i=0; i<label_count; i++)
{
lab_val_index[i] = ptr;
ptr = ptr->next;
}
}
if (symbol_count)
{
sym_tab = sort_by_name(sym_tab);
ptr = sym_tab;
for (i=0; i<symbol_count; i++)
{
sym_val_index[i] = ptr;
ptr = ptr->next;
}
}
if (name_count)
{
name_tab = sort_by_name(name_tab);
ptr = name_tab;
for (i=0; i<name_count; i++)
{
name_val_index[i] = ptr;
ptr = ptr->next;
}
}
// search label table for labels referenced but not generated
j = TRUE;
for (index=0; index<label_count; index++)
{
ptr = lab_val_index[index];
isnum = isnumeric(ptr->name); // ignore if numeric expression
if (ptr->used && !isnum)
{
val = ptr->val;
val = pgmflags[val];
val &= (PF_NOINIT | PF_CLREF | PF_SPLIT | PF_REF);
if (val == (PF_REF | PF_SPLIT) || val == (PF_REF | PF_NOINIT))
{
if (j) // do header if first one
{
j = FALSE;
if (!newline || dump)
fprintf(fp, "\n;");
fprintf(fp, "\n;\tLabel equates\n;\n;"
" These are labels in the control file that reference\n;"
" the middle of a multibyte instruction or reference\n;"
" an address outside the initialized space\n;");
}
fprintf(fp, "\n%s\t%s\t", ptr->name, equstr);
puthex(ptr->val);
newline = FALSE;
}
}
}
// now do equates for symbol table
j = TRUE;
for (index=0; index<symbol_count; index++)
{
ptr = sym_val_index[index];
isnum = isnumeric(ptr->name); // ignore if numeric expression
if (ptr->used && !isnum)
{
if (j) // do header if first one
{
j = FALSE;
if (!newline || dump)
fprintf(fp, "\n;");
fprintf(fp, "\n;\tSymbol equates\n;\n;"
" These are symbols from the control\n;"
" file that are referenced in the code\n;");
}
fprintf(fp, "\n%s\t%s\t", ptr->name, equstr);
puthex(ptr->val);
newline = FALSE;
}
}
// now do equates for operand name table
j = TRUE;
ptr = name_tab;
for (index=0; index<name_count; index++)
{
ok = FALSE;
isnum = isnumeric(ptr->name); // ignore if numeric expression
if (ptr->used && !isnum)
{
if (!strcasecmp(ptr->name, ptr->next->name))
{
adrs = ptr->val;
val = pgmmem[adrs];
if (pgmflags[adrs] & PF_2BYTE)
#ifdef CPU_BIG_ENDIAN
{
val <<= 8;
val |= pgmmem[adrs + 1];
}
#else
val |= (pgmmem[adrs + 1] << 8);
#endif
next_adrs = ptr->next->val;
next_val = pgmmem[next_adrs];
if (pgmflags[next_adrs] & PF_2BYTE)
#ifdef CPU_BIG_ENDIAN
{
next_val <<= 8;
next_val |= pgmmem[next_adrs + 1];
}
#else
next_val |= (pgmmem[next_adrs + 1] << 8);
#endif
if (val != next_val)
ok = TRUE;
}
else
ok = TRUE;
if (ok)
{
if (j) // do header if first one
{
j = FALSE;
if (!newline || dump)
fprintf(fp, "\n;");
fprintf(fp, "\n;\tOperand symbol equates\n;\n;"
" These are operand symbols from the control\n;"
" file that are referenced in the code\n;");
}
adrs = ptr->val;
val = pgmmem[adrs] & 0xff;
if (pgmflags[adrs] & PF_2BYTE)
#ifdef CPU_BIG_ENDIAN
{
val <<= 8;
val |= pgmmem[adrs + 1];
}
#else
val |= (pgmmem[adrs + 1] << 8);
#endif
fprintf(fp, "\n%s\t%s\t", ptr->name, equstr);
puthex(val);
newline = FALSE;
}
}
ptr = ptr->next;
}
// to do miscellaneous equates, we need to resort labels by value
if (label_count)
lab_tab = sort(lab_tab, lab_val_index, label_count);
j = TRUE;
for (i=0; ; )
{
k = i & 0xfff;
pflag = pgmflags[i];
// if location is referenced and un-initialized or is a split ref
if (MISC_EQU_TAG)
{
cptr = find_entry(i, label_count, lab_val_index);
if ((cptr == NULL) && !(pflag & PF_LABGEN)) // if not in label list
{
if (j) // do header if first one
{
j = FALSE;
if (!newline || dump)
fprintf(fp, "\n;");
fprintf(fp, "\n;\tMiscellaneous equates\n;\n;"
" These are addresses referenced in the code but\n;"
" which are in the middle of a multibyte instruction\n;"
" or are addresses outside the initialized space\n;");
newline = FALSE;
}
if (!upperflag)
fprintf(fp, "\nX%04x\t%s\t", i, equstr); // do EQU statement
else
fprintf(fp, "\nX%04X\t%s\t", i, equstr);
puthex(i);
}
}
i++;
if (!(i & WORD_MASK))
break;
if ((i & 0xfff) < k)
printf("\rPass 3 %04x", i);
}
printf("\rPass 3 - Equate generation complete");
if (!newline || dump)
fprintf(fp, "\n;");
if (upperflag)
fprintf(fp, "\n\t.END\n;\n\n");
else
fprintf(fp, "\n\t.end\n;\n\n");
fflush(fp);
fclose(fp);
} // End of Pass 3
// end of pass3.c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -