Engineering HL Programming: Mini-Assembler in Java

  • Thread starter Thread starter Margarita0076
  • Start date Start date
  • Tags Tags
    Java Programming
AI Thread Summary
The discussion revolves around creating a mini-Assembler for a 32-bit MIPS processor in Java, focusing on the implementation of the makeI and makeR methods. The makeR method constructs a 32-bit integer for R-type instructions using fields such as opcode, source registers, destination register, shift amount, and function code. Conversely, the makeI method does the same for I-type instructions, incorporating opcode, source registers, destination registers, and an immediate value. Participants emphasize the importance of understanding the instruction formats and bit fields to correctly implement these methods. The conversation highlights the necessity of clarity in the design and function of these methods for successful assembly code translation.
Margarita0076
Messages
5
Reaction score
0
Homework Statement
Assembler.java
Relevant Equations
Create a mini-Assembler for a 32-bit MIPS processor.
I already wrote the regToByte method, but I don't understand how to write the makeI and makeR methods correctly.

Create a mini-Assembler for a 32-bit MIPS processor; Program should accept input lines from the user until HALT is read. With each line, translate the line into MIPS machine code. Print the total memory space needed for the completed program.

Conditions:

The form for all assembly lines will be:

<code> <rd> <rs> <rt> (for codes ADD, AND);
<code> <rd> <rt> <shift_amount> (for codes SRL, SLL);
<code> <rt> <rs> <immediate> (for codes ADDI, ANDI);
BEQ <rs> <rt> <branch_address>;
LW <rt> immediate <rs>; SW <rt> immediate <rs>

Your Assembler should accept the following subset of the complete ISA:

Functions: ADD, ADDI, AND, ANDI, BEQ, LW, SW, SRL, SLL; Registers: $zero, $v0-1, $a0-3, $t0-9, $s0-7.

Immediates and shift amounts should be read in decimal. Branch addresses should be read as a decimal offset from PC+4 (positive or negative). That is, you don't need to do any address arithmetic, just use the immediate given.

Printing a 32-bit binary number can be done in Java with the following: System.out.println("***: " + String.format("%32s", Integer.toBinaryString(word)).replace(" ", "0"));

Mod note: Added code tags
Java:
import java.util.Scanner;

public class Assembler
{
   private static final boolean TEST_MODE = true;

   public static void main(String[] args)
   {
      int count = 0;

      if (TEST_MODE)
      {
         testCases();
      }
      else
      {
         System.out.println("Assembler - Your Name Here\n");

        [B] // Your code here[/B]
        
         System.out.println("\n*** Assembly complete. Program required " + count + " words of memory.");
      }
   }

   [B]private static int makeR(byte opcode, byte rs, byte rt, byte rd, byte shamt, byte funct)
   {[/B]
      int returnValue = 0;
     
      return returnValue;
   [B]}[/B]

  [B] private static int makeI(byte opcode, byte rs, byte rt, short immed)
   {[/B]
      int returnValue = 0;
     
      return returnValue;
   [B]}[/B]

  [B] private static byte regToByte(String r)
   {[/B]
      byte returnValue = 0;
      String upperCase = r.toUpperCase();

      switch(upperCase)
      {
         case "$AT":
            returnValue = 1;
            break;
         case "$ZERO":
            returnValue = 0;
            break;
         case "$V0":
            returnValue = 2;
            break;
         case "$V1":
            returnValue = 3;
            break;
         case "$A0":
            returnValue = 4;
            break;
         case "$A1":
            returnValue = 5;
            break;
         case "$A2":
            returnValue = 6;
            break;
         case "$A3":
            returnValue = 7;
            break;
         case "$T0":
            returnValue = 8;
            break;
         case "$T1":
            returnValue = 9;
            break;
         case "$T2":
            returnValue = 10;
            break;
         case "$T3":
            returnValue = 11;
            break;
         case "$T4":
            returnValue = 12;
            break;
         case "$T5":
            returnValue = 13;
            break;
         case "$T6":
            returnValue = 14;
            break;
         case "$T7":
            returnValue = 15;
            break;
         case "$T8":
            returnValue = 24;
            break;
         case "$T9":
            returnValue = 25;
            break;
         case "$S0":
            returnValue = 16;
            break;
         case "$S1":
            returnValue = 17;
            break;
         case "$S2":
            returnValue = 18;
            break;
         case "$S3":
            returnValue = 19;
            break;
         case "$S4":
            returnValue = 20;
            break;
         case "$S5":
            returnValue = 21;
            break;
         case "$S6":
            returnValue = 22;
            break;
         case "$S7":
            returnValue = 23;
            break;
      }
      return returnValue;
  [B] }

