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

📄 pcode.c

📁 一个嵌入式系统的C代码
💻 C
字号:
/***************************************************************************
 * PCODE.C - P-Code interpereter modeled after a Pascal version by Kin-Man *
 *	     Chung and Herbert Yuen from their October 1978 BYTE article,  *
 *	     'A "Tiny" Pascal Compiler - Part 1: The p_code Interpereter'. *
 * History:								   *
 *   19-DEC-92	First MSC version			     Ron Chernich  *
 *   23-DEC-92	Disassembler and help added		     arcy	   *
 *   25-DEC-92	Debugger made more usefull for development   arcy	   *
 *    3-JAN-93	Default pcode file extension to ".PCD"	     arcy	   *
 **************************************************************************/


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


#define VERS	    1.12

#define FALSE	    0
#define TRUE	    1

#define ULIM	    15
#define BPLIM	    5
#define SIZE	    500
#define SIZE1	    480
#define BUFSIZE     1024

typedef unsigned char BYTE;
typedef unsigned int  BOOL;

enum opcodes
  {LIT, OPR, LOD, STO, CAL, INT, JMP,
   JPC, CSP, LODX = 0x12, STOX = 0x13, ILLEGAL_PCD};

enum operargs
  {_RET, _NEG, _ADD, _SUB, _MUL, _DIV, _LOW, _MOD, _EQ,
   _NE, _LT, _GE, _GT, _LE, _OR, _AND, _XOR, _NOT, _SHL,
   _SHR, _INC, _DEC, _CPY, ILLEGAL_OPR_ARG};

enum cspargs
    {CHIN, CHOUT, NUMIN, NUMOUT, HEXIN, HEXOUT, STROUT=8, ILLEGAL_CSP_ARG};

/****************
* Globals...
*/
BOOL bStop;
BYTE MEM[BUFSIZE];
int  ip, bp, sp, nBreaks, ipx, TrPtr, nStep;
int  Stack[SIZE], Trace[ULIM], Bpoints[BPLIM];

/*************
* Protos..
*/
int  Base (int);
void Init (void);
void Exec (void);
void DeCode (int, int);
void CkBp (void);
int  LoadPcode(char*);
void ShowHelp (void);
void Disemble (int);
void Debug (void);
void main (int, char**);


/************************************************************************
* Backs up the stack by the passed number of "levels"
* RETURNS: value at current stack - <nLev> levels
*/
int Base (int nLevs)
{
  int nVal = bp;

  while (nLevs--)
    nVal = Stack[nVal];
  return(nVal);
}

/************
* Initialize the P machine
*/
void Init (void)
{
  int i;

  TrPtr = ULIM;
  bp = 1;
  bStop = FALSE;
  sp = ipx = ip = nStep = 0;
  Stack[0] = Stack[1] = 0;
  Stack[2] = -1;
  for (i = 0; i < ULIM; i++)
    Trace[i] = -1;
}

