Java Bytecode Assembler Examples

# Examples

## Hello, World!

The king of all sample programs is shown and analyzed below:

    class HelloWorldApp
    {
      method public static void main (java.lang.String[])
      max_stack 2
      {
        getstatic java.io.PrintStream java.lang.System.out
        ldc "Hello World!"
        invokevirtual void java.io.PrintStream.println(java.lang.String)
        return
      }
    }

This program prints out "Hello World!". Note that this is a stand-alone Java application, NOT an applet. A line-by-line analysis of the program is shown below:

    class HelloWorldApp

This is the declaration of the class HelloWorldApp. Note that the assembler generates a .class file based on the name of the class, not the name of the .jasm file. The class declaration can also include modifiers such as abstract, final, public, and interface. The class declaration can be followed by the extends or implements clauses.

      method public static void main (java.lang.String[])

This is the declaration for the method named main. Note the similarity to the Java method declaration (except for the additional method keyword preceeding the declaration). This method takes as an argument an array of references to the class java.lang.String (as do all main methods).

      max_stack 2

This line declares what the maximum size of the stack will be (in this case, it is two). This line can be followed by a max_locals line to denote the maximum number of local variables. If there is no max_locals line, the assembler automatically calculates it based on the declarations of named local variables.

        getstatic java.io.PrintStream java.lang.System.out

This line says to get a reference to the static field out from the java.lang.System class and push it onto the stack. The field's type is java.io.PrintStream.

        ldc "Hello World!"

This line pushes the string "Hello World!" onto the stack. The ldc command can take any constant as an argument.

        invokevirtual void java.io.PrintStream.println(java.lang.String)

This line invokes the virtual method println found in the java.io.PrintStream class. The method takes a string as an argument (thus the ldc "Hello World!" command). Also, since this is a virtual method, a reference to an object must also be on the stack (thus the getstatic command).

Note that since methods can be overloaded, the entire method declaration (or signature) is required.

        return

This command causes the method to return void.

## A More Complex Example

The following example incorporates many of the more complex bytecode operands assembly language syntax. The program is nonsensical, and simply provides examples of various features of the assembler. The comments should provide assistance in understanding the code. The assembly code is shown below:

    class HelloWorldApp
    extends java.lang.Object
    {
      Field java.lang.String tester   /*field declaration*/
      Field int myintfield = 125

      Method public static void main (java.lang.String[])
      max_stack 5
      max_locals 12
      {
        /*Sample accessing a class's own field (by creating an instance of it)*/
        new HelloWorldApp 	/* create new instance of this class */
        dup 		/*duplicate the value on the stack (i.e. the
    			  instance of the class)*/
        invokenonvirtual void HelloWorldApp.<init>()
        HelloWorldApp myvar /* this is a variable declaration */
        store myvar 	/* store the instance of the class in myvar */
        load myvar
        ldc "Hello Country!"
        putfield java.lang.String tester /* store "Hello Country!" in tester */
        getstatic java.io.PrintStream java.lang.System.out
        load myvar 		/* This is here, cuz to get field, must have reference
    		   	   to the class instance on stack */
        getfield java.lang.String tester
        invokevirtual void java.io.PrintStream.println(java.lang.String)

        ldc 575
        lookupswitch default nowhere
        {
    	1       : mylabel
    	5       : mysecondlabel
    	3356    : mythirdlabel
        }

    nowhere:
        ldc 99
        tableswitch 85 to 87 default here
        {
            mylabel
    	mysecondlabel
    	mythirdlabel
        }

        /* sample use of long (or other constants) */
    here:
        long mylong
        ldc 558359L		/* should be ldc2_w, but assembler figures that out */
        store mylong	/* assembler generates lstore command */
        getstatic java.io.PrintStream java.lang.System.out
        load mylong
        invokevirtual void java.io.PrintStream.println(long)

    mylabel:
        /* sample use of double */
        double mydouble
        ldc 3.14159267		/* should be ldc2_w, but assembler figures that out */
        dstore 10	/* can use slot numbers or local var names here */
        getstatic java.io.PrintStream java.lang.System.out
        dload 10
        invokevirtual void java.io.PrintStream.println(double)

    mysecondlabel:
        /*sample use of array*/
        int[] myintarray 	/*variable declaration*/
        bipush 5 		/*number of elements in the array*/
        newarray int
        store myintarray
        load myintarray
        bipush 1 		/*index to store the upcoming value in*/
        bipush 49 		/*value to store in the array*/
        iastore
        getstatic java.io.PrintStream java.lang.System.out
        load myintarray
        bipush 1
        iaload 		/*gets the value from array and leaves it on the stack*/
        invokevirtual void java.io.PrintStream.println(int)

    mythirdlabel:
        /*sample use of array of references*/
        HelloWorldApp[]  myrefarray 	/*variable declaration*/
        bipush 5 		/*number of elements in the array*/
        anewarray HelloWorldApp
        store myrefarray
        load myrefarray
        bipush 0 		/*index to store the upcoming value in*/
        load myvar		/* this is a pointer to an instance of this class,
    			   it's the value to store in the array */
        aastore
        load myrefarray
        bipush 0
        aaload 		/*gets the value from array and leaves it on the stack*/
        ldc "Hello Country!"
        putfield java.lang.String tester /* store "Hello Country!" in tester */
        getstatic java.io.PrintStream java.lang.System.out
        load myrefarray
        bipush 0
        aaload 		/*gets the value from array and leaves it on the stack*/
        getfield java.lang.String tester
        invokevirtual void java.io.PrintStream.println(java.lang.String)
        /* Generic Hello World */
        getstatic java.io.PrintStream java.lang.System.out
        ldc "Hello World, Everyone!"
        invokevirtual void java.io.PrintStream.println(java.lang.String)
    myfourthlabel:    return
    myfifthlabel:
        pop
        return

        linenumbertable   /*sample only! doesn't correspond to specific file!*/
        {
          mysecondlabel 10
          mythirdlabel  14
          myfourthlabel 22
        }
        localvariabletable /*sample only! doesn't correspond to specific vars!*/
        {
          mysecondlabel mythirdlabel int myint 3
          mylabel myfifthlabel byte mybyte 2
        }
      }

      /* the init class (i.e. constructor) */
      Method void <init> ()
      max_stack 2
      max_locals 1
      {
        getstatic java.io.PrintStream java.lang.System.out
        ldc "In the init method!"
        invokevirtual void java.io.PrintStream.println(java.lang.String)
        aload_0 /* this is the instance of the class "passed" in as variable 0 */
        invokenonvirtual void java.lang.Object.<init>() /*call superclass init*/
        return
      }
    }