   /*************************************************************
    *
    *   Test Code below
    *   Do NOT modify
    *
    ************************************************************/[/B]
  
   private static void testCases()
   {
      if (test_regToByte())
         System.out.println("RegToByte working well\n");
      else
         System.out.println("RegToByte failed\n");

      if (test_makeR())
         System.out.println("makeR working well\n");
      else
         System.out.println("makeR failed\n");

      if (test_makeI())
         System.out.println("makeI working well\n");
      else
         System.out.println("makeI failed\n");
   }

   private static boolean test_regToByte()
   {
      boolean passedTest = true;
      String[] regs = { "$ZERO", "$AT", "$V0", "$V1", "$A0", "$A1", "$A2", "$A3", "$T0", "$T1", "$T2", "$T3", "$T4",
            "$T5", "$T6", "$T7", "$S0", "$S1", "$S2", "$S3", "$S4", "$S5", "$S6", "$S7", "$T8", "$T9" };

      for (int i = 0; i < regs.length; i++)
      {
         passedTest &= testReg(regs[ i], i);
      }

      return passedTest;
   };

   private static boolean testReg(String regName, int expValue)
   {
      if (regToByte(regName) != expValue) System.out.printf("Fail: regToByte(\"%s\") = %d, should be %d\n", regName, regToByte(regName), expValue);
      return regToByte(regName) == expValue;
   }

   private static boolean test_makeR()
   {
      boolean passedTest = true;
     
      int i = makeR((byte) 1, (byte) 1,(byte) 1,(byte) 1,(byte) 1,(byte) 1);
      if (i != 0b00000100001000010000100001000001)
      {
         System.out.println("Test: makeR(1,1,1,1,1,1) = " + Integer.toBinaryString(i) + " failed");
         passedTest = false;
      }

      i = makeR((byte) 63, (byte) 0,(byte) 31,(byte) 0,(byte) 31,(byte) 0);
      if (i != 0b11111100000111110000011111000000)
      {
         System.out.println("Test: makeR(63,0,31,0,31,0) = " + Integer.toBinaryString(i) + " failed");
         passedTest = false;
      }

      return passedTest;
   };

   private static boolean test_makeI()
   {
      boolean passedTest = true;
     
      int i = makeI((byte) 1, (byte) 1,(byte) 1,(short) 1);
      if (i != 0b00000100001000010000000000000001)
      {
         System.out.println("Test: makeI(1,1,1,1) = " + Integer.toBinaryString(i) + " failed");
         passedTest = false;
      }

      i = makeI((byte) 63, (byte) 0,(byte) 31,(short) 0);
      if (i != 0b11111100000111110000000000000000)
      {
         System.out.println("Test: makeI(63,0,31,0) = " + Integer.toBinaryString(i) + " failed");
         passedTest = false;
      }

      i = makeI((byte) 63, (byte) 0,(byte) 31,(short) -1);
      if (i != 0b11111100000111111111111111111111)
      {
         System.out.println("Test: makeI(63,0,31,-1) = " + Integer.toBinaryString(i) + " failed");
         passedTest = false;
      }

      return passedTest;
   };

}

Аssembler can read and translate one line at a time. It does not need to read in the whole file first. In the example below, I cut and pasted nine lines into the running program. So you main program can be something like:
Until HALT ---- Read a line ------ Translate it ------- Print it

Output:


Assembler - Your Name Here

*** Begin entering Assembler:

