COMP15111 – 2015 – Javier Navaridas/Richard Neville/Milan Mihajlovic – Lab 5: A Simple Virtual Machine 12 5 COMP15111 Lab 5 – A Simple Virtual Machine Duration: 1 lab session 5.1 Aims To experiment with a simple virtual machine, based on JVM, and obtain more practice in converting Java statements into ARM assembly code. 5.2 Learning Outcomes On successful completion of this exercise a student will: – have experience of implementing and using a simple virtual machine (“interpreter”) 5.3 Summary You are given a Java program that implements a Simple Virtual Machine (SVM) based on JVM, and some simple programs written using SVM, which you can run. You are also given the framework of an ARM assembly code program based on the Java program, which you have to complete. You can see the JVM specification, including mnemonics, at: http://docs.oracle.com/javase/specs/ Each lab exercise has the usual deadline at the end of your scheduled lab session. If you attend the lab you will, if you need it, get an automatic 7-day extension. This is so that you can get help in the lab and then have some time to make use of that help to complete the exercise. This will be the case for all your labs for this course-unit. Remember that you must use “submit” in the usual way to show that you completed your work by the (extended) deadline. If you decide to complete the exercise after our labs shut in the evening, it is your responsibility to make sure that you can “submit” remotely. 5.4 Description As usual, you will need to copy the starting files to your lab directory and run KMD: > cd COMP15111/ex5 > cp /opt/info/courses/COMP15111/Lab/ex5/* . > start komodo 15111& The file “VM.java” contains the original Java program for part 1 only, and “VM.class” contains the compiled Java program for both parts 1 and 2. If you want to, you can read “VM.java” or run “VM.class” (as below) to see how your completed ARM program should behave if you have done everything correctly. (If you compile “VM.java” by mistake, you will have to copy “VM.class” again to be able to see what should happen for part 2.) To run the program, type: java VM 1 to run the SVM used for part 1, or: java VM 2 to run the SVM used for part 2. For either part, you can turn on tracing, to see each individual SVM instruction executed, by adding an extra command-line parameter “trace” e.g.: java VM 1 trace or: java VM 2 trace There is another file, “VM.s”, that contains (a slightly modified version of) the Java program as a set of comments, with some ARM code that mainly deals with the output; this is the file that you will be editing. The main difference between the Java and ARM versions of this program is that KMD cannot deal with command-line parameters, so tracing is always turned on. 5.4.1 SVM – A Simple Virtual Machine, based on JVM SVM corresponds to a tiny subset of JVM, with many of the instructions greatly simplified: – SVM only uses integers e.g. for variables and arithmetic. – SVM code consists of a series of integers, rather than bytes. Therefore, any literals that follow the instruction codes (e.g. the constant stacked by “bipush”, or the address for a“go to”) are single integer values, rather than a series of byte values that together make up the literal. – SVM does not know about methods, or method invocation. Therefore, the “iload” and “istore” instructions, that access variables, use an extra array of integers to hold these variables, rather than a stack frame. – Instructions that might be useful, but are not needed in the examples, have been omitted e.g. some arithmetic and logical operations. COMP15111 – 2015 – Javier Navaridas/Richard Neville/Milan Mihajlovic – Lab 5: A Simple Virtual Machine 13 There are also two extra SVM instructions, that do not correspond to anything in JVM: – “iprint” outputs an integer value (popped from the stack). – “stop” stops the SVM program. 5.4.2 Part 1 For this part, you should edit the assembly-code file that you are given, “VM.s”. As usual, this file contains the Java program as a set of comments, with some ARM code that mainly deals with the output. However, to simplify the problem, you are also given extra pieces of ARM code, mainly dealing with the various arrays (“code”, “stack”, and “vars”). All three are declared for you, and “code” is initialised with the SVM instructions. You are also given a set of routines written in ARM code that access the various arrays. To make use of one: first, if necessary, load R0 and maybe also R1 with some parameters, then call it, using the “BL” command, and finally, use any result left in R0. The routines are: – “getCode” gets an integer value from the SVM program i.e. does R0 = code[vmPC] (you usually, but not always, need to increment vmPC after calling this routine) – “popR0” pops a value off the SVM stack, i.e. does R0 = stack[vmSP++] – “pushR0” pushes a value onto the SVM stack, i.e. does stack[--vmSP] = R0 – “getVars” fetches a value from an SVM variable, i.e. does R0 = vars[R0] – “putVars” stores a value into an SVM variable, i.e. does vars[R1] = R0 There are three main variables in the original Java program, “vmPC”, “vmSP”, and “done”, that you should keep in registers R2, R3 and R4 respectively. You can use the usual register names e.g. ADD R2, R2, #1 or the “RN” declarations you have been given allow you to use the variable names directly as register names e.g. ADD vmPC, vmPC, #1 The main part of the code that you have to write is a switch statement, dealing with each of the different SVM operations. You are given a table of addresses called “switch”, initially all set to “default”. You should start by just completing the “default” code, which prints the value of some useful variables and then stops the program. When you actually run the program, this information will tell you which SVM operations you need to implement, and you can fill in the cases in the switch statement one-by-one as you need them. Note: some of the cases in the switch correspond to SVM operations that are not used in part 1, so don’t worry about them. 5.4.3 Part 2 You should save a copy of your answer to part 1 before you start part 2. For this part, you should change your code to initialise “vmPC” to 30 instead of 0, and then proceed in a similar way to part 1, except that you have to work out for yourself what to do for the missing SVM operations. To run the SVM used for part 2, type: java VM 2 or: java VM 2 trace (If you compile “VM.java” by mistake, you will have to copy “VM.class” again to be able to see what should happen for part 2.) This lets you see what results you should get from your program but does not tell you what the missing instructions do (iadd & if icmplt). If you can’t guess what they do, links to the JVM manuals are given on the course-unit web-page and at the start of the script for this exercise. 5.5 Marking Process There are 7 marks for part 1 and 3 marks for part 2. (You cannot get different parts marked on different days.) When you have completed the exercise, you need to run submit (making sure you are in the correct directory – COMP15111/ex5 for this exercise). After this, run labprint (again, make sure you are in COMP15111/ex5), collect your marking sheet from a printer and then ask a demonstrator to mark your work (you may need to add your name and seat number to a list of those queueing to be marked). You must get your work marked during your next scheduled lab – i.e. in the extra marking session in the last week of term – (unless have a good excuse e.g. that you were ill).