|
@@ -125,7 +125,7 @@ static const char *szWreg[12] = { "ax", "cx", "dx", "bx", "sp", "bp", "si", "di"
|
|
|
static const char *szPtr[2] = { " word ptr ", " byte ptr " };
|
|
|
|
|
|
|
|
|
-static void dis1Line (Int i, boolT fWin, char attr, Int pass);
|
|
|
+static void dis1Line (Int i, Int pass);
|
|
|
void dis1LineOp(Int i, boolT fWin, char attr, word *len, Function * pProc);
|
|
|
static void formatRM(char *p, flags32 flg, ICODEMEM* pm);
|
|
|
static char *strDst(flags32 flg, ICODEMEM *pm);
|
|
@@ -160,93 +160,6 @@ static char cbuf[256]; /* Has to be 256 for wgetstr() to work */
|
|
|
// These are "curses equivalent" functions. (Used to use curses for all this,
|
|
|
// but it was too much of a distribution hassle
|
|
|
|
|
|
-#if _CONSOLE
|
|
|
-HANDLE hConsole; /* All 32 bit console style routines need this handle */
|
|
|
-#endif
|
|
|
-
|
|
|
-void attrSet(char attrib)
|
|
|
-{
|
|
|
-#ifdef _CONSOLE
|
|
|
- switch (attrib)
|
|
|
- {
|
|
|
- case A_NORMAL:
|
|
|
- SetConsoleTextAttribute(hConsole,FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED);
|
|
|
- break;
|
|
|
- case A_REVERSE:
|
|
|
- SetConsoleTextAttribute(hConsole,BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED);
|
|
|
- break;
|
|
|
- case A_BOLD:
|
|
|
- SetConsoleTextAttribute(hConsole,FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED |FOREGROUND_INTENSITY);
|
|
|
- break;
|
|
|
- }
|
|
|
-#else
|
|
|
- /* Set the attribute, using VT100 codes */
|
|
|
- switch (attrib)
|
|
|
- {
|
|
|
- case A_NORMAL:
|
|
|
- printf("\033[0m");
|
|
|
- break;
|
|
|
- case A_REVERSE:
|
|
|
- printf("\033[7m");
|
|
|
- break;
|
|
|
- case A_BOLD:
|
|
|
- printf("\033[1m");
|
|
|
- break;
|
|
|
- }
|
|
|
-#endif
|
|
|
-}
|
|
|
-
|
|
|
-#ifdef _CONSOLE
|
|
|
-void initConsole()
|
|
|
-{
|
|
|
- hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
|
-}
|
|
|
-#endif
|
|
|
-
|
|
|
-void erase(void)
|
|
|
-{
|
|
|
-#ifdef _CONSOLE
|
|
|
- COORD coordScreen = { 0, 0 }; /* here's where we'll home the
|
|
|
- cursor */
|
|
|
- DWORD cCharsWritten;
|
|
|
- CONSOLE_SCREEN_BUFFER_INFO csbi; /* to get buffer info */
|
|
|
- DWORD dwConSize; /* number of character cells in
|
|
|
- the current buffer */
|
|
|
-
|
|
|
- /* get the number of character cells in the current buffer */
|
|
|
- GetConsoleScreenBufferInfo( hConsole, &csbi );
|
|
|
- dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
|
|
|
-
|
|
|
- /* fill the entire screen with blanks */
|
|
|
- FillConsoleOutputCharacter( hConsole, (TCHAR) ' ',dwConSize, coordScreen, &cCharsWritten );
|
|
|
-
|
|
|
- /* get the current text attribute */
|
|
|
- // GetConsoleScreenBufferInfo( hConsole, &csbi );
|
|
|
-
|
|
|
- /* now set the buffer's attributes accordingly */
|
|
|
- FillConsoleOutputAttribute( hConsole, csbi.wAttributes,dwConSize, coordScreen, &cCharsWritten );
|
|
|
-
|
|
|
- /* put the cursor at (0, 0) */
|
|
|
- SetConsoleCursorPosition( hConsole, coordScreen );
|
|
|
-
|
|
|
-#else
|
|
|
- // Assume that ANSI is supported
|
|
|
- printf("\033[2J");
|
|
|
-#endif
|
|
|
-}
|
|
|
-
|
|
|
-void move(int r, int c)
|
|
|
-{
|
|
|
-#ifdef _CONSOLE
|
|
|
- COORD pos;
|
|
|
- pos.X = c;
|
|
|
- pos.Y = r;
|
|
|
- SetConsoleCursorPosition( hConsole, pos );
|
|
|
-#else
|
|
|
- printf("\033[%d;%dH", r+1, c+1);
|
|
|
-#endif
|
|
|
-}
|
|
|
-
|
|
|
#define printfd(x) printf(x)
|
|
|
#define dis_newline() printf("\n")
|
|
|
#define dis_show() // Nothing to do unless using Curses
|
|
@@ -270,7 +183,8 @@ void disassem(Int pass, Function * ppProc)
|
|
|
}
|
|
|
createSymTables();
|
|
|
allocIcode = numIcode = pProc->Icode.GetNumIcodes();
|
|
|
- if ((cb = allocIcode * sizeof(ICODE)) == 0)
|
|
|
+ cb = allocIcode * sizeof(ICODE);
|
|
|
+ if (numIcode == 0)
|
|
|
{
|
|
|
return; /* No Icode */
|
|
|
}
|
|
@@ -325,7 +239,7 @@ void disassem(Int pass, Function * ppProc)
|
|
|
/* Loop over array printing each record */
|
|
|
for (i = nextInst = 0; i < numIcode; i++)
|
|
|
{
|
|
|
- dis1Line(i, FALSE, 0, pass);
|
|
|
+ dis1Line(i, pass);
|
|
|
}
|
|
|
|
|
|
/* Write procedure epilogue */
|
|
@@ -344,8 +258,7 @@ void disassem(Int pass, Function * ppProc)
|
|
|
* i is index into Icode for this proc *
|
|
|
* It is assumed that icode i is already scanned *
|
|
|
****************************************************************************/
|
|
|
-static void
|
|
|
-dis1Line(Int i, boolT fWindow, char attr, Int pass)
|
|
|
+static void dis1Line(Int i, Int pass)
|
|
|
{
|
|
|
ICODE * pIcode = &pc[i];
|
|
|
|
|
@@ -368,10 +281,8 @@ dis1Line(Int i, boolT fWindow, char attr, Int pass)
|
|
|
|
|
|
if (pIcode->ic.ll.flg & (TARGET | CASE))
|
|
|
{
|
|
|
- if (fWindow) /* Printing to disassem window? */
|
|
|
- dis_newline(); /* Yes */
|
|
|
- else if (pass == 3)
|
|
|
- cCode.appendCode("\n"); /* No, print to c code buffer */
|
|
|
+ if (pass == 3)
|
|
|
+ cCode.appendCode("\n"); /* Print to c code buffer */
|
|
|
else
|
|
|
fprintf(fp, "\n"); /* No, print to the stream */
|
|
|
}
|
|
@@ -670,21 +581,7 @@ dis1Line(Int i, boolT fWindow, char attr, Int pass)
|
|
|
/* Display output line */
|
|
|
if (! (pIcode->ic.ll.flg & SYNTHETIC))
|
|
|
{
|
|
|
- if (fWindow)
|
|
|
- {
|
|
|
- word off;
|
|
|
- char szOffset[6];
|
|
|
-
|
|
|
- off = (word)(pIcode->ic.ll.label - ((dword)pProc->state.r[rCS] << 4));
|
|
|
- attrSet(attr);
|
|
|
-
|
|
|
- sprintf(szOffset, "%04X ", off);
|
|
|
- printfd(szOffset);
|
|
|
- printfd(buf);
|
|
|
- dis_newline();
|
|
|
- attrSet(A_NORMAL);
|
|
|
- }
|
|
|
- else if (pass == 3) /* output to .b code buffer */
|
|
|
+ if (pass == 3) /* output to .b code buffer */
|
|
|
cCode.appendCode("%s\n", buf);
|
|
|
else /* output to .a1 or .a2 file */
|
|
|
fprintf (fp, "%03ld %06lX %s\n", i, pIcode->ic.ll.label, buf);
|
|
@@ -692,13 +589,7 @@ dis1Line(Int i, boolT fWindow, char attr, Int pass)
|
|
|
else /* SYNTHETIC instruction */
|
|
|
{
|
|
|
strcat (buf, ";Synthetic inst");
|
|
|
- if (fWindow)
|
|
|
- {
|
|
|
- printfd(" ");
|
|
|
- printfd(buf);
|
|
|
- dis_newline();
|
|
|
- }
|
|
|
- else if (pass == 3) /* output to .b code buffer */
|
|
|
+ if (pass == 3) /* output to .b code buffer */
|
|
|
{
|
|
|
cCode.appendCode("%s\n", buf);
|
|
|
}
|
|
@@ -806,706 +697,13 @@ static char *strHex(dword d)
|
|
|
return (buf + (buf[1] <= '9'));
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
|
|
|
-| Interactive Disassembler and Associated Routines |
|
|
|
-\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-dword pcTop; /* Image offset of top line */
|
|
|
-Int icTop; /* Icode index of top line */
|
|
|
-dword pcCur; /* Image offset of cursor */
|
|
|
-static dword oldPcCur; /* As above, before latest command */
|
|
|
-Int icCur; /* Icode index of cursor */
|
|
|
-dword pcBot; /* Image offset of bottom line */
|
|
|
-Int icBot; /* Icode index of bottom line */
|
|
|
-dword pcLast; /* Image offset of last instr in proc */
|
|
|
-int NSCROLL; /* Number of limes to scroll. Pseudo constant */
|
|
|
-
|
|
|
-/* Paint the title line */
|
|
|
-void dispTitle(void)
|
|
|
-{
|
|
|
- char buf[80];
|
|
|
-
|
|
|
- move(0, 0); /* Must move before setting attributes */
|
|
|
- attrSet(A_BOLD);
|
|
|
- sprintf(buf, "Proc %s at %06lX (%04X:%04X): %d bytes of parameters ",pProc->name, pProc->Icode.GetFirstIcode()->ic.ll.label,
|
|
|
- pProc->state.r[rCS],(word)(pProc->Icode.GetFirstIcode()->ic.ll.label - ((dword)(pProc->state.r[rCS]) << 4)),
|
|
|
- pProc->cbParam);
|
|
|
- printfd(buf);
|
|
|
- if (pProc->flg & PROC_ISLIB) printfd(" LIBRARY");
|
|
|
- attrSet(A_NORMAL);
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-/****************************************************************************
|
|
|
-* updateScr - update the screen *
|
|
|
- ****************************************************************************/
|
|
|
-/* bNew is true if must recalculate the top line */
|
|
|
-void updateScr(boolT bNew)
|
|
|
-{
|
|
|
- int y, x;
|
|
|
- Int i, ic;
|
|
|
-
|
|
|
- bNew |= (pcCur > pcBot) || (pcCur < pcTop);
|
|
|
- if (bNew)
|
|
|
- {
|
|
|
- /* We need to redo the screen completely */
|
|
|
- erase();
|
|
|
- dispTitle();
|
|
|
- icTop = icCur;
|
|
|
- for (x=0; x < NSCROLL; x++)
|
|
|
- {
|
|
|
- if (icTop && pc[icTop-1].ic.ll.label +
|
|
|
- (dword)pc[icTop-1].ic.ll.numBytes == pc[icTop].ic.ll.label)
|
|
|
- {
|
|
|
- /* Then this instruction is contiguous with the current */
|
|
|
- icTop--;
|
|
|
- }
|
|
|
- else break;
|
|
|
- }
|
|
|
- pcTop = pc[icTop].ic.ll.label;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- dispTitle();
|
|
|
- }
|
|
|
-
|
|
|
- move(1, 0);
|
|
|
- nextInst = pcTop;
|
|
|
- for (y=1, ic=icTop; y < LINES-1; ic++, y++)
|
|
|
- {
|
|
|
- if ((ic >= numIcode) || (nextInst != pc[ic].ic.ll.label))
|
|
|
- {
|
|
|
- if (labelSrch(pc,numIcode, nextInst, &i))
|
|
|
- {
|
|
|
- ic = i;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- pcLast = pc[ic-1].ic.ll.label; /* Remember end of proc */
|
|
|
- break; /* Must be past last */
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /* Save pc of current line. Last assignment will be pc of bott line */
|
|
|
- pcBot = nextInst;
|
|
|
- icBot = ic;
|
|
|
-
|
|
|
- // Only have to repaint if screen is new, or repainting formerly highlighted
|
|
|
- // line, or newly highlighted line
|
|
|
- if (bNew || (pcCur == nextInst) || (oldPcCur == nextInst))
|
|
|
- dis1Line(ic, TRUE, (char)((pcCur == nextInst) ? A_REVERSE : A_NORMAL), 0);
|
|
|
-
|
|
|
- if (ic == numIcode-1)
|
|
|
- {
|
|
|
- switch (pc[ic].ic.ll.opcode)
|
|
|
- {
|
|
|
- case iJMP: case iJMPF:
|
|
|
- case iRET: case iRETF:
|
|
|
- case iIRET:
|
|
|
- break;
|
|
|
-
|
|
|
- default:
|
|
|
- /* We have other than a break of control flow instruction
|
|
|
- at the end of the proc. Parse more instructions to
|
|
|
- complete the basic block
|
|
|
- */
|
|
|
- if ((ic = checkScanned(nextInst)) == -1)
|
|
|
- {
|
|
|
- /* Some error. */
|
|
|
- pcLast = pcCur; /* Remember end of proc */
|
|
|
- break; /* Must be past last */
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- dis_show(); /* Make it happen */
|
|
|
-}
|
|
|
-
|
|
|
-#if 0
|
|
|
-/* An opcode based version of updateScr() */
|
|
|
-/****************************************************************************
|
|
|
-* updateScrOp - update the screen *
|
|
|
- ****************************************************************************/
|
|
|
-/* bNew is true if must recalculate the top line */
|
|
|
-void
|
|
|
-updateScrOp(boolT bNew)
|
|
|
-{
|
|
|
- int y, x;
|
|
|
- dword pc;
|
|
|
- word len;
|
|
|
-
|
|
|
- dispTitle();
|
|
|
- if (bNew || (pcCur > pcBot) || (pcCur < pcTop))
|
|
|
- {
|
|
|
- /* We need to redo the screen completely */
|
|
|
- pcTop = pcCur;
|
|
|
- }
|
|
|
-
|
|
|
- move(1, 0);
|
|
|
- for (y=1, pc = pcTop; y < LINES-1;)
|
|
|
- {
|
|
|
- /* Save pc of current line. Last assignment will be pc of bott line */
|
|
|
- pcBot = pc;
|
|
|
-
|
|
|
- dis1LineOp(pc, TRUE, (pcCur == pc) ? A_REVERSE : A_NORMAL, &len,pProc);
|
|
|
- pc += len;
|
|
|
- getyx(stdscr, y, x);
|
|
|
- }
|
|
|
-
|
|
|
- refresh();
|
|
|
-}
|
|
|
-
|
|
|
-#endif
|
|
|
-
|
|
|
-void pushPosStack(void)
|
|
|
-{
|
|
|
- /* Push the current position on the position stack */
|
|
|
- posStack[iPS].ic = icCur;
|
|
|
- posStack[iPS++].pProc = pProc;
|
|
|
-}
|
|
|
-
|
|
|
-static void popPosStack(void)
|
|
|
-{
|
|
|
- /* Push the current position on the position stack */
|
|
|
- /* Note: relies on the byte wraparound. Beware! */
|
|
|
- // if ((Int)(posStack[--iPS].pProc) != -1)
|
|
|
- if ((intptr_t)(posStack[--iPS].pProc) != intptr_t(-1))
|
|
|
- {
|
|
|
- if (posStack[iPS].pProc != pProc)
|
|
|
- {
|
|
|
- setProc(posStack[iPS].pProc);
|
|
|
- }
|
|
|
- icCur = posStack[iPS].ic;
|
|
|
- pcCur = pc[icCur].ic.ll.label;
|
|
|
- }
|
|
|
- else iPS++; /* Stack empty.. don't pop */
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-/* Check to see if there is an icode for given image offset.
|
|
|
- Scan it if necessary, adjusting the allocation of pc[] and pl[]
|
|
|
- if necessary. Returns -1 if an error, otherwise the icode offset
|
|
|
-*/
|
|
|
-static Int checkScanned(dword pcCur)
|
|
|
-{
|
|
|
- Int i;
|
|
|
-
|
|
|
- /* First we check if the current icode is in range */
|
|
|
- /* A sanity check first */
|
|
|
- if (pcCur >= (dword)prog.cbImage)
|
|
|
- {
|
|
|
- /* Couldn't be! */
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- if (!labelSrch(pc,numIcode, pcCur, &i))
|
|
|
- {
|
|
|
- /* This icode does not exist yet. Tack it on the end of the existing */
|
|
|
- if (numIcode >= allocIcode)
|
|
|
- {
|
|
|
- allocIcode = numIcode + DELTA_ICODE; /* Make space for this one, and a few more */
|
|
|
- pc = (ICODE *)reallocVar(pc, allocIcode * sizeof(ICODE));
|
|
|
- /* It is important to clear the new icodes, to ensure that the type
|
|
|
- is set to NOT_SCANNED */
|
|
|
- memset(&pc[numIcode], 0, (size_t)(allocIcode-numIcode)*sizeof(ICODE));
|
|
|
- pl.resize(allocIcode);
|
|
|
- memset(&pl[numIcode], 0, (size_t)(allocIcode-numIcode)*sizeof(Int));
|
|
|
- }
|
|
|
- i = numIcode++;
|
|
|
- }
|
|
|
-
|
|
|
- if (pc[i].type == NOT_SCANNED)
|
|
|
- {
|
|
|
- /* This is a new icode not even scanned yet. Scan it now */
|
|
|
- /* Ignore most errors... at this stage */
|
|
|
- if (scan(pcCur, &pc[i]) == IP_OUT_OF_RANGE)
|
|
|
- {
|
|
|
- /* Something went wrong... just forget it */
|
|
|
- return -1;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return i;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-/* Set up to use the procedure proc */
|
|
|
-/* This includes some important initialisations, allocations, etc that are
|
|
|
- normally done in disassem() */
|
|
|
-static void setProc(Function * proc)
|
|
|
-{
|
|
|
- Int i;
|
|
|
-
|
|
|
- pProc = proc; /* Keep in a static */
|
|
|
-
|
|
|
- /* Free old arrays, if any */
|
|
|
- if (pc) free(pc);
|
|
|
- pl.clear();
|
|
|
-
|
|
|
-
|
|
|
- /* Create temporary code array */
|
|
|
- numIcode = pProc->Icode.GetNumIcodes();
|
|
|
- cb = numIcode * sizeof(ICODE);
|
|
|
- // Mike: needs objectising
|
|
|
- pc = (ICODE *)memcpy(allocMem(cb), pProc->Icode.GetFirstIcode(), (size_t)cb);
|
|
|
-
|
|
|
- /* Create label array to keep track of location => label name */
|
|
|
- pl.clear();
|
|
|
- pl.resize(numIcode,0);
|
|
|
-
|
|
|
- /* Bind jump offsets to labels */
|
|
|
- for (i = 0; i < numIcode; i++)
|
|
|
- {
|
|
|
- if ((pc[i].ic.ll.flg & I) && !(pc[i].ic.ll.flg & JMP_ICODE) &&
|
|
|
- JmpInst(pc[i].ic.ll.opcode))
|
|
|
- {
|
|
|
- /* Immediate jump instructions. Make dest an icode index */
|
|
|
- if (labelSrch(pc,numIcode, pc[i].ic.ll.immed.op, (Int *)&pc[i].ic.ll.immed.op))
|
|
|
- {
|
|
|
- /* This icode is the target of a jump */
|
|
|
- pc[pc[i].ic.ll.immed.op].ic.ll.flg |= TARGET;
|
|
|
- pc[i].ic.ll.flg |= JMP_ICODE; /* So its not done twice */
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- /* This jump cannot be linked to a label */
|
|
|
- pc[i].ic.ll.flg |= NO_LABEL;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /* Window initially scrolled with entry point on top */
|
|
|
- pcCur = pcTop = pProc->procEntry;
|
|
|
- labelSrch(pc,numIcode, pcCur, &icCur);
|
|
|
- /* pcLast is set properly in updateScr(), at least for now */
|
|
|
- pcLast = (dword)-1;
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
/****************************************************************************
|
|
|
* interactDis - interactive disassembler *
|
|
|
****************************************************************************/
|
|
|
void interactDis(Function * initProc, Int initIC)
|
|
|
{
|
|
|
-
|
|
|
-
|
|
|
-#ifdef __UNIX__
|
|
|
printf("Sorry - interactive disasassembler option not available for Unix\n");
|
|
|
return;
|
|
|
-#else
|
|
|
- boolT fInteract;
|
|
|
- int nEsc = 0; /* This cycles 0 1 2 for Esc [ X under Unix */
|
|
|
- /* and 0 1 for NULL X under Dos */
|
|
|
- int ch;
|
|
|
- Int i;
|
|
|
- pProc = initProc; /* Keep copy of init proc */
|
|
|
- NSCROLL = max(3, LINES >> 3); /* Number of lines to scroll */
|
|
|
-
|
|
|
- /* Allocate the position stack */
|
|
|
- posStack = (POSSTACK_ENTRY*)allocMem(256 * sizeof(POSSTACK_ENTRY));
|
|
|
- iPS = 0;
|
|
|
- memset(posStack, -1, 256 * sizeof(POSSTACK_ENTRY));
|
|
|
-
|
|
|
-
|
|
|
- /* Initialise the console interface, if required */
|
|
|
- initConsole();
|
|
|
-
|
|
|
- /* Initially, work on the given proc */
|
|
|
- setProc(initProc);
|
|
|
- if (initIC)
|
|
|
- {
|
|
|
- icCur = initIC;
|
|
|
- pcCur = pc[icCur].ic.ll.label;
|
|
|
- }
|
|
|
-
|
|
|
- /* Initialise the symbol table */
|
|
|
- createSymTables();
|
|
|
-
|
|
|
- strcpy(cbuf, "label"); /* Provide a default label string */
|
|
|
-
|
|
|
- updateScr(TRUE);
|
|
|
-
|
|
|
- fInteract = TRUE;
|
|
|
- while (fInteract)
|
|
|
- {
|
|
|
- ch = ::_getch(); // Mike: need a Unix equivalent of getch()!
|
|
|
-#ifdef __MSDOS__
|
|
|
- if (nEsc)
|
|
|
- {
|
|
|
- ch += EXT; /* Got the NULL before, so this is extended */
|
|
|
- nEsc = 0;
|
|
|
- }
|
|
|
- else if (ch == 0)
|
|
|
- {
|
|
|
- nEsc = 1; /* Got one escape (actually, NULL) char */
|
|
|
- break;
|
|
|
- }
|
|
|
-#endif
|
|
|
-#ifdef __UNIX__
|
|
|
- switch (nEsc)
|
|
|
- {
|
|
|
- case 1: /* Already got one escape */
|
|
|
- if (ch == '[')
|
|
|
- {
|
|
|
- nEsc++; /* Got 2 chars in the escape sequence */
|
|
|
- break;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- /* Escape something else. Ignore */
|
|
|
- nEsc = 0;
|
|
|
- }
|
|
|
- break;
|
|
|
- case 2:
|
|
|
- /* Already got Esc [ ... */
|
|
|
- ch += EXT; /* Make it an extended key */
|
|
|
- nEsc = 0; /* Reset the escape state */
|
|
|
- break;
|
|
|
- case 0:
|
|
|
- /* No escapes... yet */
|
|
|
- if (ch == 0x1B)
|
|
|
- {
|
|
|
- nEsc++; /* That's one escape... */
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-#endif
|
|
|
-
|
|
|
- // For consoles, we get a 0xE0 then KEY_DOWN for the normal down arrow character.
|
|
|
- // We simply ignore the 0xE0; this has the effect that the numeric keypad keys
|
|
|
- // work as well (regardless of numlock state).
|
|
|
- oldPcCur = pcCur;
|
|
|
- switch (ch)
|
|
|
- {
|
|
|
- case KEY_DOWN:
|
|
|
-
|
|
|
- if (pcCur >= pcLast) continue; /* Ignore it */
|
|
|
- pcCur += pc[icCur].ic.ll.numBytes;
|
|
|
- labelSrch(pc,numIcode, pcCur, &icCur);
|
|
|
- if (pcCur >= pcBot)
|
|
|
- {
|
|
|
- int j;
|
|
|
-
|
|
|
- /* We have gone past the bottom line. Scroll a few lines */
|
|
|
- for (j=0; j < NSCROLL; j++)
|
|
|
- {
|
|
|
- if (pcTop >= pcLast)
|
|
|
- {
|
|
|
- break;
|
|
|
- }
|
|
|
- pcTop += pc[icTop].ic.ll.numBytes;
|
|
|
- if (labelSrch(pc,numIcode, pcTop, &i))
|
|
|
- icTop = i;
|
|
|
- else break; /* Some problem... no more scroll */
|
|
|
- }
|
|
|
- }
|
|
|
- updateScr(FALSE);
|
|
|
- break;
|
|
|
-
|
|
|
- case KEY_UP:
|
|
|
- /* First simply try the prev icode */
|
|
|
- if ((icCur == 0) ||
|
|
|
- pc[--icCur].ic.ll.label + (dword)pc[icCur].ic.ll.numBytes != pcCur)
|
|
|
- {
|
|
|
- for (i = 0; i < numIcode; i++)
|
|
|
- {
|
|
|
- if (pc[i].ic.ll.label + (dword)pc[i].ic.ll.numBytes == pcCur)
|
|
|
- {
|
|
|
- break; /* This is the one! */
|
|
|
- }
|
|
|
- }
|
|
|
- if (pc[i].ic.ll.label + pc[i].ic.ll.numBytes != pcCur)
|
|
|
- break; /* Not found. Sorry! */
|
|
|
- icCur = i;
|
|
|
- }
|
|
|
- pcCur = pc[icCur].ic.ll.label;
|
|
|
- updateScr(FALSE);
|
|
|
- break;
|
|
|
-
|
|
|
-
|
|
|
- case '2': /* Think up a better key... */
|
|
|
- /* As for right arrow, but considers source operand first */
|
|
|
- if (pc[icCur].ic.ll.src.off != 0)
|
|
|
- {
|
|
|
- pushPosStack();
|
|
|
- pcCur = pc[icCur].ic.ll.src.off;
|
|
|
- if (!labelSrch(pc,numIcode, pcCur, &icCur))
|
|
|
- break;
|
|
|
- updateScr(FALSE);
|
|
|
- }
|
|
|
- /* Fall through to KEY_RIGHT processing */
|
|
|
-
|
|
|
- case KEY_RIGHT:
|
|
|
- if (pc[icCur].ic.ll.flg & I)
|
|
|
- {
|
|
|
- if ((pc[icCur].ic.ll.opcode >= iJB) &&
|
|
|
- (pc[icCur].ic.ll.opcode <= iJMPF))
|
|
|
- {
|
|
|
- /* An immediate jump op. Jump to it */
|
|
|
- pushPosStack();
|
|
|
- if (pc[icCur].ic.ll.flg & JMP_ICODE)
|
|
|
- {
|
|
|
- /* immed.op is an icode offset */
|
|
|
- icCur = pc[icCur].ic.ll.immed.op;
|
|
|
- pcCur = pc[icCur].ic.ll.label;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- /* immed.op is still an image offset.
|
|
|
- Quite likely we need to scan */
|
|
|
- pcCur = pc[icCur].ic.ll.immed.op;
|
|
|
- if ((icCur = checkScanned(pcCur)) == -1)
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- else if ((pc[icCur].ic.ll.opcode == iCALL) ||
|
|
|
- (pc[icCur].ic.ll.opcode == iCALLF))
|
|
|
- {
|
|
|
- /* The dest is a pointer to a proc struct */
|
|
|
- // First check that the procedure has icodes (e.g. may be
|
|
|
- // a library function, or just not disassembled yet)
|
|
|
- Function * pp = (Function *)pc[icCur].ic.ll.immed.op;
|
|
|
- if (pp->Icode.GetFirstIcode() != NULL)
|
|
|
- {
|
|
|
- pushPosStack();
|
|
|
- setProc(pp);
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- /* Other immediate */
|
|
|
- pushPosStack();
|
|
|
- pcCur = pc[icCur].ic.ll.immed.op;
|
|
|
- dispData(pProc->state.r[rDS]);
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- else if (pc[icCur].ic.ll.dst.off != 0)
|
|
|
- {
|
|
|
- pushPosStack();
|
|
|
- pcCur = pc[icCur].ic.ll.dst.off;
|
|
|
- if (!labelSrch(pc,numIcode, pcCur, &icCur))
|
|
|
- {
|
|
|
- dispData(pProc->state.r[rDS]);
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- else if (pc[icCur].ic.ll.src.off != 0)
|
|
|
- {
|
|
|
- pushPosStack();
|
|
|
- pcCur = pc[icCur].ic.ll.src.off;
|
|
|
- if (!labelSrch(pc,numIcode, pcCur, &icCur))
|
|
|
- {
|
|
|
- dispData(pProc->state.r[rDS]);
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- updateScr(TRUE);
|
|
|
- break;
|
|
|
-
|
|
|
- case KEY_LEFT:
|
|
|
- popPosStack();
|
|
|
- pcCur = pc[icCur].ic.ll.label;
|
|
|
- updateScr(TRUE);
|
|
|
- break;
|
|
|
-
|
|
|
-
|
|
|
- case KEY_NPAGE:
|
|
|
- pcCur = pcTop = pcBot; /* Put bottom line at top now */
|
|
|
- icCur = icTop = icBot;
|
|
|
- updateScr(FALSE);
|
|
|
- break;
|
|
|
-
|
|
|
- case KEY_PPAGE:
|
|
|
- pcTop -= (LINES-2) * 2; /* Average of 2 bytes per inst */
|
|
|
- for (i = 0; i < numIcode; i++)
|
|
|
- {
|
|
|
- if ((pc[i].ic.ll.label <= pcTop) &&
|
|
|
- (pc[i].ic.ll.label + (dword)pc[i].ic.ll.numBytes >= pcTop))
|
|
|
- {
|
|
|
- break; /* This is the spot! */
|
|
|
- }
|
|
|
- }
|
|
|
- if (i >= numIcode)
|
|
|
- {
|
|
|
- /* Something went wrong. Goto to first icode */
|
|
|
- i = 0;
|
|
|
- }
|
|
|
- icCur = icTop = i;
|
|
|
- pcCur = pcTop = pc[i].ic.ll.label;
|
|
|
- updateScr(FALSE);
|
|
|
- break;
|
|
|
-
|
|
|
- case 'l': /* Add a symbolic label here */
|
|
|
- {
|
|
|
- char *pStr;
|
|
|
-
|
|
|
- move(LINES, 0);
|
|
|
- printf("Enter symbol: ");
|
|
|
- gets(cbuf); /* Get a string to buf */
|
|
|
- move (LINES, 0);
|
|
|
- printf("%50c", ' ');
|
|
|
-
|
|
|
- if (strlen(cbuf) >= SYMLEN)
|
|
|
- {
|
|
|
- /* Name too ling. Truncate */
|
|
|
- cbuf[SYMLEN-1] = '\0';
|
|
|
- }
|
|
|
- pStr = addStrTbl(cbuf); /* Add to the string table */
|
|
|
-
|
|
|
- selectTable(Label); /* Select the label table */
|
|
|
- /* Add the symbol to both value- and symbol- hashed tables */
|
|
|
- enterSym(pStr, pcCur, pProc, TRUE);
|
|
|
-
|
|
|
- if (icCur == 0)
|
|
|
- {
|
|
|
- /* We are at the first icode of a function.
|
|
|
- Assume it is the entry point, and rename the function */
|
|
|
- strcpy(pProc->name, cbuf);
|
|
|
- }
|
|
|
-
|
|
|
- updateScr(FALSE);
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- case ';':
|
|
|
- {
|
|
|
- char *pStr;
|
|
|
- word w;
|
|
|
-
|
|
|
- if (findVal(pcCur, 0, &w))
|
|
|
- {
|
|
|
- readVal(cbuf, pcCur, 0);/* Make it the default string */
|
|
|
- deleteVal(pcCur, 0, FALSE);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- cbuf[0] = '\0'; /* Remove prev string */
|
|
|
- }
|
|
|
-
|
|
|
- /* Enter a comment here, from a window */
|
|
|
- move(LINES, 0);
|
|
|
- printf("Enter comment: ");
|
|
|
- gets(cbuf); /* Get a string to buf */
|
|
|
- move(LINES, 0);
|
|
|
- printf("%50c", ' ');
|
|
|
-
|
|
|
- pStr = addStrTbl(cbuf); /* Add to the string table */
|
|
|
-
|
|
|
- selectTable(Comment);
|
|
|
- enterSym(pStr, pcCur, pProc, FALSE);/* Add the symbol */
|
|
|
-
|
|
|
- updateScr(FALSE);
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- case 'X' & 0x1F: /* Control X; can't use Alt with Unix */
|
|
|
- fInteract = FALSE; /* Exit interactive mode */
|
|
|
- attrSet(A_NORMAL); /* Normal attributes */
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- free(posStack);
|
|
|
- destroySymTables();
|
|
|
-#endif // #ifdef unix
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-/****************************************************************************
|
|
|
- * Display the current image position as data *
|
|
|
- ****************************************************************************/
|
|
|
-static void
|
|
|
-dispData(word dataSeg)
|
|
|
-{
|
|
|
- int y, c, i;
|
|
|
- Int pc, pcStart;
|
|
|
- Int off = (Int)dataSeg << 4;
|
|
|
- char szOffset[6], szByte[4];
|
|
|
-
|
|
|
- if (pcCur >= (dword)prog.cbImage)
|
|
|
- {
|
|
|
- /* We're at an invalid address. Use 0x100 instead */
|
|
|
- pcCur = 0;
|
|
|
- }
|
|
|
- erase();
|
|
|
- dispTitle();
|
|
|
-
|
|
|
- pcStart = pc = pcCur; /* pc at start of line */
|
|
|
- for (y=1; y < LINES-1; y++)
|
|
|
- {
|
|
|
- move (y, 1);
|
|
|
- sprintf(szOffset, "%04lX ", pc);
|
|
|
- printfd(szOffset);
|
|
|
- for (i=0; i < 16; i++)
|
|
|
- {
|
|
|
- sprintf(szByte, "%02X ", prog.Image[pc++ + off]);
|
|
|
- printfd(szByte);
|
|
|
- if ((pc + off) > prog.cbImage) break;
|
|
|
- }
|
|
|
- pc = pcStart;
|
|
|
- for (i=0; i < 16; i++)
|
|
|
- {
|
|
|
- c = prog.Image[pc++ + off];
|
|
|
- if ((c < 0x20) || (c > 0x7E))
|
|
|
- {
|
|
|
- c = '.';
|
|
|
- }
|
|
|
- szByte[0] = (char)c;
|
|
|
- szByte[1] = '\0';
|
|
|
- printfd(szByte);
|
|
|
- if ((pc + off) > prog.cbImage) break;
|
|
|
- }
|
|
|
- dis_newline();
|
|
|
- pcStart = pc;
|
|
|
-
|
|
|
- if ((pc + off) > prog.cbImage) break;
|
|
|
-
|
|
|
- /* getyx(stdscr, y, x); */
|
|
|
- }
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-boolT callArg(word off, char *sym)
|
|
|
-{
|
|
|
- dword imageOff;
|
|
|
-
|
|
|
- imageOff = off + ((dword)pProc->state.r[rCS] << 4);
|
|
|
- /* Search procedure list for one with appropriate entry point */
|
|
|
- FunctionListType::iterator iter= std::find_if(pProcList.begin(),pProcList.end(),
|
|
|
- [imageOff](const Function &f) -> bool { return f.procEntry==imageOff; });
|
|
|
- if(iter==pProcList.end())
|
|
|
- {
|
|
|
- /* No existing proc entry */
|
|
|
- //ERROR: dereferencing NULL !?!
|
|
|
- //LibCheck(*iter);
|
|
|
- Function *x=Function::Create();
|
|
|
- x->procEntry=imageOff;
|
|
|
- LibCheck(*x);
|
|
|
- if (x->flg & PROC_ISLIB)
|
|
|
- {
|
|
|
- /* No entry for this proc, but it is a library function.
|
|
|
- Create an entry for it */
|
|
|
- pProcList.push_back(x);
|
|
|
- iter = (++pProcList.rbegin()).base();
|
|
|
- }
|
|
|
- }
|
|
|
- if(iter==pProcList.end())
|
|
|
- return false;
|
|
|
- /* We have a proc entry for this procedure. Copy the name */
|
|
|
- strcpy(sym, iter->name);
|
|
|
- return true;
|
|
|
}
|
|
|
|
|
|
/* Handle the floating point opcodes (icode iESC) */
|