/******************
* Execute a P-Code
*/
void Exec (void)
{
  BYTE *p;
  int  wParam, bParam, Func, idx;

  p = MEM + (ip << 2);
  bParam = *(p+1);
  wParam = (*(p+3) << 8) + *(p+2);
  if (++TrPtr >= ULIM)
    TrPtr = 0;
  Trace[TrPtr] = ip;
  ++ip;
  ipx = ip;
  ++nStep;
  Func = *p;
  if (Func <= CSP)
    idx = 0;
  else {
    idx = 1;
    Func -= 0x10;
  }
  switch (Func) {
    case LIT:
      ++sp;
      Stack[sp] = wParam;
      break;
    case OPR:
      switch (wParam) {
	case _RET:
	  sp = bp - 1;
	  bp = Stack[sp+2];
	  ip = Stack[sp+3];
	  break;
	case _NEG:
	  Stack[sp] = -Stack[sp];
	  break;
	case _ADD:
	  --sp;
	  Stack[sp] += Stack[sp+1];
	  break;
	case _SUB:
	  --sp;
	  Stack[sp] -= Stack[sp+1];
	  break;
	case _MUL:
	  --sp;
	  Stack[sp] *= Stack[sp+1];
	  break;
	case _DIV:
	  --sp;
	  Stack[sp] /= Stack[sp+1];
	  break;
	case _LOW:
	  Stack[sp] &= 1;
	  break;
	case _MOD:
	  --sp;
	  Stack[sp] %= Stack[sp+1];
	  break;
	case _EQ:
	  --sp;
	  Stack[sp] = (Stack[sp] == Stack[sp+1]);
	  break;
	case _NE:
	  --sp;
	  Stack[sp] = (Stack[sp] != Stack[sp+1]);
	  break;
	case _LT:
	  --sp;
	  Stack[sp] = (Stack[sp] < Stack[sp+1]);
	  break;
	case _GE:
	  --sp;
	  Stack[sp] = (Stack[sp] >= Stack[sp+1]);
	  break;
	case _GT:
	  --sp;
	  Stack[sp] = (Stack[sp] > Stack[sp+1]);
	  break;
	case _LE:
	  --sp;
	  Stack[sp] = (Stack[sp] <= Stack[sp+1]);
	  break;
	case _OR:
	  --sp;
	  Stack[sp] |= Stack[sp+1];
	  break;
	case _AND:
	  --sp;
	  Stack[sp] &= Stack[sp+1];
	  break;
	case _XOR:
	  --sp;
	  Stack[sp] ^= Stack[sp+1];
	  break;
	case _NOT:
	  Stack[sp] = ~Stack[sp];
	  break;
	case _SHL:
	  --sp;
	  Stack[sp] <<= Stack[sp+1];
	  break;
	case _SHR:
	  --sp;
	  Stack[sp] >>= Stack[sp+1];
	  break;
	case _INC:
	  ++Stack[sp];
	  break;
	case _DEC:
	  --Stack[sp];
	  break;
	case _CPY:
	  ++sp;
	  Stack[sp] = Stack[sp-1];
	  break;
	default:
	  fprintf(stdout, "Illegal Opr\n");
	  bStop = TRUE;
	  break;
      }
      break;
    case LOD:
      if (bParam == 255)
	Stack[sp] = MEM[Stack[sp]];
      else {
	if (idx)
	  wParam = wParam + Stack[sp];
	sp += (1 - idx);
	Stack[sp] = Stack[Base(bParam)+wParam];
      }
      break;
    case STO:
      if (bParam == 255) {
	MEM[Stack[sp-1]] = Stack[sp];
	sp -= 2;
      }
      else {
	if (idx)
	  wParam += Stack[sp-1];
	Stack[Base(bParam)+wParam] = Stack[sp];
	sp -= (idx + 1);
      }
      break;
    case CAL:
      if (bParam == 255) {
	/*CAL(Stack[sp]);*/
	--sp;
      }
      else {
	Stack[sp+1] = Base(bParam);
	Stack[sp+2] = bp;
	Stack[sp+3] = ip;
	bp = sp + 1;
	ip = wParam;
      }
      break;
    case INT:
      if (sp < SIZE1 - wParam)
	sp += wParam;
      else {
	fprintf(stdout, "Stack Overflow!\n");
	bStop = TRUE;
      }
      break;
    case JMP:
      ip = wParam;
      break;
    case JPC:
      if (Stack[sp] == (int)*(p+1))
	ip = wParam;
	--sp;
      break;
    case CSP:
      switch (wParam) {
	case 0:
	  ++sp;					  /* read CHAR */
	  fscanf(stdin, "%c", &Stack[sp]);
	  break;
	case 1:
	  fprintf(stdout, "%c", Stack[sp]);	   /* write CHAR */
	  --sp;
	  break;
	case 2:
	  ++sp;					  /* read NUMBER */
	  fscanf(stdin, "%d", &Stack[sp]);
	  break;
	case 3:
	  fprintf(stdout, " %d", Stack[sp]);	   /* write NUMBER */
	  --sp;
	  break;
	case 4:
	  ++sp;					   /* read HEX */
	  fscanf(stdin, "%x", &Stack[sp]);
	  break;
	case 5:
	  fprintf(stdout, " %X", Stack[sp]);	   /* write HEX */
	  --sp;
	  break;
	case 8:
	  idx = sp - Stack[sp];			   /* write STRING */
	  while (idx <= (sp - 1))
	    fprintf(stdout, "%c", Stack[idx++]);
	  sp -= (Stack[sp] + 1);
	  break;
	default:
	  fprintf(stdout, "Illegal CSP\n");
	  bStop = TRUE;
	  break;
      }
      break;
    default:
      fprintf(stdout, "Illegal OPCODE\n");
      bStop = TRUE;
      break;
  }
}

