#include <avr/pgmspace.h>
const byte JAVA_PROGRAM[] PROGMEM = {
0xca, 0xfe, 0xba, 0xbe, 0x0, 0x0, 0x0, 0x32, 0x0, 0x31,
0xa, 0x0, 0xa, 0x0, 0x20, 0x8, 0x0, 0x21, 0xa, 0x0,
0x22, 0x0, 0x23, 0xa, 0x0, 0x22, 0x0, 0x24, 0xa, 0x0,
0x9, 0x0, 0x25, 0xa, 0x0, 0x22, 0x0, 0x26, 0x8, 0x0,
0x27, 0x9, 0x0, 0x9, 0x0, 0x28, 0x7, 0x0, 0x29, 0x7,
0x0, 0x2a, 0x1, 0x0, 0x7, 0x6d, 0x79, 0x56, 0x61, 0x6c,
0x75, 0x65, 0x1, 0x0, 0x1, 0x49, 0x1, 0x0, 0x6, 0x3c,
0x69, 0x6e, 0x69, 0x74, 0x3e, 0x1, 0x0, 0x3, 0x28, 0x29,
0x56, 0x1, 0x0, 0x4, 0x43, 0x6f, 0x64, 0x65, 0x1, 0x0,
0xf, 0x4c, 0x69, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65,
0x72, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x1, 0x0, 0x12, 0x4c,
0x6f, 0x63, 0x61, 0x6c, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62,
0x6c, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x1, 0x0, 0x4,
0x74, 0x68, 0x69, 0x73, 0x1, 0x0, 0x21, 0x4c, 0x64, 0x75,
0x6f, 0x76, 0x65, 0x6e, 0x74, 0x69, 0x70, 0x72, 0x6f, 0x67,
0x72, 0x61, 0x6d, 0x2f, 0x44, 0x55, 0x4f, 0x56, 0x65, 0x6e,
0x74, 0x69, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x3b,
0x1, 0x0, 0x4, 0x6d, 0x61, 0x69, 0x6e, 0x1, 0x0, 0x16,
0x28, 0x5b, 0x4c, 0x6a, 0x61, 0x76, 0x61, 0x2f, 0x6c, 0x61,
0x6e, 0x67, 0x2f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3b,
0x29, 0x56, 0x1, 0x0, 0x4, 0x61, 0x72, 0x67, 0x73, 0x1,
0x0, 0x13, 0x5b, 0x4c, 0x6a, 0x61, 0x76, 0x61, 0x2f, 0x6c,
0x61, 0x6e, 0x67, 0x2f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67,
0x3b, 0x1, 0x0, 0x8, 0x6d, 0x79, 0x4e, 0x75, 0x6d, 0x62,
0x65, 0x72, 0x1, 0x0, 0x8, 0x6d, 0x79, 0x52, 0x65, 0x73,
0x75, 0x6c, 0x74, 0x1, 0x0, 0x8, 0x6d, 0x79, 0x4d, 0x65,
0x74, 0x68, 0x6f, 0x64, 0x1, 0x0, 0x4, 0x28, 0x49, 0x29,
0x49, 0x1, 0x0, 0x6, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72,
0x1, 0x0, 0x8, 0x3c, 0x63, 0x6c, 0x69, 0x6e, 0x69, 0x74,
0x3e, 0x1, 0x0, 0xa, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65,
0x46, 0x69, 0x6c, 0x65, 0x1, 0x0, 0x14, 0x44, 0x55, 0x4f,
0x56, 0x65, 0x6e, 0x74, 0x69, 0x50, 0x72, 0x6f, 0x67, 0x72,
0x61, 0x6d, 0x2e, 0x6a, 0x61, 0x76, 0x61, 0xc, 0x0, 0xd,
0x0, 0xe, 0x1, 0x0, 0x17, 0x50, 0x6c, 0x65, 0x61, 0x73,
0x65, 0x20, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x20, 0x61, 0x20,
0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x2e, 0xa, 0x7, 0x0,
0x2b, 0xc, 0x0, 0x2c, 0x0, 0x2d, 0xc, 0x0, 0x2e, 0x0,
0x2f, 0xc, 0x0, 0x1a, 0x0, 0x1b, 0xc, 0x0, 0x2c, 0x0,
0x30, 0x1, 0x0, 0x10, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
0x65, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0xa,
0xc, 0x0, 0xb, 0x0, 0xc, 0x1, 0x0, 0x1f, 0x64, 0x75,
0x6f, 0x76, 0x65, 0x6e, 0x74, 0x69, 0x70, 0x72, 0x6f, 0x67,
0x72, 0x61, 0x6d, 0x2f, 0x44, 0x55, 0x4f, 0x56, 0x65, 0x6e,
0x74, 0x69, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x1,
0x0, 0x10, 0x6a, 0x61, 0x76, 0x61, 0x2f, 0x6c, 0x61, 0x6e,
0x67, 0x2f, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x1, 0x0,
0x18, 0x64, 0x75, 0x6f, 0x76, 0x65, 0x6e, 0x74, 0x69, 0x70,
0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x2f, 0x45, 0x78, 0x63,
0x68, 0x61, 0x6e, 0x67, 0x65, 0x1, 0x0, 0x5, 0x70, 0x72,
0x69, 0x6e, 0x74, 0x1, 0x0, 0x15, 0x28, 0x4c, 0x6a, 0x61,
0x76, 0x61, 0x2f, 0x6c, 0x61, 0x6e, 0x67, 0x2f, 0x53, 0x74,
0x72, 0x69, 0x6e, 0x67, 0x3b, 0x29, 0x56, 0x1, 0x0, 0x9,
0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x49, 0x6e, 0x74, 0x1,
0x0, 0x3, 0x28, 0x29, 0x49, 0x1, 0x0, 0x4, 0x28, 0x49,
0x29, 0x56, 0x0, 0x21, 0x0, 0x9, 0x0, 0xa, 0x0, 0x0,
0x0, 0x1, 0x0, 0xa, 0x0, 0xb, 0x0, 0xc, 0x0, 0x0,
0x0, 0x4, 0x0, 0x1, 0x0, 0xd, 0x0, 0xe, 0x0, 0x1,
0x0, 0xf, 0x0, 0x0, 0x0, 0x2f, 0x0, 0x1, 0x0, 0x1,
0x0, 0x0, 0x0, 0x5, 0x2a, 0xb7, 0x0, 0x1, 0xb1, 0x0,
0x0, 0x0, 0x2, 0x0, 0x10, 0x0, 0x0, 0x0, 0x6, 0x0,
0x1, 0x0, 0x0, 0x0, 0x4, 0x0, 0x11, 0x0, 0x0, 0x0,
0xc, 0x0, 0x1, 0x0, 0x0, 0x0, 0x5, 0x0, 0x12, 0x0,
0x13, 0x0, 0x0, 0x0, 0x9, 0x0, 0x14, 0x0, 0x15, 0x0,
0x1, 0x0, 0xf, 0x0, 0x0, 0x0, 0x6a, 0x0, 0x1, 0x0,
0x3, 0x0, 0x0, 0x0, 0x18, 0x12, 0x2, 0xb8, 0x0, 0x3,
0xb8, 0x0, 0x4, 0x3c, 0x1b, 0xb8, 0x0, 0x5, 0x3d, 0x1c,
0xb8, 0x0, 0x6, 0x12, 0x7, 0xb8, 0x0, 0x3, 0xb1, 0x0,
0x0, 0x0, 0x2, 0x0, 0x10, 0x0, 0x0, 0x0, 0x1a, 0x0,
0x6, 0x0, 0x0, 0x0, 0x9, 0x0, 0x5, 0x0, 0xa, 0x0,
0x9, 0x0, 0xb, 0x0, 0xe, 0x0, 0xc, 0x0, 0x12, 0x0,
0xd, 0x0, 0x17, 0x0, 0xe, 0x0, 0x11, 0x0, 0x0, 0x0,
0x20, 0x0, 0x3, 0x0, 0x0, 0x0, 0x18, 0x0, 0x16, 0x0,
0x17, 0x0, 0x0, 0x0, 0x9, 0x0, 0xf, 0x0, 0x18, 0x0,
0xc, 0x0, 0x1, 0x0, 0xe, 0x0, 0xa, 0x0, 0x19, 0x0,
0xc, 0x0, 0x2, 0x0, 0xa, 0x0, 0x1a, 0x0, 0x1b, 0x0,
0x1, 0x0, 0xf, 0x0, 0x0, 0x0, 0x47, 0x0, 0x2, 0x0,
0x2, 0x0, 0x0, 0x0, 0xb, 0x1a, 0xb2, 0x0, 0x8, 0x68,
0x3c, 0x84, 0x1, 0x1, 0x1b, 0xac, 0x0, 0x0, 0x0, 0x2,
0x0, 0x10, 0x0, 0x0, 0x0, 0xe, 0x0, 0x3, 0x0, 0x0,
0x0, 0x12, 0x0, 0x6, 0x0, 0x13, 0x0, 0x9, 0x0, 0x14,
0x0, 0x11, 0x0, 0x0, 0x0, 0x16, 0x0, 0x2, 0x0, 0x0,
0x0, 0xb, 0x0, 0x1c, 0x0, 0xc, 0x0, 0x0, 0x0, 0x6,
0x0, 0x5, 0x0, 0x19, 0x0, 0xc, 0x0, 0x1, 0x0, 0x8,
0x0, 0x1d, 0x0, 0xe, 0x0, 0x1, 0x0, 0xf, 0x0, 0x0,
0x0, 0x1d, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5,
0x5, 0xb3, 0x0, 0x8, 0xb1, 0x0, 0x0, 0x0, 0x1, 0x0,
0x10, 0x0, 0x0, 0x0, 0x6, 0x0, 0x1, 0x0, 0x0, 0x0,
0x6, 0x0, 0x1, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x2, 0x0,
0x1f
};
const byte ATTRIBUTE_NAME1[] PROGMEM = "Code";
const byte METHOD_NAME1[] PROGMEM = "<clinit>";
const byte METHOD_NAME2[] PROGMEM = "<init>";
const byte METHOD_NAME3[] PROGMEM = "main";
const byte ERROR_MESSAGE1[] PROGMEM = "Invalid class file.\n";
const byte ERROR_MESSAGE2[] PROGMEM = "Invalid constant.\n";
const byte ERROR_MESSAGE3[] PROGMEM = "Interfaces are not supported.\n";
byte equalText(byte *buffer1, byte *buffer2)
{
long index = 0;
while (index < 512)
{
byte tempValue1 = *buffer1;
byte tempValue2 = *buffer2;
if (tempValue1 != tempValue2)
{
return false;
}
if (tempValue1 == 0)
{
break;
}
buffer1 += 1;
buffer2 += 1;
index += 1;
}
return true;
}
byte equalData(long amount, byte *buffer1, byte *buffer2)
{
while (amount > 0)
{
byte tempValue1 = *buffer1;
byte tempValue2 = *buffer2;
if (tempValue1 != tempValue2)
{
return false;
}
buffer1 += 1;
buffer2 += 1;
amount -= 1;
}
return true;
}
void copyTextFromProgMemToBuffer(byte *destination, const byte *sequence)
{
byte count = 0;
while (count < 250)
{
byte tempData = pgm_read_byte(sequence);
*destination = tempData;
if (tempData == 0)
{
break;
}
sequence += 1;
destination += 1;
count += 1;
}
}
void copyDataFromProgMemToBuffer(byte *destination, long amount, const byte *sequence)
{
long index = 0;
while (index < amount)
{
byte tempData = pgm_read_byte(sequence + index);
*(destination + index) = tempData;
index += 1;
}
}
byte equalTextToTextFromProgMem(byte *buffer1, const byte *buffer2)
{
byte tempBuffer[250];
copyTextFromProgMemToBuffer(tempBuffer, buffer2);
return equalText(buffer1, tempBuffer);
}
void printFromProgMem(const byte *sequence)
{
byte tempBuffer[250];
copyTextFromProgMemToBuffer(tempBuffer, sequence);
Serial.print((char *)tempBuffer);
}
void readSequenceFromJavaProgram(long amount, byte *buffer, long address)
{
copyDataFromProgMemToBuffer(buffer, amount, JAVA_PROGRAM + address);
}
byte readByteFromJavaProgram(long address)
{
byte tempBuffer[1];
readSequenceFromJavaProgram(1, tempBuffer, address);
return tempBuffer[0];
}
unsigned int readUnsignedShortFromJavaProgram(long address)
{
byte tempBuffer[2];
readSequenceFromJavaProgram(2, tempBuffer, address);
return ((unsigned int)tempBuffer[0] << (unsigned int)8) + (unsigned int)tempBuffer[1];
}
unsigned long readUnsignedIntFromJavaProgram(long address)
{
byte tempBuffer[4];
readSequenceFromJavaProgram(4, tempBuffer, address);
long output = (unsigned long)tempBuffer[0] << (unsigned long)24;
output += (unsigned long)tempBuffer[1] << (unsigned long)16;
output += ((unsigned long)tempBuffer[2] << (unsigned long)8) + (unsigned long)tempBuffer[3];
return output;
}
long constantAddressList[100];
unsigned int thisJavaClass;
long fieldAddressList[25];
byte fieldAmount;
byte fieldIndexList[25];
byte fieldData[100];
long methodAddressList[25];
byte methodAmount;
long methodCodeAttributeAddressList[25];
int staticMethodIndex;
int constructorMethodIndex;
int mainMethodIndex;
byte operandStack[100];
unsigned int operandStackLevel;
byte variableStack[200];
unsigned int variableStackLevel;
byte tempBuffer[400];
void readJavaProgramStringConstant(byte *destination, unsigned int index)
{
long tempAddress = constantAddressList[index - 1];
tempAddress += 1;
unsigned int tempAmount = readUnsignedShortFromJavaProgram(tempAddress);
tempAddress += 2;
readSequenceFromJavaProgram(tempAmount, destination, tempAddress);
*(destination + tempAmount) = 0;
}
byte getDescriptorSize(byte *destination, byte *buffer)
{
byte tempCharacter = *buffer;
if (tempCharacter == 'B' || tempCharacter == 'C' || tempCharacter == 'F' || tempCharacter == 'I' || tempCharacter == 'S' || tempCharacter == 'Z')
{
*destination = 4;
return 1;
}
if (tempCharacter == 'D' || tempCharacter == 'J')
{
*destination = 8;
return 1;
}
if (tempCharacter == 'L')
{
*destination = 4;
buffer += 1;
byte output = 2;
while (*buffer != ';' && output < 250)
{
buffer += 1;
output += 1;
}
return output;
}
if (tempCharacter == '[')
{
*destination = 4;
byte tempNumber;
return 1 + getDescriptorSize(&tempNumber, buffer + 1);
}
}
void pushOperandIntOntoStack(long operand)
{
*((long *)(operandStack + operandStackLevel)) = operand;
operandStackLevel += 4;
}
long popOperandIntFromStack()
{
operandStackLevel -= 4;
return *((long *)(operandStack + operandStackLevel));
}
void initializeJavaProgram(long address)
{
unsigned long tempValue = readUnsignedIntFromJavaProgram(address);
address += 4;
if (tempValue != 0xCAFEBABE)
{
printFromProgMem(ERROR_MESSAGE1);
return;
}
// The version numbers could be read here.
address += 4;
unsigned int tempCount = readUnsignedShortFromJavaProgram(address);
address += 2;
unsigned int index = 1;
while (index < tempCount)
{
constantAddressList[index - 1] = address;
byte tempType = readByteFromJavaProgram(address);
address += 1;
if (tempType == 1)
{
unsigned int tempAmount = readUnsignedShortFromJavaProgram(address);
address += 2;
address += tempAmount;
//readJavaProgramStringConstant(tempBuffer, index);
//Serial.println((char *)tempBuffer);
}
if (tempType == 3 || tempType == 4 || tempType > 8)
{
address += 4;
}
if (tempType == 5 || tempType == 6)
{
address += 8;
}
if (tempType == 7 || tempType == 8)
{
address += 2;
}
if (tempType > 12)
{
printFromProgMem(ERROR_MESSAGE2);
return;
}
index += 1;
}
// Access flags here.
address += 2;
thisJavaClass = readUnsignedShortFromJavaProgram(address);
address += 2;
// Superclass here.
address += 2;
tempCount = readUnsignedShortFromJavaProgram(address);
address += 2;
if (tempCount > 0)
{
printFromProgMem(ERROR_MESSAGE3);
}
// Interfaces here.
fieldAmount = 0;
tempCount = readUnsignedShortFromJavaProgram(address);
address += 2;
index = 0;
while (tempCount > 0)
{
fieldAddressList[index] = address;
index += 1;
// Access flags here.
address += 2;
// Name index here.
address += 2;
// Descriptor index here.
address += 2;
unsigned int tempAmount = readUnsignedShortFromJavaProgram(address);
address += 2;
unsigned int tempIndex = 0;
while (tempIndex < tempAmount)
{
// Attribute name index here.
address += 2;
unsigned long tempAmount2 = readUnsignedIntFromJavaProgram(address);
address += 4;
// Info here.
address += tempAmount2;
tempIndex += 1;
}
fieldAmount += 1;
tempCount -= 1;
}
methodAmount = 0;
tempCount = readUnsignedShortFromJavaProgram(address);
address += 2;
index = 0;
while (tempCount > 0)
{
methodAddressList[index] = address;
index += 1;
// Access flags here.
address += 2;
// Name index here.
unsigned int tempIndex2 = readUnsignedShortFromJavaProgram(address);
readJavaProgramStringConstant(tempBuffer, tempIndex2);
Serial.println((char *)tempBuffer);
address += 2;
// Descriptor index here.
address += 2;
unsigned int tempAmount = readUnsignedShortFromJavaProgram(address);
address += 2;
unsigned int tempIndex = 0;
while (tempIndex < tempAmount)
{
unsigned int tempIndex2 = readUnsignedShortFromJavaProgram(address);
readJavaProgramStringConstant(tempBuffer, tempIndex2);
Serial.println((char *)tempBuffer);
if (equalTextToTextFromProgMem(tempBuffer, ATTRIBUTE_NAME1))
{
methodCodeAttributeAddressList[index] = address;
}
address += 2;
unsigned long tempAmount2 = readUnsignedIntFromJavaProgram(address);
address += 4;
// Info here.
address += tempAmount2;
tempIndex += 1;
}
methodAmount += 1;
tempCount -= 1;
}
byte tempFieldIndex = 0;
index = 0;
while (index < fieldAmount)
{
fieldIndexList[index] = tempFieldIndex;
long tempAddress = fieldAddressList[index];
unsigned int tempIndex = readUnsignedShortFromJavaProgram(tempAddress + 4);
readJavaProgramStringConstant(tempBuffer, tempIndex);
byte tempSize;
getDescriptorSize(&tempSize, tempBuffer);
tempFieldIndex += tempSize;
index += 1;
}
staticMethodIndex = -1;
constructorMethodIndex = -1;
mainMethodIndex = -1;
index = 0;
while (index < methodAmount)
{
long tempAddress = methodAddressList[index];
unsigned int tempIndex = readUnsignedShortFromJavaProgram(tempAddress + 2);
readJavaProgramStringConstant(tempBuffer, tempIndex);
if (equalTextToTextFromProgMem(tempBuffer, METHOD_NAME1))
{
staticMethodIndex = index;
}
if (equalTextToTextFromProgMem(tempBuffer, METHOD_NAME2))
{
constructorMethodIndex = index;
}
if (equalTextToTextFromProgMem(tempBuffer, METHOD_NAME3))
{
mainMethodIndex = index;
}
index += 1;
}
operandStackLevel = 0;
variableStackLevel = 0;
}
int findJavaProgramMethod(unsigned int index)
{
long tempAddress = constantAddressList[index];
unsigned int nameAndDescriptorIndex = readUnsignedShortFromJavaProgram(tempAddress + 3);
tempAddress = constantAddressList[nameAndDescriptorIndex];
unsigned int nameIndex = readUnsignedShortFromJavaProgram(tempAddress + 1);
unsigned int descriptorIndex = readUnsignedShortFromJavaProgram(tempAddress + 3);
unsigned int tempIndex = 0;
while (tempIndex < methodAmount)
{
long tempAddress = methodAddressList[tempIndex];
unsigned int tempIndex2 = readUnsignedShortFromJavaProgram(tempAddress + 2);
unsigned int tempIndex3 = readUnsignedShortFromJavaProgram(tempAddress + 4);
if (tempIndex2 == nameIndex && tempIndex3 == descriptorIndex)
{
return tempIndex;
}
tempIndex += 1;
}
return -1;
}
void runJavaProgramMethodByIndex(unsigned int index)
{
unsigned int tempVariableStackLevel = variableStackLevel;
long tempAddress = methodAddressList[index];
unsigned int tempIndex = readUnsignedShortFromJavaProgram(tempAddress + 4);
readJavaProgramStringConstant(tempBuffer, tempIndex);
unsigned int tempSize = 0;
tempIndex = 1;
while (*(tempBuffer + tempIndex) != ')' && tempIndex < 400)
{
byte tempSize2;
tempIndex += getDescriptorSize(&tempSize2, tempBuffer + tempIndex);
tempSize += tempSize2;
}
tempAddress = methodCodeAttributeAddressList[index];
variableStackLevel += 4 * readUnsignedShortFromJavaProgram(tempAddress + 8);
variableStackLevel = tempVariableStackLevel;
}
void runJavaProgramMethod(unsigned int index)
{
int tempIndex = findJavaProgramMethod(index);
if (tempIndex == -1)
{
return;
}
runJavaProgramMethodByIndex(tempIndex);
}
void runJavaProgram(long address)
{
initializeJavaProgram(address);
runJavaProgramMethodByIndex(staticMethodIndex);
runJavaProgramMethodByIndex(constructorMethodIndex);
runJavaProgramMethodByIndex(mainMethodIndex);
}
void setup()
{
Serial.begin(9600);
Serial.println("Hello world!");
runJavaProgram(0);
}
void loop()
{
}