#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define mem_size 32768
short pc;
short memory[mem_size];
short registers[4];
char regs[][10] = {"AX", "BX", "CX", "DX"};
#define IS_DOUBLE(x) (((x) == OP_MOV) || ((x) == OP_SUB) || ((x) == OP_ADD) || ((x) == OP_CMP))
#define IS_SINGLE(x) (((x) == OP_JMP) || ((x) == OP_JE) || ((x) == OP_JNE) || ((x) == OP_LOOP))
#define IS_END(x) ((x) == OP_END)
typedef enum
{
OP_NULL, OP_MOV, OP_ADD, OP_SUB, OP_CMP, OP_JMP, OP_JE, OP_JNE, OP_LOOP, OP_END
}op_type;
struct Insn_type
{
char name[10];
op_type type;
};
struct Insn_type insn_type[] =
{
{"MOV", OP_MOV},
{"ADD", OP_ADD},
{"SUB", OP_SUB},
{"CMP", OP_CMP},
{"JMP", OP_JMP},
{"JE", OP_JE},
{"JNE", OP_JNE},
{"LOOP", OP_LOOP},
{"END", OP_END}
};
#define insn_type_num 9
#define OPND_NULL 0
#define OPND_IMM 1
#define OPND_REG 0x2
#define OPND_MEM 0x5
#define OPND_INDIR_MEM 0x6
struct Insn_info
{
op_type type;
short opnd_type[2];
short opnd[2];
char label[20];
};
struct Insn_info insn_code[50];
short code_num;
struct label_info
{
char name[20];
short addr;
};
struct label_info label[30];
short label_num;
short get_insn_type(char *code)
{
short i;
for (i = 0; i < insn_type_num; ++i)
{
if (strcmp(code, insn_type[i].name) == 0)
break;
}
return i;
}
short decode_insn_info(char *insn, short index)
{
short i;
char *p = insn;
insn_code[code_num].opnd_type[index] = 0;
if (*p == '[')
{
++p;
insn_code[code_num].opnd_type[index] |= 4;
}
for (i = 0; i < 4; ++i)
{
if (regs[i][0] == *p)
break;
}
if (i != 4)
{
insn_code[code_num].opnd_type[index] |= 0x2;
insn_code[code_num].opnd[index] = i;
return 0;
}
insn_code[code_num].opnd_type[index] |= 1;
insn_code[code_num].opnd[index] = atoi(p);
return 0;
}
#define get_val(ipc, index, val) \
{\
if (insn_code[ipc].opnd_type[index] & 1)\
val = insn_code[ipc].opnd[index];\
if (insn_code[ipc].opnd_type[index] & 2)\
val = registers[insn_code[ipc].opnd[index]];\
if (insn_code[ipc].opnd_type[index] & 4)\
val = memory[val];\
}\
short * get_addr(short ipc, short index)
{
short val;
short *p = NULL;
if (insn_code[ipc].opnd_type[index] & 1)
val = insn_code[ipc].opnd[index];
if (insn_code[ipc].opnd_type[index] & 2)
{
p = ®isters[insn_code[ipc].opnd[index]];
val = *p;
}
if (insn_code[ipc].opnd_type[index] & 4)
p = &memory[val];
return p;
}
short get_label_addr(char *p)
{
short i;
for (i = 0; i < label_num; ++i)
{
if (strcmp(p, label[i].name) == 0)
break;
}
return label[i].addr;
}
int main()
{
short a, b;
short val, flag_cmp;
short i, code_count;
short *addr = NULL;
char *p = NULL;
char str[100];
char code[100], opnd1[100], opnd2[100];
while(gets(str))
{
code_count = 0;
code_num = 0;
label_num = 0;
while (1)
{
p = str;
sscanf(p, "%s", code);
if (code[strlen(code) - 1] == ':')
{
strcpy(label[label_num].name, code);
label[label_num].name[strlen(label[label_num].name) - 1] = '\0';
label[label_num].addr = code_count;
while (*p == ' ') ++p;
p = p + strlen(code);
++label_num;
}
if (sscanf(p, "%s", code) == 1)
{
i = get_insn_type(code);
while (*p == ' ') ++p;
p = p + strlen(code);
insn_code[code_num].type = insn_type[i].type;
if (IS_DOUBLE(insn_type[i].type))
{
sscanf(p, "%s %s", opnd1, opnd2);
decode_insn_info(opnd1, 0);
decode_insn_info(opnd2, 1);
}
else if (IS_SINGLE(insn_type[i].type))
{
sscanf(p, "%s", opnd1);
strcpy(insn_code[code_num].label, opnd1);
}
else
break;
++code_num;
++code_count;
}
gets(str);
}
for (i = 0; i < code_num; ++i)
{
if (insn_code[i].type == OP_JNE || insn_code[i].type == OP_JE || insn_code[i].type == OP_LOOP || insn_code[i].type == OP_JMP)
insn_code[i].opnd[0] = get_label_addr(insn_code[i].label);
}
pc = 0;
memset(registers, 0, sizeof(registers));
while(!IS_END(insn_code[pc].type))
{
switch(insn_code[pc].type)
{
case OP_MOV:
get_val(pc, 1, val);
addr = get_addr(pc, 0);
*addr = val;
++pc;
break;
case OP_ADD:
get_val(pc, 1, val);
addr = get_addr(pc, 0);
*addr += val;
++pc;
break;
case OP_SUB:
get_val(pc, 1, val);
addr = get_addr(pc, 0);
*addr -= val;
++pc;
break;
case OP_CMP:
get_val(pc, 0, a);
get_val(pc, 1, b);
flag_cmp = a - b;
++pc;
break;
case OP_JE:
if (flag_cmp == 0)
pc = insn_code[pc].opnd[0];
else
++pc;
break;
case OP_JNE:
if (flag_cmp != 0)
pc = insn_code[pc].opnd[0];
else
++pc;
break;
case OP_LOOP:
--registers[2];
if (registers[2] != 0)
pc = insn_code[pc].opnd[0];
else
++pc;
break;
case OP_JMP:
pc = insn_code[pc].opnd[0];
break;
default:
break;
}
}
printf("%d %d %d %d\n", registers[0], registers[1], registers[2], registers[3]);
}
return 0;
}
|