Rimosso examples
This commit is contained in:
parent
30677611d8
commit
223b3c81f8
724
examples/VM.c
724
examples/VM.c
@ -1,724 +0,0 @@
|
|||||||
/*
|
|
||||||
VM by Souhail Hammou : custom instruction set
|
|
||||||
data space and stack space are customizable.
|
|
||||||
Important : In calculations the VM is using unsigned values.
|
|
||||||
*/
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <conio.h>
|
|
||||||
#define TRUE 1
|
|
||||||
#define FALSE 0
|
|
||||||
typedef unsigned char boolean;
|
|
||||||
typedef uint8_t BYTE;
|
|
||||||
typedef uint16_t WORD;
|
|
||||||
typedef uint32_t DWORD;
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
/*data has also the code*/
|
|
||||||
BYTE data[4096];
|
|
||||||
/*stack space , size of one element is WORD in order to be able to push addresses*/
|
|
||||||
WORD stack[256];
|
|
||||||
}ADDRESS_SPACE,*PADDRESS_SPACE;
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
/*General Purpose Registers R0 -> R3*/
|
|
||||||
WORD GPRs[4];
|
|
||||||
union
|
|
||||||
{
|
|
||||||
unsigned char Flags;
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
unsigned char ZF:1;
|
|
||||||
unsigned char CF:1;
|
|
||||||
unsigned char Unused:6;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
WORD IP;
|
|
||||||
WORD SP;
|
|
||||||
}REGS,*PREGS;
|
|
||||||
void VmLoop(PADDRESS_SPACE AS,PREGS Regs)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
boolean exit = FALSE;
|
|
||||||
BYTE opcode,byte_val,byte_val2,byte_val3;
|
|
||||||
WORD word_val,word_val2;
|
|
||||||
while(!exit)
|
|
||||||
{
|
|
||||||
/*read byte (opcode)*/
|
|
||||||
//printf("[+] IP : %.4X => ",Regs->IP);
|
|
||||||
opcode = AS->data[Regs->IP++];
|
|
||||||
/*opcodes switch*/
|
|
||||||
switch(opcode)
|
|
||||||
{
|
|
||||||
case 0x90 :
|
|
||||||
//printf("NOP\n");
|
|
||||||
break;
|
|
||||||
/*
|
|
||||||
Each nibble of the operand represents a General purpose register (GPR)
|
|
||||||
the highest nibble is the destination , the lowest one is the source.
|
|
||||||
Example:
|
|
||||||
10 12 => MOV R1,R2
|
|
||||||
10 11 => MOV R1,R1
|
|
||||||
10 01 => MOV R0,R1
|
|
||||||
*/
|
|
||||||
case 0x10 :
|
|
||||||
byte_val = AS->data[Regs->IP++];
|
|
||||||
if((byte_val & 0xF0) <= 0x30 && (byte_val & 0x0F) <= 3)
|
|
||||||
{
|
|
||||||
Regs->GPRs[(byte_val & 0xF0)>>4] = Regs->GPRs[byte_val & 0x0F];
|
|
||||||
//printf("MOV R%d,R%d\n",(byte_val & 0xF0)>>4,byte_val & 0x0F);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
goto exception;
|
|
||||||
break;
|
|
||||||
/*
|
|
||||||
Move and extend byte from memory to register
|
|
||||||
Example:
|
|
||||||
12 03 50 00 => MOVX R3,BYTE [0050]
|
|
||||||
12 00 00 01 => MOVX R0,BYTE [0100]
|
|
||||||
*/
|
|
||||||
case 0x12 :
|
|
||||||
byte_val = AS->data[Regs->IP++];
|
|
||||||
if(byte_val > 3)
|
|
||||||
goto exception;
|
|
||||||
word_val = *(WORD*)&AS->data[Regs->IP];
|
|
||||||
Regs->IP += 2;
|
|
||||||
if(word_val >= sizeof(AS->data))
|
|
||||||
goto exception;
|
|
||||||
Regs->GPRs[byte_val] = 0;
|
|
||||||
*(BYTE*)&Regs->GPRs[byte_val] = AS->data[word_val];
|
|
||||||
//printf("MOVX R%d, BYTE [%.4X]\n",byte_val,word_val);
|
|
||||||
break;
|
|
||||||
/*
|
|
||||||
Move word from memory to register
|
|
||||||
14 03 50 00 => MOV R3,WORD [0050]
|
|
||||||
14 00 00 01 => MOV R0,WORD [0100]
|
|
||||||
*/
|
|
||||||
case 0x14 :
|
|
||||||
byte_val = AS->data[Regs->IP++];
|
|
||||||
if(byte_val > 3)
|
|
||||||
goto exception;
|
|
||||||
word_val = *(WORD*)&AS->data[Regs->IP];
|
|
||||||
Regs->IP += 2;
|
|
||||||
if(word_val >= sizeof(AS->data))
|
|
||||||
goto exception;
|
|
||||||
Regs->GPRs[byte_val] = *(WORD*)&AS->data[word_val];
|
|
||||||
//printf("MOV R%d, WORD [%.4X]\n",byte_val,word_val);
|
|
||||||
break;
|
|
||||||
/*
|
|
||||||
Move and extend byte to register
|
|
||||||
16 01 15 => MOVX R1,15h
|
|
||||||
*/
|
|
||||||
case 0x16 :
|
|
||||||
byte_val = AS->data[Regs->IP++];
|
|
||||||
if(byte_val > 3)
|
|
||||||
goto exception;
|
|
||||||
Regs->GPRs[byte_val] = 0;
|
|
||||||
*(BYTE*)&Regs->GPRs[byte_val] = AS->data[Regs->IP++];
|
|
||||||
//printf("MOVX R%d,%.2Xh\n",byte_val,AS->data[Regs->IP - 1]);
|
|
||||||
break;
|
|
||||||
/*
|
|
||||||
Move word to register
|
|
||||||
18 01 15 28 => MOV R1,2815h
|
|
||||||
*/
|
|
||||||
case 0x18 :
|
|
||||||
byte_val = AS->data[Regs->IP++];
|
|
||||||
if(byte_val > 3)
|
|
||||||
goto exception;
|
|
||||||
Regs->GPRs[byte_val] = 0;
|
|
||||||
Regs->GPRs[byte_val] = *(WORD*)&AS->data[Regs->IP];
|
|
||||||
//printf("MOV R%d,%.4Xh\n",byte_val,*(WORD*)&AS->data[Regs->IP]);
|
|
||||||
Regs->IP += sizeof(WORD);
|
|
||||||
break;
|
|
||||||
/*
|
|
||||||
Move byte from register to memory location
|
|
||||||
ex :
|
|
||||||
1C 01 20 01 => MOV BYTE [0120],R1
|
|
||||||
1C 03 50 03 => MOV BYTE [0350],R3
|
|
||||||
*/
|
|
||||||
case 0x1c :
|
|
||||||
byte_val = AS->data[Regs->IP++];
|
|
||||||
if(byte_val > 3)
|
|
||||||
goto exception;
|
|
||||||
word_val = *(WORD*)&AS->data[Regs->IP];
|
|
||||||
Regs->IP += 2;
|
|
||||||
if(word_val >= sizeof(AS->data))
|
|
||||||
goto exception;
|
|
||||||
AS->data[word_val] = *(BYTE*)&Regs->GPRs[byte_val];
|
|
||||||
//printf("MOV BYTE [%.4X],R%d\n",word_val,byte_val);
|
|
||||||
break;
|
|
||||||
/*
|
|
||||||
Move word from register to memory location
|
|
||||||
ex :
|
|
||||||
1F 01 20 01 => MOV WORD [0120],R1
|
|
||||||
1F 03 50 03 => MOV WORD [0350],R3
|
|
||||||
*/
|
|
||||||
case 0x1f :
|
|
||||||
byte_val = AS->data[Regs->IP++];
|
|
||||||
if(byte_val > 3)
|
|
||||||
goto exception;
|
|
||||||
word_val = *(WORD*)&AS->data[Regs->IP];
|
|
||||||
Regs->IP += 2;
|
|
||||||
if(word_val >= sizeof(AS->data))
|
|
||||||
goto exception;
|
|
||||||
*(WORD*)&AS->data[word_val] = Regs->GPRs[byte_val];
|
|
||||||
//printf("MOV WORD [%.4X],R%d\n",word_val,byte_val);
|
|
||||||
break;
|
|
||||||
/*
|
|
||||||
Unconditional Jump
|
|
||||||
example :
|
|
||||||
E0 10 00 => JMP 0010
|
|
||||||
E0 54 02 => JMP 0254
|
|
||||||
*/
|
|
||||||
case 0xE0 :
|
|
||||||
word_val = *(WORD*)&AS->data[Regs->IP];
|
|
||||||
Regs->IP += 2;
|
|
||||||
if(word_val > sizeof(AS->data))
|
|
||||||
goto exception;
|
|
||||||
Regs->IP = word_val;
|
|
||||||
//printf("JMP %.4X\n",word_val);
|
|
||||||
break;
|
|
||||||
/*
|
|
||||||
JZ : Jump if equal
|
|
||||||
E2 54 01 =>JNZ 0154
|
|
||||||
*/
|
|
||||||
case 0xE2 :
|
|
||||||
word_val = *(WORD*)&AS->data[Regs->IP];
|
|
||||||
Regs->IP += 2;
|
|
||||||
if(word_val > sizeof(AS->data))
|
|
||||||
goto exception;
|
|
||||||
/*Jump if ZF is set*/
|
|
||||||
if(Regs->ZF)
|
|
||||||
Regs->IP = word_val;
|
|
||||||
//printf("JZ %.4X\n",word_val);
|
|
||||||
break;
|
|
||||||
/*
|
|
||||||
JNZ : Jump if not equal
|
|
||||||
E3 54 01 => JNZ 0154
|
|
||||||
*/
|
|
||||||
case 0xE3 :
|
|
||||||
word_val = *(WORD*)&AS->data[Regs->IP];
|
|
||||||
Regs->IP += 2;
|
|
||||||
if(word_val > sizeof(AS->data))
|
|
||||||
goto exception;
|
|
||||||
if(! Regs->ZF)
|
|
||||||
Regs->IP = word_val;
|
|
||||||
//printf("JNZ %.4X\n",word_val);
|
|
||||||
break;
|
|
||||||
/*
|
|
||||||
JAE : Jump if above or equal
|
|
||||||
E4 54 01 : JAE 0154
|
|
||||||
*/
|
|
||||||
case 0xE4 :
|
|
||||||
word_val = *(WORD*)&AS->data[Regs->IP];
|
|
||||||
Regs->IP += 2;
|
|
||||||
if(word_val > sizeof(AS->data))
|
|
||||||
goto exception;
|
|
||||||
if(Regs->ZF || ! Regs->CF)
|
|
||||||
Regs->IP = word_val;
|
|
||||||
//printf("JAE %.4X\n",word_val);
|
|
||||||
break;
|
|
||||||
/*
|
|
||||||
JBE : Jump if below or equal
|
|
||||||
E6 54 01 : JBE 0154
|
|
||||||
*/
|
|
||||||
case 0xE6 :
|
|
||||||
word_val = *(WORD*)&AS->data[Regs->IP];
|
|
||||||
Regs->IP += 2;
|
|
||||||
if(word_val > sizeof(AS->data))
|
|
||||||
goto exception;
|
|
||||||
if(Regs->ZF || Regs->CF)
|
|
||||||
Regs->IP = word_val;
|
|
||||||
//printf("JBE %.4X\n",word_val);
|
|
||||||
break;
|
|
||||||
/*
|
|
||||||
JB : Jump if below
|
|
||||||
E8 54 01 : JB 0154
|
|
||||||
*/
|
|
||||||
case 0xE8 :
|
|
||||||
word_val = *(WORD*)&AS->data[Regs->IP];
|
|
||||||
Regs->IP += 2;
|
|
||||||
if(word_val > sizeof(AS->data))
|
|
||||||
goto exception;
|
|
||||||
if(Regs->CF && ! Regs->ZF)
|
|
||||||
Regs->IP = word_val;
|
|
||||||
//printf("JB %.4X\n",word_val);
|
|
||||||
break;
|
|
||||||
/*
|
|
||||||
JA : Jump if above
|
|
||||||
EC 54 01 => JA 0154
|
|
||||||
*/
|
|
||||||
case 0xEC :
|
|
||||||
word_val = *(WORD*)&AS->data[Regs->IP];
|
|
||||||
Regs->IP += 2;
|
|
||||||
if(word_val > sizeof(AS->data))
|
|
||||||
goto exception;
|
|
||||||
if( ! Regs->CF && ! Regs->ZF)
|
|
||||||
Regs->IP = word_val;
|
|
||||||
//printf("JA %.4X\n",word_val);
|
|
||||||
break;
|
|
||||||
/*=======================================================*/
|
|
||||||
/*ARITHMETIC OPERATIONS ON THE WHOLE REGISTER (WORD)*/
|
|
||||||
/*
|
|
||||||
ADD : Add value to register
|
|
||||||
AD 01 15 00 : ADD R1,15h
|
|
||||||
AD 01 01 50 : ADD R1,5001h
|
|
||||||
|
|
||||||
Updated flags :
|
|
||||||
ZF and CF
|
|
||||||
*/
|
|
||||||
case 0xAD :
|
|
||||||
byte_val = AS->data[Regs->IP++];
|
|
||||||
if(byte_val > 3)
|
|
||||||
goto exception;
|
|
||||||
word_val = *(WORD*)&AS->data[Regs->IP];
|
|
||||||
Regs->IP += 2;
|
|
||||||
word_val2 = Regs->GPRs[byte_val] + word_val;
|
|
||||||
if(word_val2 == 0)
|
|
||||||
Regs->ZF = 1;
|
|
||||||
else
|
|
||||||
Regs->ZF = 0;
|
|
||||||
if(word_val2 < Regs->GPRs[byte_val])
|
|
||||||
Regs->CF = 1;
|
|
||||||
else
|
|
||||||
Regs->CF = 0;
|
|
||||||
Regs->GPRs[byte_val] = word_val2;
|
|
||||||
//printf("ADD R%d,%.4X\n",byte_val,word_val);
|
|
||||||
break;
|
|
||||||
/*
|
|
||||||
ADD : Add 2 registers
|
|
||||||
A5 12 : ADD R1,R2
|
|
||||||
A5 30 : ADD R3,R0
|
|
||||||
*/
|
|
||||||
case 0xA5 :
|
|
||||||
byte_val = AS->data[Regs->IP++];
|
|
||||||
if((byte_val & 0xF0) <= 0x30 && (byte_val & 0x0F) <= 3)
|
|
||||||
{
|
|
||||||
word_val = Regs->GPRs[(byte_val & 0xF0)>>4];
|
|
||||||
word_val2 = Regs->GPRs[(byte_val & 0xF0)>>4] += Regs->GPRs[byte_val & 0x0F];
|
|
||||||
if(word_val2 == 0)
|
|
||||||
Regs->ZF = 1;
|
|
||||||
else
|
|
||||||
Regs->ZF = 0;
|
|
||||||
if(word_val2 < word_val)
|
|
||||||
Regs->CF = 1;
|
|
||||||
else
|
|
||||||
Regs->CF = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
goto exception;
|
|
||||||
//printf("ADD R%d,R%d\n",(byte_val & 0xF0)>>4,byte_val & 0x0F);
|
|
||||||
break;
|
|
||||||
/*
|
|
||||||
ADDL : Add 2 registers (low byte)
|
|
||||||
A2 12 => ADDL R1,R2
|
|
||||||
*/
|
|
||||||
case 0xA2 :
|
|
||||||
byte_val = AS->data[Regs->IP++];
|
|
||||||
if((byte_val & 0xF0) <= 0x30 && (byte_val & 0x0F) <= 3)
|
|
||||||
{
|
|
||||||
byte_val2 = *(BYTE*)&Regs->GPRs[(byte_val & 0xF0)>>4];
|
|
||||||
byte_val3 = *(BYTE*)&Regs->GPRs[(byte_val & 0xF0)>>4] += *(BYTE*)&Regs->GPRs[byte_val & 0x0F];
|
|
||||||
if(byte_val3 == 0)
|
|
||||||
Regs->ZF = 1;
|
|
||||||
else
|
|
||||||
Regs->ZF = 0;
|
|
||||||
if(byte_val3 < byte_val2)
|
|
||||||
Regs->CF = 1;
|
|
||||||
else
|
|
||||||
Regs->CF = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
goto exception;
|
|
||||||
//printf("ADDL R%d,R%d\n",(byte_val & 0xF0)>>4,byte_val & 0x0F);
|
|
||||||
break;
|
|
||||||
/*
|
|
||||||
SUB : substract value from register
|
|
||||||
5B 01 15 00 : SUB R1,15h
|
|
||||||
5B 01 01 50 : SUB R1,5001h
|
|
||||||
|
|
||||||
Updated flags :
|
|
||||||
ZF and CF
|
|
||||||
*/
|
|
||||||
case 0x5B :
|
|
||||||
byte_val = AS->data[Regs->IP++];
|
|
||||||
if(byte_val > 3)
|
|
||||||
goto exception;
|
|
||||||
word_val = *(WORD*)&AS->data[Regs->IP];
|
|
||||||
Regs->IP += 2;
|
|
||||||
word_val2 = Regs->GPRs[byte_val] - word_val;
|
|
||||||
if(word_val2 == 0)
|
|
||||||
Regs->ZF = 1;
|
|
||||||
else
|
|
||||||
Regs->ZF = 0;
|
|
||||||
if(word_val2 > Regs->GPRs[byte_val])
|
|
||||||
Regs->CF = 1;
|
|
||||||
else
|
|
||||||
Regs->CF = 0;
|
|
||||||
Regs->GPRs[byte_val] = word_val2;
|
|
||||||
//printf("SUB R%d,%.4X\n",byte_val,word_val);
|
|
||||||
break;
|
|
||||||
/*
|
|
||||||
SUB : substract registers (word)
|
|
||||||
5C 01 => SUB R0,R1
|
|
||||||
*/
|
|
||||||
case 0x5C :
|
|
||||||
byte_val = AS->data[Regs->IP++];
|
|
||||||
if((byte_val & 0xF0) <= 0x30 && (byte_val & 0x0F) <= 3)
|
|
||||||
{
|
|
||||||
word_val = Regs->GPRs[(byte_val & 0xF0)>>4];
|
|
||||||
word_val2 = Regs->GPRs[(byte_val & 0xF0)>>4] -= Regs->GPRs[byte_val & 0x0F];
|
|
||||||
if(word_val2 == 0)
|
|
||||||
Regs->ZF = 1;
|
|
||||||
else
|
|
||||||
Regs->ZF = 0;
|
|
||||||
if(word_val2 > word_val)
|
|
||||||
Regs->CF = 1;
|
|
||||||
else
|
|
||||||
Regs->CF = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
goto exception;
|
|
||||||
//printf("SUB R%d,R%d",(byte_val & 0xF0)>>4,byte_val & 0x0F);
|
|
||||||
break;
|
|
||||||
/*
|
|
||||||
SUBL : Substract 2 registers (low part)
|
|
||||||
5D 12 => SUBL R1,R2
|
|
||||||
*/
|
|
||||||
case 0x5D :
|
|
||||||
byte_val = AS->data[Regs->IP++];
|
|
||||||
if((byte_val & 0xF0) <= 0x30 && (byte_val & 0x0F) <= 3)
|
|
||||||
{
|
|
||||||
byte_val2 = *(BYTE*)&Regs->GPRs[(byte_val & 0xF0)>>4];
|
|
||||||
byte_val3 = *(BYTE*)&Regs->GPRs[(byte_val & 0xF0)>>4] -= *(BYTE*)&Regs->GPRs[byte_val & 0x0F];
|
|
||||||
if(byte_val3 == 0)
|
|
||||||
Regs->ZF = 1;
|
|
||||||
else
|
|
||||||
Regs->ZF = 0;
|
|
||||||
if(byte_val3 > byte_val2)
|
|
||||||
Regs->CF = 1;
|
|
||||||
else
|
|
||||||
Regs->CF = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
goto exception;
|
|
||||||
//printf("SUBL R%d,R%d",(byte_val & 0xF0)>>4,byte_val & 0x0F);
|
|
||||||
break;
|
|
||||||
/*
|
|
||||||
XOR : Xor 2 registers
|
|
||||||
(operand uses nibbles : high = dest , low = source)
|
|
||||||
F0 12 => XOR R1,R2
|
|
||||||
F0 01 => XOR R0,R1
|
|
||||||
*/
|
|
||||||
case 0xF0 :
|
|
||||||
byte_val = AS->data[Regs->IP++];
|
|
||||||
if((byte_val & 0xF0) <= 0x30 && (byte_val & 0x0F) <= 3)
|
|
||||||
{
|
|
||||||
word_val = Regs->GPRs[(byte_val & 0xF0)>>4] ^= Regs->GPRs[byte_val & 0x0F];
|
|
||||||
if(word_val == 0)
|
|
||||||
Regs->ZF = 1;
|
|
||||||
else
|
|
||||||
Regs->ZF = 0;
|
|
||||||
Regs->CF = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
goto exception;
|
|
||||||
//printf("XOR R%d,R%d\n",(byte_val & 0xF0)>>4,byte_val & 0x0F);
|
|
||||||
break;
|
|
||||||
/*===============================================================*/
|
|
||||||
/*ARITHMETIC OPERATIONS ON THE LOWER BYTE OF THE REGISTER*/
|
|
||||||
/*
|
|
||||||
XORL : Xor the lower bytes of 2 registers
|
|
||||||
F1 12 : XORL R1,R2
|
|
||||||
F1 01 : XORL R0,R1
|
|
||||||
*/
|
|
||||||
case 0xF1 :
|
|
||||||
byte_val = AS->data[Regs->IP++];
|
|
||||||
if((byte_val & 0xF0) <= 0x30 && (byte_val & 0x0F) <= 3)
|
|
||||||
{
|
|
||||||
byte_val2 = *(BYTE*)&Regs->GPRs[(byte_val & 0xF0)>>4] ^= *(BYTE*)&Regs->GPRs[byte_val & 0x0F];
|
|
||||||
if(byte_val2 == 0)
|
|
||||||
Regs->ZF = 1;
|
|
||||||
else
|
|
||||||
Regs->ZF = 0;
|
|
||||||
Regs->CF = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
goto exception;
|
|
||||||
//printf("XORL R%d,R%d\n",(byte_val & 0xF0)>>4,byte_val & 0x0F);
|
|
||||||
break;
|
|
||||||
/*
|
|
||||||
ADDL : add only to the lower of the register
|
|
||||||
A1 03 20 => ADDL R3,20h
|
|
||||||
*/
|
|
||||||
case 0xA1:
|
|
||||||
byte_val = AS->data[Regs->IP++];
|
|
||||||
if(byte_val > 3)
|
|
||||||
goto exception;
|
|
||||||
byte_val2 = AS->data[Regs->IP++];
|
|
||||||
byte_val3 = *(BYTE*)&Regs->GPRs[byte_val] + byte_val2;
|
|
||||||
if(byte_val3 == 0)
|
|
||||||
Regs->ZF = 1;
|
|
||||||
else
|
|
||||||
Regs->ZF = 0;
|
|
||||||
if(byte_val3 < *(BYTE*)&Regs->GPRs[byte_val])
|
|
||||||
Regs->CF = 1;
|
|
||||||
else
|
|
||||||
Regs->CF = 0;
|
|
||||||
*(BYTE*)&Regs->GPRs[byte_val] = byte_val3;
|
|
||||||
//printf("ADDL R%d,%.2X\n",byte_val,byte_val2);
|
|
||||||
break;
|
|
||||||
/*
|
|
||||||
SUBL : Substract only from the lower byte of the register
|
|
||||||
51 03 20 => SUBL R3,20h
|
|
||||||
*/
|
|
||||||
case 0x51:
|
|
||||||
byte_val = AS->data[Regs->IP++];
|
|
||||||
if(byte_val > 3)
|
|
||||||
goto exception;
|
|
||||||
byte_val2 = AS->data[Regs->IP++];
|
|
||||||
byte_val3 = *(BYTE*)&Regs->GPRs[byte_val] - byte_val2;
|
|
||||||
if(byte_val3 == 0)
|
|
||||||
Regs->ZF = 1;
|
|
||||||
else
|
|
||||||
Regs->ZF = 0;
|
|
||||||
if(byte_val3 > *(BYTE*)&Regs->GPRs[byte_val])
|
|
||||||
Regs->CF = 1;
|
|
||||||
else
|
|
||||||
Regs->CF = 0;
|
|
||||||
*(BYTE*)&Regs->GPRs[byte_val] = byte_val3;
|
|
||||||
//printf("SUBL R%d,%.2X\n",byte_val,byte_val2);
|
|
||||||
break;
|
|
||||||
/*===============================================================*/
|
|
||||||
/*
|
|
||||||
Store register (low byte) at [Rx].
|
|
||||||
55 21 => MOV BYTE [R2],R1
|
|
||||||
*/
|
|
||||||
case 0x55 :
|
|
||||||
byte_val = AS->data[Regs->IP++];
|
|
||||||
if((byte_val & 0xF0) <= 0x30 && (byte_val & 0x0F) <= 3 && Regs->GPRs[(byte_val & 0xF0)>>4] < sizeof(AS->data))
|
|
||||||
AS->data[Regs->GPRs[(byte_val & 0xF0)>>4]] = *(BYTE*)&Regs->GPRs[byte_val & 0x0F];
|
|
||||||
else
|
|
||||||
goto exception;
|
|
||||||
//printf("MOV BYTE [R%d],R%d\n",(byte_val & 0xF0)>>4,byte_val & 0x0F);
|
|
||||||
break;
|
|
||||||
/*
|
|
||||||
Load and extend low byte of register from memory pointed by a register
|
|
||||||
56 21 => MOV R2,BYTE [R1]
|
|
||||||
*/
|
|
||||||
case 0x56 :
|
|
||||||
byte_val = AS->data[Regs->IP++];
|
|
||||||
if((byte_val & 0xF0) <= 0x30 && (byte_val & 0x0F) <= 3 && Regs->GPRs[(byte_val & 0x0F)] < sizeof(AS->data))
|
|
||||||
{
|
|
||||||
*(BYTE*)&Regs->GPRs[(byte_val & 0xF0)>>4] = AS->data[Regs->GPRs[byte_val & 0x0F]];
|
|
||||||
Regs->GPRs[(byte_val & 0xF0)>>4] &= 0xFF;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
goto exception;
|
|
||||||
//printf("MOVX R%d, BYTE [R%d]\n",(byte_val & 0xF0)>>4,byte_val & 0x0F);
|
|
||||||
break;
|
|
||||||
/*
|
|
||||||
CMP : Compare 2 registers (word)
|
|
||||||
70 12 : CMP R1,R2
|
|
||||||
*/
|
|
||||||
case 0x70 :
|
|
||||||
byte_val = AS->data[Regs->IP++];
|
|
||||||
if((byte_val & 0xF0) <= 0x30 && (byte_val & 0x0F) <= 3 && Regs->GPRs[(byte_val & 0x0F)] < sizeof(AS->data))
|
|
||||||
{
|
|
||||||
word_val = Regs->GPRs[(byte_val & 0xF0)>>4];
|
|
||||||
word_val2 = Regs->GPRs[byte_val & 0x0F];
|
|
||||||
if(word_val2 == word_val)
|
|
||||||
Regs->ZF = 1;
|
|
||||||
else
|
|
||||||
Regs->ZF = 0;
|
|
||||||
if(word_val2 > word_val)
|
|
||||||
Regs->CF = 1;
|
|
||||||
else
|
|
||||||
Regs->CF = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
goto exception;
|
|
||||||
//printf("CMP R%d,R%d\n",(byte_val & 0xF0)>>4,byte_val & 0x0F);
|
|
||||||
break;
|
|
||||||
/*
|
|
||||||
CMPL : Compare 2 registers (lower byte)
|
|
||||||
71 12 : CMPL R1,R2
|
|
||||||
*/
|
|
||||||
case 0x71 :
|
|
||||||
byte_val = AS->data[Regs->IP++];
|
|
||||||
if((byte_val & 0xF0) <= 0x30 && (byte_val & 0x0F) <= 3 && Regs->GPRs[(byte_val & 0x0F)] < sizeof(AS->data))
|
|
||||||
{
|
|
||||||
byte_val2 = *(BYTE*)&Regs->GPRs[(byte_val & 0xF0)>>4];
|
|
||||||
byte_val3 = *(BYTE*)&Regs->GPRs[byte_val & 0x0F];
|
|
||||||
if(byte_val3 == byte_val2)
|
|
||||||
Regs->ZF = 1;
|
|
||||||
else
|
|
||||||
Regs->ZF = 0;
|
|
||||||
if(byte_val3 > byte_val2)
|
|
||||||
Regs->CF = 1;
|
|
||||||
else
|
|
||||||
Regs->CF = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
goto exception;
|
|
||||||
//printf("CMP R%d,R%d\n",(byte_val & 0xF0)>>4,byte_val & 0x0F);
|
|
||||||
break;
|
|
||||||
/*
|
|
||||||
Push register
|
|
||||||
example : AF 01 => PUSH R1
|
|
||||||
*/
|
|
||||||
case 0xAF :
|
|
||||||
byte_val = AS->data[Regs->IP++];
|
|
||||||
if(byte_val > 3)
|
|
||||||
goto exception;
|
|
||||||
/*Decrement the stack pointer to store the new value*/
|
|
||||||
Regs->SP--;
|
|
||||||
/*Check for stack overflow*/
|
|
||||||
if(Regs->SP == 0xFFFF)
|
|
||||||
goto exception;
|
|
||||||
/*Push value */
|
|
||||||
AS->stack[Regs->SP] = Regs->GPRs[byte_val];
|
|
||||||
//printf("PUSH R%d\n",byte_val);
|
|
||||||
break;
|
|
||||||
/*
|
|
||||||
Pop a register
|
|
||||||
AE 01 => POP R1
|
|
||||||
*/
|
|
||||||
case 0xAE :
|
|
||||||
byte_val = AS->data[Regs->IP++];
|
|
||||||
if(byte_val > 3)
|
|
||||||
goto exception;
|
|
||||||
/*
|
|
||||||
Check for stack underflow
|
|
||||||
*/
|
|
||||||
if(&AS->stack[Regs->SP] == &AS->stack[sizeof(AS->stack)/sizeof(WORD)])
|
|
||||||
goto exception;
|
|
||||||
/*Move the value into the register*/
|
|
||||||
Regs->GPRs[byte_val] = AS->stack[Regs->SP];
|
|
||||||
/*Value popped , increment SP*/
|
|
||||||
Regs->SP++;
|
|
||||||
//printf("POP R%d\n",byte_val);
|
|
||||||
break;
|
|
||||||
/*========================================================*/
|
|
||||||
/*User interaction operations (print and receive input)*/
|
|
||||||
/*
|
|
||||||
Print Word to user as integer, the value must be at the top of the stack and it is popped
|
|
||||||
C0 => print integer
|
|
||||||
*/
|
|
||||||
case 0xC0 :
|
|
||||||
/*read value then pop it*/
|
|
||||||
if(&AS->stack[Regs->SP] == &AS->stack[sizeof(AS->stack)/sizeof(WORD)])
|
|
||||||
goto exception;
|
|
||||||
word_val = AS->stack[Regs->SP++];
|
|
||||||
//printf("Print integer\n");
|
|
||||||
printf("%u\n",word_val);
|
|
||||||
break;
|
|
||||||
/*
|
|
||||||
Print string to user, the pointer must be at the top of the stack and it is popped
|
|
||||||
C2 => print string
|
|
||||||
*/
|
|
||||||
case 0xC2 :
|
|
||||||
if(&AS->stack[Regs->SP] == &AS->stack[sizeof(AS->stack)/sizeof(WORD)])
|
|
||||||
goto exception;
|
|
||||||
/*read it and pop it*/
|
|
||||||
word_val = AS->stack[Regs->SP++];
|
|
||||||
if(word_val > sizeof(AS->data))
|
|
||||||
goto exception;
|
|
||||||
//printf("Print string\n");
|
|
||||||
printf("%s",&AS->data[word_val]);
|
|
||||||
break;
|
|
||||||
/*
|
|
||||||
Scan string from user, the pointer where to store the integer must be on top of the stack
|
|
||||||
89
|
|
||||||
*/
|
|
||||||
case 0x89 :
|
|
||||||
if(&AS->stack[Regs->SP] == &AS->stack[sizeof(AS->stack)/sizeof(WORD)])
|
|
||||||
goto exception;
|
|
||||||
/*read it and pop it*/
|
|
||||||
word_val = AS->stack[Regs->SP++];
|
|
||||||
if(word_val > sizeof(AS->data))
|
|
||||||
goto exception;
|
|
||||||
//printf("Scan string\n");
|
|
||||||
//printf(" [+] Input : ");
|
|
||||||
gets((char*)&AS->data[word_val]);
|
|
||||||
break;
|
|
||||||
/*=======================================================*/
|
|
||||||
/*0xDB Debugging Only*/
|
|
||||||
/*
|
|
||||||
case 0xDB :
|
|
||||||
printf("\n===Debug Information Start===\n");
|
|
||||||
printf("+ Registers :\n");
|
|
||||||
for(i=0;i<=3;i++)
|
|
||||||
printf(" R%d : 0x%.4X\n",i,Regs->GPRs[i]);
|
|
||||||
printf(" IP : 0x%.4X\n",Regs->IP);
|
|
||||||
printf(" SP : 0x%.4X\n",Regs->SP*sizeof(WORD));
|
|
||||||
printf("+ Current Stack : (Top 4 values)\n");
|
|
||||||
if(Regs->SP == sizeof(AS->stack)/sizeof(WORD))
|
|
||||||
{
|
|
||||||
printf(" The stack is empty.\n");
|
|
||||||
goto loc;
|
|
||||||
}
|
|
||||||
for(i=0;i<4;i++)
|
|
||||||
{
|
|
||||||
if(Regs->SP + i < sizeof(AS->stack)/sizeof(WORD))
|
|
||||||
printf(" SP+%d => 0x%.4X : %.4X\n",i*2,(Regs->SP + i)*2,AS->stack[Regs->SP+i]);
|
|
||||||
}
|
|
||||||
loc:
|
|
||||||
printf("+Flags Information :\n");
|
|
||||||
printf(" Flags = 0x%.2X\n",Regs->Flags);
|
|
||||||
printf(" ZF = %d\n",Regs->ZF);
|
|
||||||
printf(" CF = %d\n",Regs->CF);
|
|
||||||
printf("===Debug Information End ===\n\n");
|
|
||||||
break;
|
|
||||||
*/
|
|
||||||
/*======================================================*/
|
|
||||||
case 0xED :
|
|
||||||
//printf("Exit\n");
|
|
||||||
exit = TRUE;
|
|
||||||
break;
|
|
||||||
default :
|
|
||||||
exception:
|
|
||||||
//printf("\n==Exception : ...Exiting==\n");
|
|
||||||
exit = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
PADDRESS_SPACE AS;
|
|
||||||
PREGS Regs;
|
|
||||||
int size;
|
|
||||||
FILE* File;
|
|
||||||
//printf("DEBUG INFO :");
|
|
||||||
//printf("Allocating Address Space\n");
|
|
||||||
AS = (PADDRESS_SPACE) malloc(sizeof(ADDRESS_SPACE));
|
|
||||||
//printf("Allocating Registers\n");
|
|
||||||
Regs = (PREGS) malloc(sizeof(REGS));
|
|
||||||
//printf("Initializing Registers\n");
|
|
||||||
Regs->IP = 0;
|
|
||||||
Regs->SP = sizeof(AS->stack) / sizeof(WORD);
|
|
||||||
Regs->Flags = 0;
|
|
||||||
/*Open code and data file and read it into */
|
|
||||||
File = fopen("vm_file","rb");
|
|
||||||
if(!File)
|
|
||||||
{
|
|
||||||
printf("Found trouble opening the file");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/*Check the file size*/
|
|
||||||
fseek(File,0,SEEK_END);
|
|
||||||
size = ftell(File);
|
|
||||||
if( size > sizeof(AS->data))
|
|
||||||
{
|
|
||||||
printf("File size is larger than the storage available for data and code");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
rewind(File);
|
|
||||||
/*Copy the file to our VM address space*/
|
|
||||||
fread(AS->data,1,size,File);
|
|
||||||
fclose(File);
|
|
||||||
//printf("Starting Execution\n");
|
|
||||||
VmLoop(AS,Regs);
|
|
||||||
_getch();
|
|
||||||
return 0;
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user