num = (LW << 22) | (atoi (arg0) << 19) |
(atoi (arg1) << 16) | addressField;
} else {
num = (SW << 22) | (atoi (arg0) << 19) |
(atoi (arg1) << 16) | addressField;
}
}
} else if (! strcmp (opcode,". fill")) {
if (! isNumber (arg0)) {
num = translateSymbol (labelArray, labelAddress, numLabels,
arg0);
} else {
num = atoi (arg0);
}
}
/* printf (" (address %d): %d (hex 0x%x) \n", address, num, num); */
fprintf (outFilePtr, "%d\n", num);
}
exit (0);
}
/*
* Read andf parse a line of the assembly-language file. Fields are returned
* in label, opcode, arg0, arg1, arg2 (these strings must have memory already
* allocated to them).
*
* Return values:
* 0 if reached end of file
* 1 if all went well
*
* exit (1) if line is too long.
*/
int readandfParse (FILE *inFilePtr, char *label, char *opcode, char *arg0,char *arg1, char *arg2)
{
char line [MAXLINELENGTH];
char *ptr = line;
/* delete prior values */
label [0] = opcode [0] = arg0 [0] = arg1 [0] = arg2 [0] = '\0';
/* read the line from the assembly-language file */
if (fgets (line, MAXLINELENGTH, inFilePtr) == NULL) {
/* reached end of file */
return (0);
}
/* check for line too long */
if (strlen (line) == MAXLINELENGTH-1) {
printf ("error: line too long\n");
exit (1);
}
/* is there a label? */
ptr = line;
if (sscanf (ptr, "% [^\t\n]", label)) {
/* successfully read label; advance pointer over the label */
ptr += strlen (label);
}
/*
* Parse the rest of the line. Would be nice to have real regular
* expressions, but scanf will suffice.
*/
sscanf (ptr, "%* [\t\n\r] % [^\t\n\r] %* [\t\n\r] % [^\t\n\r] %* [\t\n\r] % [^\t\n\r] %* [\t\n\r] % [^\t\n\r] ",
opcode, arg0, arg1, arg2);
return (1);
}
int translateSymbol (char labelArray [MAXNUMLABELS] [MAXLABELLENGTH],
int labelAddress [MAXNUMLABELS], int numLabels, char *symbol)
{
int i;
/* search through address label table */
for (i=0; i<numLabels && strcmp (symbol, labelArray [i]); i++) {
}
if (i>=numLabels) {
printf ("error: missing label %s\n", symbol);
exit (1);
}
return (labelAddress [i]);
}
int isNumber (char *string)
{
/* return 1 if string is a number */
int i;
return ( (sscanf (string, "%d", &i)) == 1);
}
/* Test register argument; make sure it's in range andf has no bad characters. */
void testRegArg (char *arg)
{
int num;
char c;
if (atoi (arg) < 0 || atoi (arg) > 7) {
printf ("error: register out of range\n");
exit (2);
}
if (sscanf (arg, "%d%c", &num, &c)! = 1) {
printf ("bad character in register argument\n");
exit (2);
}
}
/* Test addressField argument. */
void testAddrArg (char *arg)
{
int num;
char c;
/* test numeric addressField */
if (isNumber (arg)) {
if (sscanf (arg, "%d%c", &num, &c)! = 1) {
printf ("bad character in addressField\n");
exit (2);
}
}
}
Додаток II (код симулятора)
/*Instruction-level simulator for the LC */
#include <stdio. h>
#include <stdlib. h>
#include <string>
#include <math. h>
#include <vector>
using namespace std;
#define NUMMEMORY 65536 /* maximum number of words in memory */
#define NUMREGS 8 /* number of machine registers */
#define MAXLINELENGTH 1000
#define STACKDEPTH 32
#define ADD 0
#define NAND 1
#define LW 2
#define SW 3
#define BEQ 4
#define JALR 5
#define HALT 6
#define NOOP 7
#define div 8
#define imul 9
#define xidiv 10
#define andf 11
#define xorf 12
#define cmpge 13
#define jmae 14
#define jmnae 15
#define bsf 16
#define bsr 17
#define jne 18
#define push 19
#define pop 20
typedef struct stateStruct {
int pc;
int mem [NUMMEMORY];
int reg [NUMREGS];
int numMemory;
vector <int> sStack;
int ZF;
} stateType;
void printState (stateType *);
void run (stateType);
int convertNum (int);
int main (int argc, char *argv [])
{
int i;
char line [MAXLINELENGTH];
stateType state;
FILE *filePtr;
if (argc! = 2) {
printf ("error: usage: %s <machine-code file>\n", argv [0]);
exit (1);
}
/* initialize memories and registers */
for (i=0; i<NUMMEMORY; i++) {
state. mem [i] = 0;
}
for (i=0; i<NUMREGS; i++) {
state. reg [i] = 0;
}
state. ZF=0;
state. pc=0;
/* read machine-code file into instruction/data memory (starting at
address 0) */
filePtr = fopen (argv [1], "r");
if (filePtr == NULL) {
printf ("error: can't open file %s\n", argv [1]);
perror ("fopen");
exit (1);
}
for (state. numMemory=0; fgets (line, MAXLINELENGTH, filePtr)! = NULL;
state. numMemory++) {
if (state. numMemory >= NUMMEMORY) {
printf ("exceeded memory size\n");
exit (1);
}
if (sscanf (line, "%d", state. mem+state. numMemory)! = 1) {
printf ("error in reading address %d\n", state. numMemory);
exit (1);
}
printf ("memory [%d] =%d\n", state. numMemory, state. mem [state. numMemory]);
}
printf ("\n");
/* run never returns */
run (state);
return (0);
}
void run (stateType state)
{
int i;
int arg0, arg1, arg2, addressField;
int instructions=0;
int opcode;
int maxMem=-1; /* highest memory address touched during run */
for (; 1; instructions++) { /* infinite loop, exits when it executes halt */
printState (&state);
if (state. pc < 0 || state. pc >= NUMMEMORY) {
printf ("pc went out of the memory range\n");
exit (1);
}
maxMem = (state. pc > maxMem)? state. pc: maxMem;
/* this is to make the following code easier to read */
opcode = state. mem [state. pc] >> 22;
arg0 = (state. mem [state. pc] >> 19) & 0x7;
arg1 = (state. mem [state. pc] >> 16) & 0x7;
arg2 = state. mem [state. pc] & 0x7; /* only for add, nand */
addressField = convertNum (state. mem [state. pc] & 0xFFFF); /* for beq,
lw, sw */
state. pc++;
if (opcode == ADD) {
state. reg [arg2] = state. reg [arg0] + state. reg [arg1];
} else if (opcode == NAND) {
state. reg [arg2] = ~ (state. reg [arg0] & state. reg [arg1]);
} else if (opcode == LW) {
if (state. reg [arg0] + addressField < 0 ||
state. reg [arg0] + addressField >= NUMMEMORY) {
printf ("address out of bounds\n");
exit (1);
}
state. reg [arg1] = state. mem [state. reg [arg0] + addressField];
if (state. reg [arg0] + addressField > maxMem) {
maxMem = state. reg [arg0] + addressField;
}
} else if (opcode == SW) {
if (state. reg [arg0] + addressField < 0 ||
state. reg [arg0] + addressField >= NUMMEMORY) {
printf ("address out of bounds\n");
exit (1);
}
state. mem [state. reg [arg0] + addressField] = state. reg [arg1];
if (state. reg [arg0] + addressField > maxMem) {
maxMem = state. reg [arg0] + addressField;
}
} else if (opcode == BEQ) {
if (state. reg [arg0] == state. reg [arg1]) {
state. pc += addressField;
}
} else if (opcode == JALR) {
state. reg [arg1] = state. pc;
if (arg0! = 0)
state. pc = state. reg [arg0];
else
state. pc = 0;
} else if (opcode == NOOP) {
} else if (opcode == HALT) {
printf ("machine halted\n");
printf ("total of %d instructions executed\n", instructions+1);
printf ("final state of machine: \n");
printState (&state);
exit (0);
} else if (opcode == xidiv) {
state. reg [arg2] = state. reg [arg0] / state. reg [arg1];
state. reg [arg0] ^=state. reg [arg1] ^=state. reg [arg0] ^=state. reg [arg1];
} else if (opcode == div) {
state. reg [arg2] = (unsigned) state. reg [arg0] / (unsigned) state. reg [arg1];
} else if (opcode == imul) {
state. reg [arg2] = state. reg [arg0] * state. reg [arg1];
} else if (opcode == andf) {
state. reg [arg2] = state. reg [arg0] & state. reg [arg1];
} else if (opcode == xorf) {
state. reg [arg2] = state. reg [arg0] xor state. reg [arg1];
} else if (opcode == cmpge) {
state. reg [arg2] = state. reg [arg0] >= state. reg [arg1];
} else if (opcode == jmae) {
if ( (unsigned) state. reg [arg0] >= (unsigned) state. reg [arg1])
state. pc += addressField;
} else if (opcode == jmnae) {
if ( (unsigned) state. reg [arg0] < (unsigned) state. reg [arg1])
state. pc += addressField;
} else if (opcode == bsf) {
state. ZF=0;
for (i=0; i<31; i++) {
if (state. reg [arg0] %2==1) {
state. ZF=1;
state. reg [arg1] =i;
break;
}
else {
state. reg [arg0] =state. reg [arg0] >>1;
}
}
} else if (opcode == bsr) {
state. ZF=0;
for (i=31; i>0; i--) {
if (state. reg [arg0] /0x80000000==1) {
state. ZF=1;
state. reg [arg1] =i;
break;
}
else {
state. reg [arg0] =state. reg [arg0] <<1;
}
}
} else if (opcode == jne) {
if (state. ZF! =0) state. pc = addressField;
} else if (opcode == push) {
if (state. sStack. size () > STACKDEPTH - 1)
{
printf ("\nerror: stack overflow! 0x%x\n", opcode);
printf ("total of %d instructions executed\n", instructions+1);
printf ("final state of machine: \n");
printState (&state);
exit (1);
}
else state. sStack. push_back (state. reg [1]);
} else if (opcode == pop) {
if (state. sStack. empty ())
{
printf ("\nerror: stack underflow! 0x%x\n", opcode);
printf ("total of %d instructions executed\n", instructions+1);
printf ("final state of machine: \n");
printState (&state);
exit (1);
}
else
{
state. reg [1] = state. sStack. back ();
state. sStack. pop_back ();
}
} else {
printf ("error: illegal opcode 0x%x\n", opcode);
exit (1);
}
state. reg [0] = 0;
}
}
void
printState (stateType *statePtr)
{
int i;
printf ("\n@@@\nstate: \n");
printf ("\tpc %d\n", statePtr->pc);
printf ("\t\tZF = %d\n",statePtr->ZF);
vector <int>:: iterator stackiter;
printf ("\tstack: \n");
for (stackiter = statePtr->sStack. begin (), i = 0; stackiter < statePtr->sStack. end (); stackiter++, i++) {
printf ("\t\tstek [%d] %d\n", i, *stackiter);
}
printf ("\tmemory: \n");
for (i=0; i<statePtr->numMemory; i++) {
printf ("\t\tmem [%d] %d\n", i, statePtr->mem [i]);
}
printf ("\tregisters: \n");
for (i=0; i<NUMREGS; i++) {
printf ("\t\treg [%d] %d\n", i, statePtr->reg [i]);
}
printf ("end state\n");
}
int convertNum (int num)
{
/* convert a 16-bit number into a 32-bit Sun integer */
if (num & (1<<15)) {
num - = (1<<16);
}
return (num);
}