- UID
- 852722
|
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/* Instruction Set */
#define LOADA 0X00
#define LOADB 0X01
#define LOADAI 0X02
#define LOADBI 0X03
#define NOP 0X04
#define STOREA 0X05
#define STOREB 0X06
#define ADDA 0X07
#define ADDB 0X08
#define COMPAI 0X09
#define COMPBI 0X0A
#define BLT 0X0B
#define BGT 0X0C
#define JUMP 0X0D
#define PRINTA 0X0E
#define BREAK 0x0F
#define MAX_LINE 1024
#define FALSE 0
#define TRUE (!FALSE)
#define ADDRESS_LENGTH 2
#define IMMEDIATE_LENGTH 1
#define ADDRESS_SPACE 65536
typedef enum {NONE, IMMEDIATE, ADDRESS}OPERAND_TYPE;
typedef int BOOL;
typedef struct
{
char* InstructionName;
OPERAND_TYPE Operand;
unsigned char MachineCode;
} INSTRUCTION;
static INSTRUCTION InstructionTable[] ={"LOADA", ADDRESS, LOADA,
"LOADB", ADDRESS, LOADB,
"LOADAI", IMMEDIATE, LOADAI,
"LOADBI", IMMEDIATE, LOADBI,
"NOP", NONE, NOP,
"STOREA", ADDRESS, STOREA,
"STOREB", ADDRESS, STOREB,
"ADDA", IMMEDIATE, ADDA,
"ADDB", IMMEDIATE,ADDB,
"COMPAI", IMMEDIATE, COMPAI,
"COMPBI", IMMEDIATE, COMPBI,
"BLT", ADDRESS, BLT,
"BGT", ADDRESS, BGT,
"JUMP", ADDRESS, JUMP,
"PRINTA", NONE, PRINTA,
"BREAK", NONE, BREAK };
typedef struct
{
char*Symbol;
int MemLocation;
int Line;
} SYMTAB_ENTRY;
typedef struct
{
SYMTAB_ENTRY Entry[1024];
int Count;
} SYM_T;
typedef struct
{
unsigned int RegA;
unsigned int RegB;
unsigned int PC;
int SR;
} REGISTERS;
INSTRUCTION* FindInstruction (char* Token)
{
int i = 0;
INSTRUCTION* Entry = NULL;
for (i = 0; i < sizeof InstructionTable / sizeof InstructionTable[0];i++)
{
if (0 == strcmp (InstructionTable[i].InstructionName, Token))
{
Entry = &InstructionTable[i];
}
}
return Entry;
}
void InsertSymbol (char* Token, intMemLocation, SYM_T* SymTable)
{
SYMTAB_ENTRY* Entry;
Entry = &SymTable->Entry[SymTable->Count];
/*perform equivalent of strdup */
Entry->Symbol = malloc (strlen(Token) + 1);
if(NULL != Entry->Symbol)
{
strcpy (Entry->Symbol, Token);
}
SymTable->Count++;
Entry->MemLocation = MemLocation;
}
SYMTAB_ENTRY* FindSymbol (SYM_T*SymbolTable, char* Symbol)
{
int i = 0;
SYMTAB_ENTRY* Entry = NULL;
for (i=0; i< SymbolTable->Count; i++)
{
if (0 == strcmp (SymbolTable->Entry[i].Symbol, Symbol))
{
Entry = &SymbolTable->Entry[i];
break;
}
}
return Entry;
}
void ReadAssembly (char* Memory, intMemLocation, char* FileName)
{
FILE* Fp = NULL;
char Line[MAX_LINE] = {0};
int LineNo = 0;
char* Token = NULL;
char Seps[] = " ,\t\n";
SYM_T SymbolTable = {0};
BOOL IsOk = TRUE;
INSTRUCTION* Instruction = NULL;
SYMTAB_ENTRY* Symbol = NULL;
Fp= fopen ( FileName, "r" );
if( NULL == Fp )
{
fprintf( stderr, "cannot open file %s\n", FileName );
IsOk= FALSE;
}
/*go through each line */
while (IsOk && NULL != fgets (Line, MAX_LINE, Fp ))
{
LineNo++;
if ( '*' == Line[0] || '#' == Line[0] || '\n' == Line[0] )
{
/* discard comments */
continue;
}
/* parse the line */
Token = strtok (Line, Seps);
if (NULL == Token)
{
continue;
}
/* check to see if this a label, if so then add to the symbol table */
if (':' == Token[0])
{
Token++;
InsertSymbol (Token, MemLocation, &SymbolTable);
}
else
{
/* assemble the token into memory */
Instruction = FindInstruction (Token);
if (NULL == Instruction)
{
printf ("Error at line %d; Do not recognise instruction %s\n",
LineNo, Token);
IsOk = FALSE;
}
else
{
Memory [MemLocation] = Instruction->MachineCode;
MemLocation++;
if (IMMEDIATE == Instruction->Operand ||
ADDRESS ==Instruction->Operand)
{
/* Get the operand */
Token = strtok (NULL, Seps);
if (NULL == Token)
{
printf("Error\n");
break;
}
}
/* We need to put one extra byte into memory */
if ( IMMEDIATE == Instruction->Operand)
{
Memory [MemLocation] = (unsignedchar) strtol (Token, NULL, 16);
MemLocation++;
}
/* We need to put two extra bytes into memory */
if ( ADDRESS == Instruction->Operand)
{
Symbol = FindSymbol(&SymbolTable, Token);
/* make sure Symbol has alreadybeen defined */
if (NULL == Symbol)
{
printf ("Error at Line%d. Label %s not defined\n",
LineNo, Token);
IsOk = FALSE;
}
else
{
/* the machine is big endian,so store the high byte first */
Memory [MemLocation] =(Symbol->MemLocation >> 8) & 0xFF;
MemLocation++;
Memory [MemLocation] =Symbol->MemLocation &0xFF;
MemLocation++;
}
}
}
}
}
if(NULL != Fp)
fclose (Fp);
}
unsigned int LoadAddress (unsigned char*Location)
{
unsigned int Address;
Address = Location[0] << 8;
Address += Location[1];
return Address;
}
int Execute (unsigned char *Memory,REGISTERS* Reg)
{
unsigned int Address = 0;
unsigned int Instruction = 0;
unsigned int RegA = Reg->RegA;
unsigned int RegB = Reg->RegB;
unsigned int PC = Reg->PC;
int SR = Reg->SR;
unsignedchar* Operand = NULL;
int Stop = FALSE;
Instruction = Memory[PC];
PC++;
Operand = &Memory[PC];
/*Decode the instruction instruction */
switch ( Instruction )
{
case LOADA:
Address = LoadAddress(Operand);
RegA = Memory[Address];
PC += ADDRESS_LENGTH;
break;
case LOADB:
Address = LoadAddress(Operand);
RegB = Memory[Address];
PC += ADDRESS_LENGTH;
break;
case LOADAI:
RegA = *Operand;
PC += IMMEDIATE_LENGTH;
break;
case LOADBI:
RegB = *Operand;
PC += IMMEDIATE_LENGTH;
break;
case NOP:
break;
case STOREA:
Address = LoadAddress(Operand);
Memory[Address] = RegA;
PC += ADDRESS_LENGTH;
break;
case STOREB:
Address = LoadAddress(Operand);
Memory[Address] = RegB;
PC += ADDRESS_LENGTH;
break;
case ADDA:
RegA += *Operand;
PC += IMMEDIATE_LENGTH;
break;
case ADDB:
RegB += *Operand;
PC += IMMEDIATE_LENGTH;
break;
case COMPAI:
SR = RegA - *Operand;
PC += IMMEDIATE_LENGTH;
break;
case COMPBI:
SR = RegB - *Operand;
PC += IMMEDIATE_LENGTH;
break;
case BLT:
PC += ADDRESS_LENGTH;
/* only branch if comparison less than is true */
if (SR < 0)
{
Address = LoadAddress(Operand);
PC = Address;
}
break;
case BGT:
PC += ADDRESS_LENGTH;
/* only branch if comparison greater than is true */
if (SR > 0)
{
Address = LoadAddress(Operand);
PC = Address;
}
break;
case JUMP:
Address = LoadAddress(Operand);
PC = Address;
break;
case PRINTA:
printf("%x\n", RegA);
break;
case BREAK:
Stop = TRUE;
break;
default:
/* didn't recognise the Instruction just decoded */
Stop = TRUE;
}
Reg->RegA = RegA;
Reg->RegB = RegB;
Reg->SR = SR;
Reg->PC = PC;
return Stop;
}
void Run (REGISTERS* Registers, unsignedchar* Memory, int Start)
{
printf ("Beginning execution at address %04X\n", Start);
Registers->PC = Start;
while (Execute (Memory, Registers) == FALSE) ;
printf ("Break encountered at address %04X\n",Registers->PC);
}
void Step (REGISTERS* Registers, unsignedchar* Memory)
{
if(Execute (Memory, Registers) == FALSE)
printf ("Break encountered at address %04X\n",Registers->PC);
}
void SetStep (REGISTERS* Registers, unsignedchar* Memory, int Start)
{
Registers->PC = Start;
if(Execute (Memory, Registers) == FALSE)
printf ("Break encountered at address %04X\n",Registers->PC);
}
void DumpRegisters (REGISTERS* Registers)
{
printf (" Reg A :%02X\n", Registers->RegA);
printf (" Reg B :%02X\n", Registers->RegB);
printf (" PC :%02X\n", Registers->PC);
printf (" SR :%02X\n", Registers->SR);
}
void DumpMemory (unsigned char* Memory, intstart, int end)
{
int i = 0;
int j = 0;
for (i=start; i < end; i+= 8)
{
printf ("%04X ", i);
for (j = i; j < i+8; j++)
{
printf ("%02X ",Memory[j]);
}
printf("\n");
}
}
void Disassemble (int Start, int End,unsigned char* Memory)
{
int addr = 0;
unsigned char InsCode;
INSTRUCTION* Instruction = NULL;
for (addr = Start; addr < End; addr++)
{
InsCode = Memory[addr];
/* print the address of the instruction */
printf("%04X %02X ", addr, InsCode);
/* make sure the instruction code is withinbounds */
if (InsCode < sizeof InstructionTable / sizeof InstructionTable[0])
{
Instruction = &InstructionTable[InsCode];
switch(Instruction->Operand)
{
case NONE:
printf(" %-8s\n",Instruction->InstructionName);
break;
case IMMEDIATE:
addr++;
printf("%02X %-8s#%02X\n", Memory[addr],
Instruction->InstructionName,
Memory[addr]);
break;
case ADDRESS:
addr++;
printf("%02X %02X %-8s%04X\n", Memory[addr],
Memory[addr+1],
Instruction->InstructionName,
LoadAddress(&Memory[addr]));
addr++;
break;
}
}
else
{
printf(" ???\n");
}
}
}
void HelpMenu()
{
printf ("h or help this helpmenu\n");
printf ("load <filename> <memory_addr> assemble file starting at address\n");
printf ("go <memory addr> run program starting ataddress\n");
printf ("s <memory addr> step one instruction,starting at address\n");
printf ("s step one instruction, fromcurrent PC\n");
printf ("d <start> <end> disassemble memory from startto end\n");
printf ("r print contentsof registers\n");
printf ("m <start> <end> print memory from start toend\n");
printf ("q or quit exits\n");
}
void main ( int argc, char **argv)
{
int Exit = FALSE;
char Seps[] = " ,\t\n";
char* Token = NULL;
char Line1[MAX_LINE] = {0};
char Line2[MAX_LINE] = {0};
char* LoadLocation = NULL;
char* FileName = NULL;
char* Start = NULL;
char* End = NULL;
REGISTERS Registers = {0};
char Memory[ADDRESS_SPACE]= {0};
HelpMenu();
/*loop until user asks to quit */
while (!Exit)
{
printf (">");
fgets (Line1, MAX_LINE, stdin);
Token = strtok (Line1, Seps);
/* parse the command line */
if (NULL == Token)
{
continue;
}
if (0 == strcmp (Token, "load"))
{
/* see if there are any arguments specified */
FileName = strtok (NULL, Seps);
while (NULL == FileName)
{
printf ("File name :");
fgets (Line1, MAX_LINE, stdin);
FileName = strtok (Line1,Seps);
}
LoadLocation = strtok (NULL, Seps);
while (NULL == LoadLocation)
{
printf ("Load to Memory Address :");
fgets (Line2, MAX_LINE, stdin);
LoadLocation = strtok (Line2, Seps);
}
ReadAssembly (Memory, strtol(LoadLocation, NULL, 16), FileName);
}
else if (0 == strcmp (Token, "go"))
{
/* see if there are any arguments specified */
Token = strtok (NULL, Seps);
while (NULL == Token)
{
printf ("address :");
fgets (Line1, MAX_LINE, stdin);
Token = strtok (Line1, Seps);
}
Run (&Registers, Memory, strtol(Token, NULL, 16));
}
else if (0 == strcmp (Token, "s"))
{
/* Step option specified */
/* see if there are any arguments specified */
Token = strtok (NULL, Seps);
if (NULL != Token)
{
SetStep (&Registers, Memory, strtol(Token, NULL, 16));
}
else
{
Step (&Registers, Memory);
}
}
else if (0 == strcmp (Token, "d"))
{
/* disassemble option specified */
Start = strtok (NULL, Seps);
while (NULL == Start)
{
printf ("Start Address :");
fgets (Line1, MAX_LINE, stdin);
Start = strtok (Line1, Seps);
}
End = strtok (NULL, Seps);
while (NULL == End)
{
printf ("End Address :");
fgets (Line2, MAX_LINE, stdin);
End = strtok (Line2, Seps);
}
Disassemble (strtol(Start, NULL, 16), strtol(End, NULL, 16), Memory);
}
else if (0 == strcmp (Token, "r"))
{
DumpRegisters (&Registers);
}
else if (0 == strcmp (Token, "m"))
{
/* see if there are any arguments specified */
Start = strtok (NULL, Seps);
while (NULL == Start)
{
printf ("Start Address :");
fgets (Line1, MAX_LINE, stdin);
Start = strtok (Line1, Seps);
}
End = strtok (NULL, Seps);
while (NULL == End)
{
printf ("End Address :");
fgets (Line2, MAX_LINE, stdin);
End = strtok (Line2, Seps);
}
DumpMemory (Memory, strtol(Start, NULL, 16), strtol(End, NULL, 16));
}
else if (0 == strcmp (Token, "quit") || 0 == strcmp (Token,"q"))
{
Exit = TRUE;
}
else if (0 == strcmp (Token, "help") || 0 == strcmp (Token,"h"))
{
HelpMenu();
}
else
{
printf ("Unknown command\n");
}
}
} |
|