/******************
* Decode and display the opcode at the passed address and its args.
*/
void DeCode (int pc, int bNln)
{
  BYTE *p;
  int  m, k, *pw;
  unsigned int *pa;
  char st[24], *str;
  static char *stMn[] =
    {"LIT ","OPR ","LOD ","STO ","CAL ","INT ","JMP ",
     "JPC ","CSP ","LODX","STOX","????"};
  static char *OPRarg[] =
    {"RET", "NEG", "ADD", "SUB", "MUL",
     "DIV", "LOW", "MOD", "EQ", "NE", "LT",
     "GE", "GT", "LE", "OR", "AND", "XOR",
     "NOT", "SHL", "SHR", "INC", "DEC", "CPY", "???"};
  static char *CSParg[] =
    {"INCH", "OUTCH", "INNM", "OUTNM", "INHX", "OUTHX",
     "", "", "OUTST", "????"};

  str = st + 14;
  p = MEM + (pc << 2);
  pw = (int*)(MEM + (pc << 2) + 2);
  pa = (unsigned int*)(MEM + (pc << 2) + 2);
  if ((*p >= LIT) && (*p <= CSP))
    k = *p;
  else if ((*p == LODX) || (*p == STOX))
    k = *p - 9;
  else
    k = ILLEGAL_PCD;
  sprintf(st, "%4d: %s %2X,", pc, stMn[k], *(p+1));
  switch (k) {
    case OPR:
      m = (((*pa >= _RET) && (*pa <= _CPY)) ? *pw : ILLEGAL_OPR_ARG);
      sprintf(str, "%s", OPRarg[m]);
      break;
    case CSP:
      m = (((*pa == STROUT) || ((*pa >= CHIN) && (*pa <= HEXOUT))) ? *pw :
	    ILLEGAL_CSP_ARG);
      sprintf(str, "%s", CSParg[m]);
      break;
    default:
      if ((k == LIT) && (*pw > 0))
	sprintf(str, "0x%02X ", *pw);
      else
	sprintf(str, "%2d", *pw);
      break;
  }
  if (bNln)
    fprintf(stdout, "%s\n", st);
  else {
    while (strlen(st) < 20)
      strcat(st, " ");
      fprintf(stdout, st);
  }
}

/***********************
* Look for a Break point at the current <ip> address
*/
void CkBp (void)
{
  int i;

  if (ip < 0)
    bStop = TRUE;
  else
    for (i = 0; i < nBreaks; i++)
      if (Bpoints[i] == ip) {
	fprintf(stdout, "\nBreak at %d!\n", ip);
	bStop = TRUE;
	break;
      }
}

/************
* load some p-codes (hopefully) from the passed file.  If no extension
* given, default it to ".PCD"
*/
int LoadPcode(char *st)
{
  FILE *fp;
  char *cp;
  int  cnt = 0;

  if ((strrchr(st, '.') == NULL) ||
    (((cp = strrchr(st, '.')) != NULL) && (strchr(cp, '\\') == NULL)))
      strcat(st, ".PCD");
  if (fp = fopen(st, "r")) {
    cnt = fread(MEM, sizeof(BYTE), BUFSIZE, fp);
    fclose(fp);
  }
  return(cnt);
}

/**********
* available commands..
*/
void ShowHelp (void)
{
  int i;
  static char *stHelp[] =
    {"Commands:","G: Go (resume)","S: Single Step",
     "R: Reset","B: Set break-point","C: Clear all break-points",
     "Y: Display break-points","X: Examine status","K: Show stack",
     "L: List p-codes", "T: Trace back", "E: Examine memory",
     "U: Backup PC", "N: Increment PC","Q: Quit program",
     "?: Display help (this!)",
     " ", NULL};

  for (i = 0; stHelp[i]; i++)
    fprintf(stdout, ((i) ? "  %s\n" : "%s\n"), stHelp[i]);
}

/**********
* disassemble to standard out, 4 pcodes per line..
*/
void Disemble(int cnt)
{
  int n = 0;

  while (n < cnt)
    if ((n+1)%4)
      DeCode(n++, FALSE);
    else
      DeCode(n++, TRUE);
}

