📄 d52pass2.c
字号:
/*
* D52 8052 Disassembler
* Copyright (C) 1995-2004 by Jeffery L. Post
* theposts <AT> pacbell <DOT> net
*
* d52pass2.C - Disassembly pass 2
*
* Version 3.3.6 - 11/28/04
*
* 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 <time.h>
#include "d52.h"
#include "common.h"
#include "d52pass1.h"
#include "d52pass2.h"
#include "d52table.h"
//
// Defined Constants
//
/* none */
//
// Global variables
//
/* none */
//
// Pass two of disassembly. Rescan data array and generate output file.
// Generate label if location flagged as referenced by some other opcode.
// If un-initialized data is encountered, ignore it but set skip flag so
// that an ORG statement can be generated when the next initialized data
// is found.
//
void pass2(void)
{
char *cptr;
int skip, year;
int i, l, q, temp, oldpc;
byte j, k;
int pflag;
time_t tp;
if (upperflag) // convert SFR, register, etc text to upper case
{
for (i=0; i<128; i++)
makeupper(sfr[i].dent);
for (i=0; i<128; i++)
makeupper(keilsfr[i].dent);
for (i=0; i<128; i++)
makeupper(sfrbits[i].dent);
for (i=0; i<128; i++)
makeupper(keilsfrbits[i].dent);
for (i=0; i<128; i++)
makeupper(membits[i].dent);
for (i=0; i<128; i++)
makeupper(keilmembits[i].dent);
for (i=0; i<128; i++)
makeupper(rbname[i].dent);
}
k = 0;
j = 0xff;
skip = TRUE;
dump = FALSE;
byte_cnt = 0;
asc_cnt = 0;
newline = FALSE;
printf("\nPass 2 0000");
fp = fopen(dst, "w"); // open output source file
if (!fp)
{
printf("\n* Can't open output file %s *\n", dst);
exit(FILE_ERROR);
}
// output header
fprintf(fp, ";\n; D52 V%d.%d.%d 8052 Disassembly of %s", VERSION, MAJORREV, MINORREV, src);
time(&tp); // get current time
date_time = localtime(&tp); // convert to hr/min/day etc
year = date_time->tm_year;
while (year > 100)
year -= 100;
fprintf(fp, "\n; %02d/%02d/%02d %02d:%02d", date_time->tm_mon + 1,
date_time->tm_mday, year,
date_time->tm_hour, date_time->tm_min);
if (incflag)
fprintf(fp, "\n;\n\tinclude\t\"sfr52.inc\"");
if (ascii_flag) // if user specified A on command line...
{
fprintf(fp, "\n;\nascii\tmacro\tx"); // generate macro for text
fprintf(fp, "\n\t%s\t'#x#'", defbstr);
fprintf(fp, "\n\tendm");
strcpy(ascistr, "ascii");
}
//
// Generate output file
//
for (i=offset; i<=himark; )
{
if (pgmflags[i] & PF_CMT)
{
if (byte_cnt) // dump any pending binary
dump_bytes(i);
if (asc_cnt) // dump any accumulated ascii
dump_ascii(i);
output_comment(i);
}
if (pgmflags[i] & PF_PATCH)
{
if (byte_cnt) // dump any pending binary
dump_bytes(i);
if (asc_cnt) // dump any accumulated ascii
dump_ascii(i);
output_patch(i);
}
oldpc = i;
l = i & 0xff;
pflag = pgmflags[i];
if (pflag == PF_INIT) // ignore un-initialized data
{
if (byte_cnt) // if binary or ascii data in buffers...
dump_bytes(i); // output them now
if (asc_cnt)
dump_ascii(i);
if (dump) // if we had to flush buffers...
{ // do a newline, since we will
dump = FALSE; // be doing an org (or end)
fprintf(fp, "\n;");
newline = TRUE;
}
i++; // next program location
skip = TRUE; // flag skip for ORG statement
j = -1;
}
else if (pflag & (PF_ADRS | PF_WORD | PF_BYTE | PF_ASCII))
{ // if not executable code
if (!(j & 0x80) && !skip)
{
j = -1;
fprintf(fp, "\n;");
newline = TRUE;
}
switch (pflag & (PF_ADRS | PF_WORD | PF_BYTE | PF_ASCII)) // ignore irrelevant bits
{
case PF_ASCII: // if ascii text...
if (byte_cnt) // dump any pending binary
dump_bytes(i);
if (skip) // insert ORG statement
{
if (!newline)
fprintf(fp, "\n;");
fprintf(fp, "\n\t%s\t", orgstr);
puthex(i);
fprintf(fp, "\n;");
newline = TRUE;
skip = FALSE; // reset skip flag
}
if (is_ascii(pgmmem[i])) // if it really is ascii...
{
string[asc_cnt] = pgmmem[i];
asc_cnt++;
if (asc_cnt >= ASCLIMIT)
dump_ascii(i + 1);
}
else // else treat it as binary data
{
pgmflags[i] |= PF_BYTE;
if (asc_cnt) // dump any accumulated ascii
dump_ascii(i);
byte_data[byte_cnt] = pgmmem[i]; // add data to buffer
byte_cnt++;
}
break;
case PF_WORD: // if word data...
if (byte_cnt) // dump any binary or ascii in buffers
dump_bytes(i);
if (asc_cnt)
dump_ascii(i);
if (skip) // insert ORG statement
{
if (!newline)
fprintf(fp, "\n;");
fprintf(fp, "\n\t%s\t", orgstr);
puthex(i);
fprintf(fp, "\n;");
newline = TRUE;
skip = FALSE; // reset skip flag
}
chk_label(i); // add label if referenced
q = ((int) pgmmem[i] & 0xff) << 8; // get word value
temp = pgmmem[i + 1] & 0xff;
q |= temp;
fprintf(fp, "%s\t", defwstr);
cptr = find_entry(q, symbol_count, sym_val_index); // see if symbol exists
if (cptr == NULL) // if not, do hex value
puthex(q);
else
fprintf(fp, "%s", cptr); // else output symbol
if (hexflag) // add comment field
{
fprintf(fp, "\t\t; %04x %02x %02x %c%c",
i, pgmmem[i], pgmmem[i + 1], ascii(pgmmem[i]),
ascii(pgmmem[i + 1]));
}
if (pgmflags[i] & PF_ICMT)
output_icomment(i);
i++;
if (pgmflags[i + 2] != PF_ADRS && pgmflags[i + 2] != PF_WORD)
{
fprintf(fp, "\n;");
newline = TRUE;
}
break;
case PF_ADRS: // if address data...
if (byte_cnt) // output any pending binary or
dump_bytes(i); // ascii data from buffers
if (asc_cnt)
dump_ascii(i);
if (skip) // insert ORG statement
{
if (!newline)
fprintf(fp, "\n;");
fprintf(fp, "\n\t%s\t", orgstr);
puthex(i);
fprintf(fp, "\n;");
newline = TRUE;
skip = FALSE; // reset skip flag
}
chk_label(i); // add label if referenced
q = ((int) pgmmem[i]) << 8; // get address value
temp = pgmmem[i + 1] & 0xff;
q |= temp;
fprintf(fp, "%s\t", defwstr);
cptr = find_entry(q, label_count, lab_val_index);
// see if label exists
if (cptr == NULL) // if not, output hex
{
if (!pgmflags[i] & PF_LABEL) // search symbol table only if not defined as label
cptr = find_entry(q, symbol_count, sym_val_index);
if (cptr == NULL)
{
if (!upperflag)
fprintf(fp, "X%04x", q);
else
fprintf(fp, "X%04X", q);
}
else
fprintf(fp, "%s", cptr);
}
else
fprintf(fp, "%s", cptr); // else output label text
if (hexflag) // do comment field
{
fprintf(fp, "\t\t; %04x %02x %02x %c%c",
i, pgmmem[i], pgmmem[i + 1],
ascii(pgmmem[i]), ascii(pgmmem[i + 1]));
}
if (pgmflags[i] & PF_ICMT)
output_icomment(i);
i++;
if (pgmflags[i + 2] != PF_ADRS)
{
fprintf(fp, "\n;");
newline = TRUE;
}
break;
default: // default = binary data...
if (asc_cnt) // output any pending ascii data
dump_ascii(i);
if (skip) // insert ORG statement
{
if (byte_cnt)
dump_bytes(i);
if (!newline)
fprintf(fp, "\n;");
fprintf(fp, "\n\t%s\t", orgstr);
puthex(i);
fprintf(fp, "\n;");
newline = TRUE;
skip = FALSE; // reset skip flag
}
byte_data[byte_cnt] = pgmmem[i]; // add data to buffer
byte_cnt++;
if (byte_cnt >= BYTELIMIT) // if end of buffer...
dump_bytes(i + 1); // dump accumulated data
}
i++; // next program location
if (pgmflags[i] != PF_INIT && pgmflags[i] & PF_ASCII)
{ // if next byte is flagged as
if (!is_ascii(pgmmem[i])) // ascii, but is not...
pgmflags[i] |= PF_BYTE; // then flag it as binary
}
}
//
// If previous data was an unconditional transfer, AND
// current location is not referenced by some other opcode, AND
// current byte is 0 or 0FFH, THEN
// treat this byte as un-initialized data.
//
else if ((j & 0x80) && (!(pflag & PF_REF)) &&
((pgmmem[i] == 0) || (pgmmem[i] == NO_DATA)) &&
(!(pflag & PF_FORCE)))
{
if (byte_cnt) // since we're going to skip some
dump_bytes(i); // data, output any pending ascii
if (asc_cnt) // or binary data remaining in buffers
dump_ascii(i);
if (dump) // if ascii or binary output was done,
{ // stick in a newline
fprintf(fp, "\n;");
dump = FALSE;
newline = TRUE;
}
pgmflags[i] = PF_INIT; // flag as uninitialized data
i++;
skip = TRUE;
byte_cnt = 0;
}
//
// If previous opcode was 0 or 0ffH, AND current location is not
// referenced but is initialized, AND current opcode is 0 or 0ffH,
// un-initialize it.
//
else if ((k == 0 || k == 0xff) &&
(!(pflag & PF_REF)) && (pgmmem[i] == 0 || pgmmem[i] == NO_DATA) &&
(!(pflag & PF_CLREF)) && !(pflag & PF_NOINIT) &&
(!(pflag & PF_FORCE)))
{
pgmflags[i] = PF_INIT;
i++;
skip = TRUE;
j = -1;
}
else // IT'S EXECUTABLE CODE!
{
pgmflags[i] &= ~PF_NOINIT; // clear for label search in pass 3
if (byte_cnt) // if any ascii or binary data remains
dump_bytes(i); // in the buffers, output them now
if (asc_cnt)
dump_ascii(i);
if (dump)
{
fprintf(fp, "\n;");
dump = FALSE;
newline = TRUE;
}
byte_cnt = 0;
if (skip) // insert ORG statement
{
if (!newline)
fprintf(fp, "\n;");
fprintf(fp, "\n\t%s\t", orgstr);
puthex(i);
fprintf(fp, "\n;");
newline = TRUE;
skip = FALSE; // reset skip flag
}
k = pgmmem[i]; // get opcode
if (k == 0xa5 && !newline) // if invalid opcode
{
fprintf(fp, "\n;");
newline = TRUE;
}
chk_ref(i); // add label if referenced
kcnt = 8;
j = opttbl[k]; // get options
doopcode(mnemtbl[k].mnem); // output mnemonic
//
// Generate operands
//
switch (j & OPT_MASK)
{
case OPT_NONE: // single byte - no options
break;
case OPT_IMM2: // 2 byte immediate data
q = (int) pgmmem[i + 1] & 0xff;
if (pgmflags[i + 1] & PF_NAME)
cptr = find_entry(i + 1, name_count, name_val_index);
else
cptr = find_entry(q, symbol_count, sym_val_index);
if (cptr == NULL)
puthex(q);
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -