CmpSci 201 Project 2 Description ------------------------ In this project, you will acquaint yourself with functions, I/O, and numerical conversion. Getting rolecks --------------- Rolecks is available off of the course website (www.cs.umass.edu/~trekp/cs201). It is an executable Jar file, so any system running a reasonably recent version of Java should be able to run it. Make sure you get the latest version! Rolecks is regularly being extended and improved (read: bug fixes). Make sure you grab a recent copy before starting. Loading and running your code ----------------------------- You can write your code in your text editor of choice. To assemble it, click on the 'assemble file' button in rolecks. This will generate a simple binary version of the file (if the file was named foo.s the binary form will be named foo.bin). To load up the binary, click on the 'Open Executable' button in rolecks. The problem ----------- The problem is to read a number inputted by the user and then inform the user whether or not it's a perfect square by outputting "Yes" (and the number of which it is a square) or "No". For this project you can salvage your work from project 1 to do the actual computation to decide on the "squareness" of the input value. If your code didn't work, or you are for some reason unwilling to use it, you can use the example code available from the web page. The actual work of the project is going to be writing functions to get the user's input, parse it, and write out the resulting value. Getting the user input ---------------------- Use the I/O routines discussed in class to read user input (one character at a time). SWI #h00F00001 will read a character from input and place the ASCII value in R0. To input values, simply type them into the text entry field labeled "Standard Input". When you've got the string you want inputted, hit enter. The string will now be available to read with the SWI #h00F00001 system call. Note that the carriage return will NOT be part of the string. If you haven't entered a value into the system, SWI #h00F00001 will simply write 0x0 to R0 (this is the value of ASCII NULL). The user will be able to input values in either decimal or hexadecimal. Hexadecimal values will be prefixed with "0x" (e.g. "10" is the value 10, "0x10" is the value 16). You will need to read in values one character at a time, so remember that these are NULL terminated strings. The user input can be incorrect (e.g. "zorba" or "0xFISH"), but it will NOT exceed 16 characters in length, nor will it exceed the maximum value that you can represent in a 32-bit register (namely 0xFFFFFFFF). If the input is incorrect, you will need to output the string "Incorrect input.\n" to standard out. See the following section on output for details. You may assume that the letters input for hex will all be upper-case, but making your code work with lower-case values shouldn't be too hard either. Parsing the user input ----------------------- After you get the string from the user, you need to parse it. Remember that ASCII values for the numerical and alphabetic characters do NOT correspond to their value as a digit. So you'll have to do a series of comparisons in order to determine the value of a digit. On the plus side, ASCII values are 8-bits wide, which means they fit within the ARM's funky immediate field, so you can write them as constants within your code. So, after figuring out what a given character's value is, you'll need to ascertain its value in accordance with its position in the string. This can be a little tricky. I recommend STRONGLY writing out this algorithm in Java or pseudo code and testing it before you start coding it up in ARM. Once you have converted the user's string to a numerical value in some register, you can then jump into the code for project 1 and get crunching on the number. Outputting to the user ---------------------- When you have determined that the user's number is square or not, you need to tell them your result. There are three cases: 1) Input is a perfect square: In this case, output the string "Yes: 0x\n" where is the number of which the input was a square. For example, if the input was 25, the output will be "Yes: 0x5\n". 2) Input is not a perfect square: In this case, simply output the string "No.\n" 3) Input was incorrect: In this case, the incoming value is not a number, so output the value "Incorrect input.\n" To generate these output strings, you'll need to use SWI 0x00F00002 to output the characters one at a time. You may also have to convert a numerical value in a register to a string representing a hexadecimal number. This is complicated by the fact that the ARM has no generic division operator. But remember that ASR (arithmetic shift right) is equivalent to division by a power of two (e.g. ASR #4 is the same as dividing by 16). Alternatively, you could utilize the fact that every four bits of a binary value corresponds to a hex digit and use masking and shifting to generate the characters (this requires no looping division). I recommend the second technique, but you are free to do whatever your programming heart desires. Hints ----- The single biggest hint I can give you is to USE FUNCTIONS. I will be flabbergasted if you manage to hack together a fully functional and correct monolithic hunk of code (without actually implementing it as functions first and then just globbing it together after the fact). You'll need more than three functions as well. Getting and parsing the input will take several functions, as will generating the output. Also, take a little time to plan out your code. Don't just jump in and hack away. If any part of the project confuses you, write out the code first in Java and then TEST the Java before you convert it to ARM. Testing your code ----------------- To test your code, you just need to type in valid (or invalid, but under 16 chars long) input into the Standard Input entry area. Output values will appear in the Standard Output window. Of course, this doesn't help you test or debug the parsing code. To do that you may need to use breakpoints. A breakpoint is basically a stopping point in the code. To set the breakpoint, click the "Set Breakpoint" button (note, you need to have code loaded before it becomes active). This will open a dialog that'll query you for a PC value to stop at. This is why the disassembled output has the PC as the first value. So, to find the PC, go to the line of code you're interested in and use the hex number at the far left (the one with the colon after it). That's the value you want to set a breakpoint at. When the breakpoint is set, you can run the program. When (and if) the code reaches your breakpoint, execution will stop and you'll be able to inspect register values. Note that the PC that rolecks stopped at will be highlighted in the code window. Here you can either change register values (by clicking on the register), or step through the code one instruction at a time. To do this, you simply click on the "Step/Debug" button. This will advance the program by one instruction (the highlight will move to reflect the change in the PC). By slowly stepping through your code and watching the registers change, you should be able to ascertain where your code goes wrong. Submitting your code -------------------- Submit your code by e-mailing to trekp@cs.umass.edu a message with: "CS201 Project 2 Submission, " in the subject line, where "" is replaced with your actual name. Attach the source code, which should be in a file named "proj2.s" to the message.