ADD $v0 $v1 $zero
AND $a0 $a1 $a2
ADDI $a3 $t4 -321
ANDI $t0 $t5 123
BEQ $s0 $t1 +517
LW $s1 -12 $t2
SW $s2 20 $t3
SRL $a2 $a3 3
SLL $a3 $a2 31
HALT
***: 00000000011000000001000000100000
***: 00000000101001100010000000100100
***: 00100001100001111111111010111111
***: 00110001101010000000000001111011
***: 00010010000010010000001000000101
***: 10001101010100011111111111110100
***: 10101101011100100000000000010100
***: 00000000000001110011000011000010
***: 00000000000001100011111111000000

*** Assembly complete. Program required 9 words of memory.
 
Last edited by a moderator:
Physics news on Phys.org
You need to post code in [code] tags. Otherwise the bbCode parser will see [i] and interpret it as an opening italic tag. This makes your code difficult for the reader to follow. [code] also preserves indentation, again making your code clearer.

Mod note: I added code tags
 
Last edited by a moderator:
Margarita0076 said:
Homework Statement:: Assembler.java
Relevant Equations:: Create a mini-Assembler for a 32-bit MIPS processor.

I already wrote the regToByte method, but I don't understand how to write the makeI and makeR methods correctly.
The first step would be to find out what makeI and makeR actually are supposed to do. If you can't write that down, I don't think you will get far with systems programming.
 
  • Like
Likes Mark44
This is my first time encountering bit encryption in Java. My methods:

int makeR(byte opcode, byte rs, byte rt, byte rd, byte shamt, byte funct)
Constructs a 32-bit integer from the component parts for an R-type instruction.

int makeI(byte opcode, byte rs, byte rt, short immed)
Constructs a 32-bit integer from the component parts for an I-type instruction.

byte regToByte(String r)
Converts a string representation of a register to its numeric equivalent. For example, if you pass in “$s5”, it will return 21. Why 21? Check you green sheet, bottom righthand corner).
 
Margarita0076 said:
int makeR(byte opcode, byte rs, byte rt, byte rd, byte shamt, byte funct)
Constructs a 32-bit integer from the component parts for an R-type instruction.
Please describe what needs to be done by the function, in such a way that someone can build it. Do you want the research, the design AND the implementation to be done by the internet?
Hint: Do you have any experience with bit fields? (don't use c bitfields, but you need to make them yourself)
 
Margarita0076 said:
This is my first time encountering bit encryption in Java.
In this case, it's encoding; not encryption ##-## an 'assembler' produces machine instructions ('opcode') from mnemonic (readily-memorizable) 'source code' instructions.
 
Do you understand the formats of the R-type and I-type instructions? If you're expected to write code that generates MIPS instructions, you need to have a clear understanding of how the instructions are laid out and what each field represents.
Margarita0076 said:
int makeR(byte opcode, byte rs, byte rt, byte rd, byte shamt, byte funct)
Constructs a 32-bit integer from the component parts for an R-type instruction.
An R-format instruction has 6 fields, listed from most significant bits to least significant:
opcode - 6 bits
Rs field - 5 bits - first source register
Rt field - 5 fits - second source register
Rd field - 5 bits - destination register
Shamt field - 5 bits - shift amount
Function code - 6 bits - the specific R-format instruction

Margarita0076 said:
int makeI(byte opcode, byte rs, byte rt, short immed)
Constructs a 32-bit integer from the component parts for an I-type instruction.
An I-format instruction has 4 fields, listed from most significant bits to least significant:
opcode - 6 bits
Rs field - 5 bits - first source register
Rt field - 5 fits - second source register (can be destination register for some instructions)
Immediate or offset field - 16 bits - Holds the immediate value for instructions such as addi, andi, etc. Holds the offset value for instructions such as lw, lb, sw, etc.
 
Last edited:
  • Like
Likes Margarita0076 and sysprog
@Margarita0076, are you still stuck? You've started three threads, but haven't returned to any of them to let us know if you have been successful.
 

Similar threads

Replies
12
Views
2K
Replies
1
Views
2K
Replies
1
Views
2K
Replies
9
Views
2K
Replies
3
Views
2K
Replies
2
Views
4K
Back
Top