A Gentle Guide to Using the LC-3 Simulator

0. Conventions

Throughout this document, commands that you have to type or buttons you have to click will appear like so.

1. Getting Java

The LC-3 Simulator is written in Java, which means Java must be installed on the computer you plan to use. Java should already be available on all public SEAS machines. If you plan to work on your personal machine, you may need to install Java yourself. You can download Java here. The LC-3 simulator requires Java 1.4 or newer (which is available for Windows, Linux, and Mac OS X).


2. Getting the Simulator

Next, you need to download the simulator. It is distributed in a .jar file (short for Java ARchive) which you can download here. In Windows or on a Mac, you should be able to double-click the .jar file to launch the simulator. You can also launch the simulator from the command line (shell in Linux or command prompt in Windows) of your operating system (Linux/Unix) by using the command:

java -jar (jarfile)

The Simulator version is 1.2.5 (r436). You should see the simulator screen, much like the screenshot below.

LC-3 simulator screenshot


3. Assembling and Loading LC-3 Programs

Now the simulator is running, but to get it to do anything interesting, we need to load some software. The first piece of software we should load is, naturally, an operating system. The LC-3 operating system is very basic: it handles simple I/O operations and is responsible for starting other programs, such as the ones you will write for lab and homework assignments. Download the LC-3 OS here (right click to save).

So that you can understand what the operating system does, we distribute it as an assembly language file. But the LC-3 machine doesn't understand assembly directly; we first have to 'assemble' the assembly code into machine language (a .obj file containing binary data). The LC-3 simulator has a built-in assembler, accessible (as is the case for most of its functionality) via the Command Line text box (see screenshot above). To assemble the operating system, type as lc3os.asm at the command line and hit enter. Make sure that the lc3os.asm file is in the same directory as the .jar file; the as command also understands relative and absolute paths if the file is in a different directory. Output from the assembly process is displayed in the CommandLine Output Pane. After assembling the operating system, you should notice that 2 new files, lc3os.obj and lc3os.sym, have been created in your directory. The .obj file is the machine language encoding of the assembly language file, and the .sym file is a text file that holds symbol information so the simulator can display your symbols. Recall that symbols are really just a convenience for humans; the machine language encoding knows only about offsets.

Now we can load the lc3os.obj file into the simulator, either via the command load lc3os.obj or by going to the File menu and selecting Open .obj file. Notice that the contents of the memory change when the OS is loaded.

Now assemble and load a sample assembly language program file into the simulator, using the "as" and "load" commands.

When you load the program into memory, the memory contents will change, but you may not notice since the relevant memory addresses (starting at x3000) aren't visible unless you've scrolled down the screen. User-level programs (i.e., non-OS code) start, by convention, at x3000. If you type the command list x3000 the memory view will jump to x3000 and you can see the instructions that you have loaded.

4. Running Code

To actually run code, you can use the 4 control buttons at the top of the simulator, or type commands into the command line interface (the command names are the same as the buttons). Note that the PC register is set to x0200, which is the entry point to the operating system by convention. However, we loaded our program to start at address x3000. So you need to manually modify the PC, using the command set PC x3000. You should see the PC value get changed in the Registers section, and the instruction at line x3000 get highlighted in the Memory section.

In the sample program that you compiled and loaded in the previous step of this tutorial, the value in register R3 gets incremented. Before running the program, set the value in R3 to any value you like, either by double-clicking it in the Registers section, or via the command set R3 (value). Note that you can do the same for the values held in memory addresses, though you don't need to do so for this tutorial.

You're finally ready to run your program! You can step through the code by clicking the the next button. Note that three things happen:

  1. the value in R3 gets incremented in the Registers section
  2. the value of the PC gets incremented in the Registers section
  3. the highlight moves to the next line in the Memory section

When you click next again, the "HALT" instruction will get executed. When this happens, the operating system takes over, and the PC is set to x0263 so that the OS can take care of necessary cleanup. Note also that the Status Display (upper right hand corner) tells us the machine is halted.

Note: Both next and step do pretty much the same thing. The LC-3 Manual has a more involved discussion, with an example of the difference between them.

4a. Let's try that again!

Let's try running the program again. Notice that from the halted state, the PC points to an instruction that will branch us right back to the start of the operating system ("BR OS_START"). So we can hit next once and go back to the beginning of the operating system, at address x0200.

Note that (most of) the registers are as we left them. Sometimes, having old values lying around everywhere can be problematic, and you can do a real "reboot" via the reset command, but be aware that this clears all of memory and resets registers to default values, so you'd have to reload the OS and your program. So don't do that now.

If you hit next a few more times, you should see some OS code get executed, and eventually you will hit the RTT instruction at location x0205, which jumps to the start of your program at x3000. This runs the program again, and if you keep hitting next, you'll keep seeing your program get executed until you can't take the excitement anymore.

4b. Breakpoints

Going one instruction at a time is great, but somewhat tedious. On the other hand, if you don't want to step through the program, you can click the continue button, but the simulator will fly through your program up until it gets to a halting point (try this out, and notice that the value in R3 is increasing each time, even though you don't see the lines of code one at a time anymore).

We need a happy medium between not knowing what's going on at all, and having to go through every single instruction, whether we care about it or not. Breakpoints are this happy medium.

A breakpoint is set at a particular memory location, and tells the simulator to stop execution upon reaching that point. Memory locations with breakpoints set on them show up in the simulator with a red square in the "BP" column. It is left as an exercise to the reader to determine what "BP" stands for. You can set a breakpoint at a memory location with the command break set (memory location), or by checking the checkbox in the "BP" column. You can get rid of a previously-set breakpoint with the command break clear (memory location), or by un-checking a previously checked box. You can also set and clear breakpoints at labels, instead of specifying a hex memory location.

When you tell the simulator to continue, it will only run until it hits a breakpoint (or the system halts or has an error). When you are writing and testing your answer for Problem 0, you can use the command break set START to set a breakpoint at the beginning of your code. Then, you can use continue to skip all the OS code and get to the instructions you care about. Then you can next over your code to make sure it's doing what you want it to do.

5. Running Scripts

"Scripts" are typically plain-text files that include a sequence of commands. Using a script allows you to specify that sequence just once, and saves you the agony of typing the same thing over and over and over again. The LC-3 simulator lets you use scripts that contain the commands that you've been typing into the command line in the Controls section (like assembling and loading files; setting the PC; initializing registers; etc.).

Download the sample script for the program we've been playing, and put it in the same directory as the other files. You can view it with a text editor and you will see that it's merely a plain-text file containing the different commands. Now try running the test script with the command script sample.lcs.

6. General Help and Advice

This document doesn't cover all of the simulator's functionality; for an extended discussion of usage see the LC-3 Simulator Manual. For quick help within the simulator itself, you can use the help command to see a list of all of the LC-3's commands. Use help (command) to get help on a specific command.

Many of the LC-3 commands have shortcuts - b is short for break, n for next, and so forth. Use the help (or h) command to see what shortcuts exist.

The LC-3 Command Line has a history feature - use the up and down arrow keys to go backwards and forwards through the commands you've previously entered.

If you resize the simulator window to make it bigger, the Commandline Output Pane will grow. If you have a small screen and the Commandline Output Pane still isn't big enough, you can open an external, resizable Command Output Window by selecting the Open Command Output Window option from the File menu. This lets you see a lot more output from the commands you run, and is particularly useful for viewing the errors the assembler generates.

Original Document by Milo Martin
Modified by Diana Palsetia.
Last updated by Chris Murphy, October 20, 2010.