diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..12a80fe --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Datasource local storage ignored files +/../../../../../../../../:\Users\anton\OneDrive\Documents\GitHub\JavaComputer\.idea/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/discord.xml b/.idea/discord.xml new file mode 100644 index 0000000..9079745 --- /dev/null +++ b/.idea/discord.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..37e641e --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..ec0822a --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/CPU.java b/CPU.java index 72cb1e1..65514a8 100644 --- a/CPU.java +++ b/CPU.java @@ -20,6 +20,90 @@ public CPU() { registers[Registers.ebp] = 0x7fffff00; } + public static void main(String[] args) { + CPU myCPU = new CPU(); + //EDI=Base + //ESI=Exponent + int i = 0; + + myCPU.memory[i++] = Instructions.MOV_LIT_REG; + myCPU.memory[i++] = 0x00; + myCPU.memory[i++] = 0x00; + myCPU.memory[i++] = 0x00; + myCPU.memory[i++] = 0x05; + myCPU.memory[i++] = Registers.edi; + + myCPU.memory[i++] = Instructions.MOV_LIT_REG; + myCPU.memory[i++] = 0x00; + myCPU.memory[i++] = 0x00; + myCPU.memory[i++] = 0x00; + myCPU.memory[i++] = 0x05; + myCPU.memory[i++] = Registers.esi; + + myCPU.memory[i++] = Instructions.MOV_LIT_REG; + myCPU.memory[i++] = 0x00; + myCPU.memory[i++] = 0x00; + myCPU.memory[i++] = 0x00; + myCPU.memory[i++] = 0x01; + myCPU.memory[i++] = Registers.eax; + + i = 0x20; + //LOOP: 32 / 0x20 + myCPU.memory[i++] = Instructions.CMP_LIT_REG; + myCPU.memory[i++] = 0x00; + myCPU.memory[i++] = 0x00; + myCPU.memory[i++] = 0x00; + myCPU.memory[i++] = 0x00; + myCPU.memory[i++] = Registers.esi; + + myCPU.memory[i++] = Instructions.JE_LIT; + myCPU.memory[i++] = 0x00; + myCPU.memory[i++] = 0x00; + myCPU.memory[i++] = 0x04; + myCPU.memory[i++] = 0x00; + myCPU.memory[i++] = Registers.esi; + + myCPU.memory[i++] = Instructions.MUL_REG; + myCPU.memory[i++] = Registers.edi; + + myCPU.memory[i++] = Instructions.SUB_LIT_REG; + myCPU.memory[i++] = 0x00; + myCPU.memory[i++] = 0x00; + myCPU.memory[i++] = 0x00; + myCPU.memory[i++] = 0x01; + myCPU.memory[i++] = Registers.esi; + + myCPU.memory[i++] = Instructions.JMP_LIT; + myCPU.memory[i++] = 0x00; + myCPU.memory[i++] = 0x00; + myCPU.memory[i++] = 0x00; + myCPU.memory[i++] = 0x20; + +//After: + i = 0x400; + myCPU.memory[i++] = Instructions.MOV_REG_REG; + myCPU.memory[i++] = Registers.eax; + myCPU.memory[i++] = Registers.esi; + + myCPU.memory[i++] = Instructions.MOV_LIT_REG; + myCPU.memory[i++] = 0x00; + myCPU.memory[i++] = 0x00; + myCPU.memory[i++] = 0x10; + myCPU.memory[i++] = 0x00; + myCPU.memory[i++] = Registers.edi; + + myCPU.memory[i++] = Instructions.CALL_PRINTF; + + myCPU.memory[i++] = Instructions.CALL_EXIT; + + i = 0x1000; + myCPU.memory[i++] = (char) '%'; + myCPU.memory[i++] = (char) 'd'; + myCPU.memory[i++] = 0x00; + + myCPU.run(); + } + public String padLeftZeros(String inputString, int length) { if (inputString.length() >= length) { return inputString; @@ -32,17 +116,21 @@ public String padLeftZeros(String inputString, int length) { return sb.toString(); } - public void printMemory(int startingLocation){ + + public void printMemory(int startingLocation) { printMemory(startingLocation, 100); } - public void printMemory(int startingLocation, int bytes){ - for (int i = startingLocation; i < startingLocation+bytes; i++) { + + public void printMemory(int startingLocation, int bytes) { + for (int i = startingLocation; i < startingLocation + bytes; i++) { System.out.println(String.format("0x%02X", memory[i])); } } - public int btoi(byte inByte){ - return ((int)inByte) & 0xff; + + public int btoi(byte inByte) { + return ((int) inByte) & 0xff; } + public long binaryAdd(long a, long b) { String String1 = padLeftZeros(Long.toBinaryString(a), 32); String String2 = padLeftZeros(Long.toBinaryString(b), 32); @@ -51,7 +139,7 @@ public long binaryAdd(long a, long b) { String outString = ""; int carry = 0; for (int i = 31; i > 0; i--) { - int temp = (int) String1Array[i]-48 + (int) String2Array[i]-48 + carry; + int temp = (int) String1Array[i] - 48 + (int) String2Array[i] - 48 + carry; carry = 0; if (temp > 1) { temp = temp - 2; @@ -60,35 +148,36 @@ public long binaryAdd(long a, long b) { outString = Integer.toString(temp) + outString; } long outputLong = Long.parseLong(outString, 2); - flags[Flags.CF] = carry==1; + flags[Flags.CF] = carry == 1; return outputLong; } - //=============== ALL THE FETCH INSTRUCTIONS FROM EIP ========================= - public long fetch32(){ + public long fetch32() { int ip = (int) registers[Registers.eip]; long returnValue = fetch32at(ip); - registers[Registers.eip] = ip+4; + registers[Registers.eip] = ip + 4; return returnValue; } - public int fetch16(){ + + public int fetch16() { int ip = (int) registers[Registers.eip]; int returnValue = fetch16at(ip); - registers[Registers.eip] = ip+2; + registers[Registers.eip] = ip + 2; return returnValue; } - public byte fetch(){ + //=============== ALL THE FETCH INSTRUCTIONS FROM ADDRESS ========================= + + public byte fetch() { int ip = (int) registers[Registers.eip]; byte returnValue = fetchat(ip); - registers[Registers.eip] = ip+1; + registers[Registers.eip] = ip + 1; return returnValue; } - //=============== ALL THE FETCH INSTRUCTIONS FROM ADDRESS ========================= - public long fetch32at(int address){ + public long fetch32at(int address) { byte byte1 = memory[address++]; byte byte2 = memory[address++]; byte byte3 = memory[address++]; @@ -96,21 +185,25 @@ public long fetch32at(int address){ long result = btoi(byte4) + btoi(byte3) * 0x100 + btoi(byte2) * 0x10000 + btoi(byte1) * 0x1000000; return result; } - public int fetch16at(int address){ + + public int fetch16at(int address) { byte byte1 = memory[address++]; byte byte2 = memory[address++]; int result = btoi(byte2) + btoi(byte1) * 0x100; return result; } - public byte fetchat(int address){ + + //=============== ALL THE WRITE INSTRUCTIONS ========================= + + public byte fetchat(int address) { byte byte1 = memory[address]; return byte1; } - //=============== ALL THE WRITE INSTRUCTIONS ========================= /** * Writes the 32 bit value to the address in memory - * @param value the value to write + * + * @param value the value to write * @param address the address to write to */ public void write32at(long value, int address) { @@ -124,31 +217,36 @@ public void write32at(long value, int address) { memory[address++] = byte3; memory[address] = byte4; } - public void write16at(int value, int address){ + + public void write16at(int value, int address) { byte byte2 = (byte) (value & 0x00ff); //0x00000078 byte byte1 = (byte) ((value & 0xff00) >> 8); //0x00005600 memory[address++] = byte1; memory[address] = byte2; } - public void write8at(byte value, int address){ + + public void write8at(byte value, int address) { memory[address] = value; } - public void push(long literal){ + + public void push(long literal) { registers[Registers.esp] -= 4; - write32at(literal, (int)registers[Registers.esp]); + write32at(literal, (int) registers[Registers.esp]); } - public long pop(){ - long returnValue = fetch32at((int)registers[Registers.esp]); + + public long pop() { + long returnValue = fetch32at((int) registers[Registers.esp]); registers[Registers.esp] += 4; return returnValue; } + /** * Executes 1 instruction starting at the instruction pointer */ - public void step(){ + public void step() { byte instruction = fetch(); - switch(instruction){ + switch (instruction) { //=====================Implementation of MOV instructions=============== case Instructions.MOV_LIT_MEM: { long lit = fetch32(); @@ -171,7 +269,7 @@ public void step(){ case Instructions.MOV_REG_MEM: { int reg = fetch(); int mem = fetch16(); - write32at(registers[reg],mem); + write32at(registers[reg], mem); break; } case Instructions.MOV_MEM_REG: { @@ -184,8 +282,8 @@ public void step(){ case Instructions.ADD_LIT_REG: { long lit = fetch32(); int reg = fetch(); - if(registers[reg]+lit>0x100000000l) - registers[reg] = binaryAdd(registers[reg], lit); + if (registers[reg] + lit > 0x100000000l) + registers[reg] = binaryAdd(registers[reg], lit); break; } case Instructions.ADD_REG_REG: { @@ -199,8 +297,8 @@ public void step(){ int reg = fetch(); //Set appropriate CF registers[reg] = registers[reg] - lit; - flags[Flags.CF] = registers[reg]<0; - flags[Flags.ZF] = registers[reg]==0; + flags[Flags.CF] = registers[reg] < 0; + flags[Flags.ZF] = registers[reg] == 0; break; } case Instructions.SUB_REG_REG: { @@ -208,8 +306,8 @@ public void step(){ int reg2 = fetch(); registers[reg2] = registers[reg2] - registers[reg1]; - flags[Flags.CF] = registers[reg2]<0; - flags[Flags.ZF] = registers[reg2]==0; + flags[Flags.CF] = registers[reg2] < 0; + flags[Flags.ZF] = registers[reg2] == 0; break; } case Instructions.MUL_LIT: { @@ -240,14 +338,14 @@ public void step(){ int formatstring_memorylocation = (int) registers[Registers.edi]; byte charByte = fetchat(formatstring_memorylocation++); String formatString = ""; - while(charByte != 0){ + while (charByte != 0) { formatString += (char) charByte; charByte = fetchat(formatstring_memorylocation++); } long vararg1 = registers[Registers.esi]; long vararg2 = registers[Registers.edx]; long vararg3 = registers[Registers.ecx]; - System.out.printf(formatString,vararg1,vararg2,vararg3); + System.out.printf(formatString, vararg1, vararg2, vararg3); break; } case Instructions.CALL_PUTCHAR: { @@ -267,8 +365,8 @@ public void step(){ long lit = fetch32(); byte reg = fetch(); long reg_value = registers[reg]; - flags[Flags.CF] = lit-reg_value<0; - flags[Flags.ZF] = lit-reg_value==0; + flags[Flags.CF] = lit - reg_value < 0; + flags[Flags.ZF] = lit - reg_value == 0; break; } case Instructions.CMP_REG_REG: { @@ -276,8 +374,8 @@ public void step(){ byte reg2 = fetch(); long reg_value1 = registers[reg1]; long reg_value2 = registers[reg2]; - flags[Flags.CF] = reg_value1-reg_value2<0; - flags[Flags.ZF] = reg_value1-reg_value2==0; + flags[Flags.CF] = reg_value1 - reg_value2 < 0; + flags[Flags.ZF] = reg_value1 - reg_value2 == 0; break; } case Instructions.JMP_LIT: { @@ -292,84 +390,84 @@ public void step(){ } case Instructions.JE_LIT: { long address = fetch32(); - if(flags[Flags.ZF]==true) { + if (flags[Flags.ZF] == true) { registers[Registers.eip] = address; } break; } case Instructions.JE_REG: { byte reg = fetch(); - if(flags[Flags.ZF]==true) { + if (flags[Flags.ZF] == true) { registers[Registers.eip] = registers[reg]; } break; } case Instructions.JNE_LIT: { long address = fetch32(); - if(flags[Flags.ZF]!=true) { + if (flags[Flags.ZF] != true) { registers[Registers.eip] = address; } break; } case Instructions.JNE_REG: { byte reg = fetch(); - if(flags[Flags.ZF]!=true) { + if (flags[Flags.ZF] != true) { registers[Registers.eip] = registers[reg]; } break; } case Instructions.JGE_LIT: { long address = fetch32(); - if(flags[Flags.ZF]==true || flags[Flags.CF]==false) { + if (flags[Flags.ZF] == true || flags[Flags.CF] == false) { registers[Registers.eip] = address; } break; } case Instructions.JGE_REG: { byte reg = fetch(); - if(flags[Flags.ZF]==true || flags[Flags.CF]==false) { + if (flags[Flags.ZF] == true || flags[Flags.CF] == false) { registers[Registers.eip] = registers[reg]; } break; } case Instructions.JG_LIT: { long address = fetch32(); - if(flags[Flags.ZF]==false && flags[Flags.CF]==false) { + if (flags[Flags.ZF] == false && flags[Flags.CF] == false) { registers[Registers.eip] = address; } break; } case Instructions.JG_REG: { byte reg = fetch(); - if(flags[Flags.ZF]==false && flags[Flags.CF]==false) { + if (flags[Flags.ZF] == false && flags[Flags.CF] == false) { registers[Registers.eip] = registers[reg]; } break; } case Instructions.JLE_LIT: { long address = fetch32(); - if(flags[Flags.ZF]==true || flags[Flags.CF]==true) { + if (flags[Flags.ZF] == true || flags[Flags.CF] == true) { registers[Registers.eip] = address; } break; } case Instructions.JLE_REG: { byte reg = fetch(); - if(flags[Flags.ZF]==true || flags[Flags.CF]==true) { + if (flags[Flags.ZF] == true || flags[Flags.CF] == true) { registers[Registers.eip] = registers[reg]; } break; } case Instructions.JL_LIT: { long address = fetch32(); - if(flags[Flags.ZF]==false && flags[Flags.CF]==true) { + if (flags[Flags.ZF] == false && flags[Flags.CF] == true) { registers[Registers.eip] = address; } break; } case Instructions.JL_REG: { byte reg = fetch(); - if(flags[Flags.ZF]==false && flags[Flags.CF]==true) { + if (flags[Flags.ZF] == false && flags[Flags.CF] == true) { registers[Registers.eip] = registers[reg]; } break; @@ -394,8 +492,8 @@ public void step(){ case Instructions.CALL_LIT: { long lit = fetch32(); //PRESERVE REGISTERS - for(int i=0;i=0;i--){ - if(i!=Registers.eax && i!=Registers.esp && i!=Registers.ebp && i!=Registers.eip){ + for (int i = registers.length - 1; i >= 0; i--) { + if (i != Registers.eax && i != Registers.esp && i != Registers.ebp && i != Registers.eip) { registers[i] = pop(); } } @@ -511,94 +609,11 @@ public void step(){ } } - public void run(){ + + public void run() { running = true; - while(running){ + while (running) { step(); } } - - public static void main(String[] args) { - CPU myCPU = new CPU(); - //EDI=Base - //ESI=Exponent - int i = 0; - - myCPU.memory[i++] = Instructions.MOV_LIT_REG; - myCPU.memory[i++] = 0x00; - myCPU.memory[i++] = 0x00; - myCPU.memory[i++] = 0x00; - myCPU.memory[i++] = 0x05; - myCPU.memory[i++] = Registers.edi; - - myCPU.memory[i++] = Instructions.MOV_LIT_REG; - myCPU.memory[i++] = 0x00; - myCPU.memory[i++] = 0x00; - myCPU.memory[i++] = 0x00; - myCPU.memory[i++] = 0x05; - myCPU.memory[i++] = Registers.esi; - - myCPU.memory[i++] = Instructions.MOV_LIT_REG; - myCPU.memory[i++] = 0x00; - myCPU.memory[i++] = 0x00; - myCPU.memory[i++] = 0x00; - myCPU.memory[i++] = 0x01; - myCPU.memory[i++] = Registers.eax; - - i=0x20; - //LOOP: 32 / 0x20 - myCPU.memory[i++] = Instructions.CMP_LIT_REG; - myCPU.memory[i++] = 0x00; - myCPU.memory[i++] = 0x00; - myCPU.memory[i++] = 0x00; - myCPU.memory[i++] = 0x00; - myCPU.memory[i++] = Registers.esi; - - myCPU.memory[i++] = Instructions.JE_LIT; - myCPU.memory[i++] = 0x00; - myCPU.memory[i++] = 0x00; - myCPU.memory[i++] = 0x04; - myCPU.memory[i++] = 0x00; - myCPU.memory[i++] = Registers.esi; - - myCPU.memory[i++] = Instructions.MUL_REG; - myCPU.memory[i++] = Registers.edi; - - myCPU.memory[i++] = Instructions.SUB_LIT_REG; - myCPU.memory[i++] = 0x00; - myCPU.memory[i++] = 0x00; - myCPU.memory[i++] = 0x00; - myCPU.memory[i++] = 0x01; - myCPU.memory[i++] = Registers.esi; - - myCPU.memory[i++] = Instructions.JMP_LIT; - myCPU.memory[i++] = 0x00; - myCPU.memory[i++] = 0x00; - myCPU.memory[i++] = 0x00; - myCPU.memory[i++] = 0x20; - -//After: - i = 0x400; - myCPU.memory[i++] = Instructions.MOV_REG_REG; - myCPU.memory[i++] = Registers.eax; - myCPU.memory[i++] = Registers.esi; - - myCPU.memory[i++] = Instructions.MOV_LIT_REG; - myCPU.memory[i++] = 0x00; - myCPU.memory[i++] = 0x00; - myCPU.memory[i++] = 0x10; - myCPU.memory[i++] = 0x00; - myCPU.memory[i++] = Registers.edi; - - myCPU.memory[i++] = Instructions.CALL_PRINTF; - - myCPU.memory[i++] = Instructions.CALL_EXIT; - - i = 0x1000; - myCPU.memory[i++] = (char) '%'; - myCPU.memory[i++] = (char) 'd'; - myCPU.memory[i++] = 0x00; - - myCPU.run(); - } } diff --git a/JavaComputer.iml b/JavaComputer.iml new file mode 100644 index 0000000..b107a2d --- /dev/null +++ b/JavaComputer.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/out/production/JavaComputer/.idea/.gitignore b/out/production/JavaComputer/.idea/.gitignore new file mode 100644 index 0000000..12a80fe --- /dev/null +++ b/out/production/JavaComputer/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Datasource local storage ignored files +/../../../../../../../../:\Users\anton\OneDrive\Documents\GitHub\JavaComputer\.idea/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/out/production/JavaComputer/.idea/discord.xml b/out/production/JavaComputer/.idea/discord.xml new file mode 100644 index 0000000..9079745 --- /dev/null +++ b/out/production/JavaComputer/.idea/discord.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/out/production/JavaComputer/.idea/misc.xml b/out/production/JavaComputer/.idea/misc.xml new file mode 100644 index 0000000..37e641e --- /dev/null +++ b/out/production/JavaComputer/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/out/production/JavaComputer/.idea/modules.xml b/out/production/JavaComputer/.idea/modules.xml new file mode 100644 index 0000000..ec0822a --- /dev/null +++ b/out/production/JavaComputer/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/out/production/JavaComputer/.idea/vcs.xml b/out/production/JavaComputer/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/out/production/JavaComputer/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/out/production/JavaComputer/CPU.class b/out/production/JavaComputer/CPU.class new file mode 100644 index 0000000..25f169e Binary files /dev/null and b/out/production/JavaComputer/CPU.class differ diff --git a/out/production/JavaComputer/Flags.class b/out/production/JavaComputer/Flags.class new file mode 100644 index 0000000..c308748 Binary files /dev/null and b/out/production/JavaComputer/Flags.class differ diff --git a/out/production/JavaComputer/Instructions.class b/out/production/JavaComputer/Instructions.class new file mode 100644 index 0000000..37e46ac Binary files /dev/null and b/out/production/JavaComputer/Instructions.class differ diff --git a/out/production/JavaComputer/JavaComputer.iml b/out/production/JavaComputer/JavaComputer.iml new file mode 100644 index 0000000..b107a2d --- /dev/null +++ b/out/production/JavaComputer/JavaComputer.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/out/production/JavaComputer/README.md b/out/production/JavaComputer/README.md new file mode 100644 index 0000000..97c6120 --- /dev/null +++ b/out/production/JavaComputer/README.md @@ -0,0 +1,29 @@ +# JavaComputer + +## A computer in java (duh) + +## Features as of now: + *Fully functional CPU with memory\ + *Fully function Instructionset, containing Moving, arithmetics, logical, branching, stack manipulation, and function call instructions\ + *Preserves registers by itself on the stack when calling subroutines, so no need to preserve them yourself +## Coming soon: +Own assembler!\ +Memory mapped IO! +# Instalation: +(not tested, so if this doesn't work shoot me a message) +1. Create a new project in IntelliJ +2. Create 4 new files, named according to the files in this git repository +3. Copy-paste the content into the files +4. Run the project, with the CPU's main class being the main function\ + +You can make your own 'Program' by modifying the bytecode being written in main. +## Some other info +I made this in the freshmen discord server, along with some other people in a call. We spent 6 hours total on this as of now, consisting of a 2 hour chunk (before a lecture) and another 4 hour chunk (after that lecture).\ +Both sittings were recorded and uploaded to youtube, so to see us messing around in java and building it from scratch, you can visit these links: https://youtu.be/PAJS4On2_fg and https://youtu.be/-G-1VTyQ5A8 \ +\ +As for now, we've also made and tested some code in it, for example a power function, which worked flawlessly.\ +I also managed to get a true recursive factorial function working, which was pretty neat. +### Contact: +@jurrejelle on telegram, instagram, twitter, github\ +jurrejelle#4936 on discord\ +jurre@jilles.com on email, but might reply slowly diff --git a/out/production/JavaComputer/Registers.class b/out/production/JavaComputer/Registers.class new file mode 100644 index 0000000..d232de3 Binary files /dev/null and b/out/production/JavaComputer/Registers.class differ