/*********
* The simple (VERY) interactive p-code debugger..
*/
void Debug (void)
{
  int i, j, k = 0;
  char st[32], Cmd, *cp;

  ShowHelp();
  nBreaks = 0;
  DeCode(ip, TRUE);
  while (ip >= 0) {
    fprintf(stdout, ">");
    fflush(stdin);
    fgets(st, 32, stdin);
    if (islower(*st))
      Cmd = toupper(st[0]);
    else
      Cmd = st[0];
    cp = st+1;
    while (*cp && (*cp == ' '))
      ++cp;
    strcpy(st, cp);
    if (cp = strchr(st, '\n'))
      *cp = '\0';
    switch (Cmd) {
      case 'G': bStop = FALSE;
		while (!bStop) {
		  if (bp < 0) {
		    bStop = TRUE;
		    fprintf(stderr, "\nHalt!\n");
		  }
		  else {
		    Exec();
		    CkBp();
		  }
		}
		break;
      case 'S': Exec(); 	  /* note fall-thru to show pcode and regs */
      case 'X': DeCode(ip, TRUE);
		fprintf(stdout, "  IP = %04d  SP = %04d  BP = %d", ip,sp,bp);
		fprintf(stdout, "  Stack[sp] = %04d  Stack[sp-1] = %04d\n",
		  Stack[sp], Stack[sp-1]);
		break;
      case 'R': Init();
		break;
      case 'T': fprintf(stdout, "* TRACE *\n");
		for (i = 0; i < ULIM; i++) {
		  if (++TrPtr >= ULIM)
		    TrPtr = 0;
		  if (Trace[TrPtr] >= 0)
		    DeCode(Trace[TrPtr], TRUE);
		}
		break;
      case 'K': if (!isdigit(*st)) {
		  fprintf(stderr, "Stack offset? ");
		  fgets(st, 16, stdin);
		  if (cp = strchr(st, '\n'))
		    *cp = '\0';
		}
		i = ((strlen(st)) ? atoi(st) : sp+4);
		if (_toupper(st[1]) == 'P')
		  if (_toupper(*st) == 'S')
		    i = sp;
		  else if (_toupper(*st) == 'B')
		    i = bp;
		if (i == 0)
		  i = sp+8;
		if ((j = i-16) < 0)
		  j = 0;
		while (i >= j) {
		  if (i == sp)
		    fprintf(stderr, "%04d: %4d <-- sp\n", i, Stack[i]);
		  else if (i == bp)
		    fprintf(stderr, "%04d: %4d <-- bp\n", i, Stack[i]);
		  else
		    fprintf(stderr, "%04d: %4d\n", i, Stack[i]);
		  --i;
		}
		break;
      case 'L': if (!isdigit(*st)) {
		  fprintf(stderr, "IP offset? ");
		  fgets(st, 16, stdin);
		  if (cp = strchr(st, '\n'))
		    *cp = '\0';
		}
		if (strlen(st) == 0)
		  i = k;
		else
		  if ((_toupper(st[0]) == 'I') && (_toupper(st[1]) == 'P'))
		    i = ip;
		  else
		    i = atoi(st);
		for (j = i; j < i + 16; j++)
		  if (j != ip)
		    DeCode(j, TRUE);
		  else {
		    DeCode(j, FALSE);
		    fprintf(stderr, " <-- ip\n");
		  }
		k = j;
		break;
      case 'B': if (nBreaks < BPLIM) {
		  if (isdigit(*st)) {
		    Bpoints[nBreaks] = atoi(st);
		    fprintf(stderr, "%d: %d\n", nBreaks+1, Bpoints[nBreaks]);
		  }
		  else {
		    fprintf(stdout, "%d: ", nBreaks+1);
		    fscanf(stdin, "%d", &Bpoints[nBreaks]);
		  }
		  ++nBreaks;
		}
		break;
      case 'C': nBreaks = 0;
		fprintf(stdout, "\n");
		break;
      case 'Y': for (i = 0; i < nBreaks; i++)
		  fprintf(stdout, "%d:  %4d\n", i+1, Bpoints[i]);
		break;
      case 'E': if (!isdigit(*st)) {
		  fprintf(stderr, "PC? ");
		  fgets(st, 16, stdin);
		  if (cp = strchr(st, '\n'))
		    *cp = '\0';
		}
		ipx = atoi(st);
		DeCode(ipx, TRUE);
		break;
      case 'U': if (ipx > 0) {
		  --ipx;
		  DeCode(ipx, TRUE);
		}
		break;
      case 'N': ++ipx;
		DeCode(ipx, TRUE);
		break;
      case 'Q': ip = -1;
		break;
      case '?': ShowHelp();
		break;
      default:	fprintf(stdout, "??\n");
		break;
    }
  }
  fprintf(stdout, "%d instructions executed\n", nStep);
}


/****************************
* Main P-Code Intwerpreter..
*/
void main (int argc, char **argv)
{
  int Pcnt = 0;
  int bDump, bMonitor;

  fprintf(stdout, "\nP-Code Intwerpreter V%.2f\n\n", VERS);
  bDump = bMonitor = FALSE;
  if (argc == 1)
    fprintf(stdout, "Usage:\n  pcode [-d|m] <filename>\n");
  while (--argc)
    if (*argv[argc] != '-')
      Pcnt = LoadPcode(argv[1]);
    else {
      if ((argv[argc][1] == 'd') || (argv[argc][1] == 'D'))
	bDump = TRUE;
      if ((argv[argc][1] == 'm') || (argv[argc][1] == 'M'))
	bMonitor = TRUE;
    }
  if (Pcnt == 0)
    fprintf(stderr, "File not found, or empty!\n");
  else {
    Init();
    if (bDump)
      Disemble(Pcnt >> 2);
    if (bMonitor)
      Debug();
    if (!(bDump || bMonitor))
     while (bp >= 0)
       Exec();
  }
}


/********************************* EOF *********************************/

⌨️ 快捷键说明

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