Skip to main content Link Menu Expand (external link) Document Search Copy Copied

Lab 6 - git and ToyASM

Wouldn’t it be great if we did not need to write binary to program our machines? In class, we will soon be discussing x86-64 assembly, which is a more readable representation very close to the binary machine code, allowing us to program our computers (and the portal) more directly. In this lab, we will consider a simpler version of assembly language that directly maps to the Toy ISA we have been programming in over the past few weeks.

But before we get to that, we’ll cover some basics of git version control.

Lab Goals

After this lab, you should:

  1. Know git basics such as init, clone, add, push, fetch, and pull
  2. Understand general format of assembly (similar to AT&T syntax of x86-64)
  3. Understand how ToyASM maps to our Toy ISA
  4. Be able to write code using assembly

Getting Started

In this lab, we will begin using the CS portal to write and run our code. Please refer to Lab 1 for details on getting connected.

ssh mst3k@portal.cs.virginia.edu

git

We’ll use git in this class, and many other classes that follow. Git is a versatile tool that does many useful things; among them are

  • It stores all versions of your files so you can recover from mistakes
  • It lets you move files between machines easily
  • It lets multiple people collaborate on a project with minimal coordination
  • It lets you set up “hooks” to automatically run when things change

Broad overview

  • Several computers will be involved
  • Each will have a complete copy of the history of every file
  • On a single computer,
    • Each file has two places it is stored: the working directory (which is where you’ll work on it) and a hidden git-managed copy (which is where git will track versions, communicate with other machines etc)
    • When you edit a file, git considers it either “untracked” or “modified”
      • an “untracked” file has no copy in the git-managed space
      • a “modified” file has been changed from the last git-managed version
    • “adding” a file tells git to care about your changes to it (i.e., you’re “staging” the file for commit).
    • “committing” a file tells git top update the git-manages copy to match your version. You can only commit added (i.e., staged) files.
  • Working between computers,
    • you can “push”, saying “remote computer, you should know about what I’ve done lately.”
    • you can “pull”, saying “remote computer, what have you done lately?”
    • In general you have to both pull and push if you want your copy and the remote copy to become the same.

Creating a project

For this class, you should only need to create a server-side repository once or twice. We’ll start by creating a place to store our repositories, then initialize our first server-side repository to hold code for labs.

Location for repos

Create a place to store your server-side repos:

mkdir repos

Our first server-side repo

Now, cd into that directory and create your first server-side repository. In general, once we create these, we will not interact with them; they will store our code in an organization scheme that git understands but is not human readable.

cd repos
mkdir cso1-code.git
cd cso1-code.git
git init --bare

If this was successful, you will see the following notice about an empty repository being created:

Initialized empty Git repository in /u/mst3k/repos/cso1-code.git/

Working copy on portal

Now we are ready to check out a working copy of this repository so that we can actually begin coding! Return to your home directory before continuing: cd ~.

To check out a working copy of a git repository, we “clone” the repository. The general format of this command is git clone REPOSITORY-LOCATION, where the location is either a URL (such as GitHub), an SSH server and path, or a full path to a git repository. Let’s clone the server-side repository we created a few moments ago (replace mst3k with your computing id):

git clone /u/mst3k/repos/cso1-code.git

Once you issue the command, git should confirm that it cloned the repository into a new directory, cso1-code.

cd into your working copy.

Using git

We expect the most common case will be you’ve created or modified a file on the portal and want to get a local version on your laptop to submit to Gradescope. Let’s go through this step by step, assuming you start on the portal in the working directory of your git repository.

git pull

Before we make any changes to local files, let’s have git check to see if some other computer (such as our laptop) has also made changes that you’ll need to merge. We don’t expect that to happen very often this semester, but you should get into the practice of always git pull before git push.

git add file1 file2 ...

Tell git which files you want to commit into the version history. Any changes to these files will be “staged” for commit so that the current state of the files can be saved into the version control system. Adding and then committing files often will help ensure that we can always revert to an older version if something goes wrong. It is also a convenient way to sync our files to another client, i.e., our laptops.

If you want everything in the current directory to be added, you can use git add ..

git commit -m "I changed a few files"

Tell git to update it’s internal copy of the files you’ve added and label this change “I changed a few files”. Using good descriptive labels becomes more important as project teams grow, so you should be more specific here. For example, “Added the instructions that save the PC for the jump instead of hard coding the memory address.”

You can add and commit in one step if you have only modified (not added) files by using git commit -a -m "fixed typos"

git push

Ask git to send your changes to the main repository on the remote server.

Your Laptop’s Local Copy

We also want a local working copy on our laptops. This will allow us to git pull the changes we made on the CS portal to our laptop and then upload them to Gradescope. In order to clone (i.e., set up a local working repository based on the server’s version) to your laptop, you’ll need to use the full address of the server.

You may need to install git to continue. If you have a Mac or Linux machine, you likely already have git installed. Windows users will need to install git. Use the following links to install it if you do not already have it.

Windows: git for Windows
For Windows, it may be easiest to use the Standalone Installer or the winget tool.

Mac: git for Mac
For Mac, git may be provided with your Xcode install, or you can install it with homebrew.

Once git is installed, from your local Powershell or Terminal, cd into the directory you want your local copy to reside, and enter the following git command:

git clone mst3k@portal.cs.virginia.edu:repos/cso1-code.git

Once your laptop has cloned the git repository, you should now see a cso1-code directory/folder with the same contents as your working directory on the portal nodes. You can follow the same steps locally to edit files and then sync them to the server.

In general, when using git to manage your source code, it’s helpful to follow these steps:

  1. git pull - get any changes from the server
  2. Edit the files
  3. git add ... - stage the changes you made to your files so that they can be committed to the version history
  4. git commit -m "your message" - commit the changes to your local repository (not on the server yet). It may be helpful to do steps 2-4 as you’re editing, in case you decide you want to roll back some changes if something breaks.
  5. git push - push the committed changes to the server

After editing your files on the portal, you can issue a git pull command from your laptop’s working copy to get the newest files from the server.

Additional Tutorials

There are several tutorials you may find useful. Don’t feel that you have to do all of these (unless you want to and/or you need to still learn it), but doing at least one all the way through may help you feel more confident. You should probably do them on your own time, though, not during lab time.

  1. https://git-scm.com/docs/gittutorial
  2. https://try.github.io/
  3. https://learngitbranching.js.org/
  4. https://rogerdudler.github.io/git-guide/
  5. https://guides.github.com/introduction/flow/
  6. https://guides.github.com/activities/hello-world/

Toy Assembly

We will define a new language, ToyASM, that will make it easier to program our Toy ISA. It supports all of our icodes and operations from Lab 4, but with more human readable code than the bits we have been writing so far.

Each line in our code will consist of a single instruction with an operation and one or two operands, as follows:

operation source, destination

Definitions

Labels

When writing our ToyASM code, we may want to “remember” a location in our code so that we can jump to it later; i.e., to support loops and if statements. If a line in our code consists of only lower-case characters (a through z) followed by a colon, such as:

mylabel:

then this defines a label in our code. The assembler will remember the address of the next instruction in the code and replace the label with the correct memory address when producing the machine code.

Operations

Our Toy ISA has 14 total operations based on our 8 icode values and additional operations from icodes 5 and 6. We can represent all of those instructions using the following operations:

mov
Move/copy a value from one place to another. We can move from register to register (icode 0), memory at a register value to a register (icode 3), a register value to memory at a register’s value (icode 4), an immediate address to a register (icode 6.0), and memory at a given immediate address to a register (icode 6.3).
add
Add a value from one place to a register’s value. We can add a register value to another register’s value (icode 1), or add an immediate value to a register’s value (icode 6.1).
and
Bitwise and a value from one place to a register’s value. We can and a register value to another register’s value (icode 2), or add an immediate value to a register’s value (icode 6.2).
neg
Negate a register’s value based on two’s complement (icode 5.1); updates the given register’s value.
not
Bitwise not of a register’s value (icode 5.0); updates the given register’s value.
lnot
Logical not of a register’s value (icode 5.2); updates the given register’s value.
jump
Compares the value in the first operand register to 0. If it is less than or equal to 0, then jump to the location (address) stored in the second operand register (icode 7).
movpc
Save the current pc value into the operand register (icode 5.3).
halt
A special instruction for our machines that will produce an instruction with reserved bit = 1, so that the code can be run on our simulators.

Operands

Our operands may take on multiple forms:

Registers
Registers are denoted using the %. For example, to write “register 2”, we would write %r2.
Literals
Literal values (immediates in our Toy ISA) are specified using a $. That is, to write the hex value 0x53 in our assembly language, we would write $0x53.
Memory Accesses
Our operand may be a value from memory instead of a value from a register or an immediate. Parentheses are used for a memory access as an operand; for example, to read memory at the address stored in register 1, we would write (%r1).

If we want to read from memory at an immediate (i.e., icode 6.3), we would write that value directly in the parentheses without the $ used for normal literals. For example, to read the value at memory location 0x74 into register r0, we would write:

  mov (0x74), %r0
Labels
Since we are no longer writing bytes, jumping to a particular location in our code becomes tricky. Therefore, we can move a “label” into a register. Due to the limitations of our ToyISA, a label may only be moved into a register in the following way:
  mov mylabel, %r1

Note: when assembled, the binary generated from this instruction will move the address of the instruction following the mylabel: into register 1.

Example Instructions

Consider the following example instructions. For each instruction below, we display a python/Java-like syntax, the binary and hex from our Toy ISA, and the ToyASM assembly instruction.

Code Toy ISA Binary Toy ISA Hex ToyASM
r0 = r1 0000 0001 01 mov %r1, %r0
r3 = 0x42 0110 1100 0100 0010 6C 42 mov $0x42, %r3
r2 += r1 0001 1001 19 add %r1, %r2
r0 += 0x9A 0110 0001 1001 1010 61 9A add $0x9a, %r3
r3 = M[r2] 0011 1110 3E mov (%r2), %r3
M[r1] = r0 0100 0100 44 mov %r0, (%r1)

Example Programs

Here are a few example programs in code, hex (binary), and ToyASM to compare. As we begin moving towards x86-64 assembly over the next week, it will be helpful to see how assembly compares with the underlying binary instructions.

Subtraction

Compute 0x42 - 0x15. This can be achieved in the following python-like pseudocode:

x = 0x42
y = 0x15
z = x - y

Compare that with our Toy ISA and ToyASM instructions:

CodeHexToyASM
r0 = 0x42
r1 = 0x15
r2 = r1
r2 = -r2
r2 += r0

60 42
64 15
09
59
18
80
mov $0x42, %r0
mov $0x15, %r1
mov %r1, %r2
neg %r2
add %r0, %r2
halt

Modulo

Compute 0x94 % 0x21. This can be achieved in the following python-like pseudocode:

x = 0x94
y = 0x21
while (x > 0)
    x -= y
x += y
return x

Compare that with our Toy ISA and ToyASM instructions. Note that we must first modify our loop slightly to the following pseudocode:

x = 0x94
y = 0x21
x = -x
while (x <= 0)
    x += y
x = -x
x += y
return x
CodeHexToyASM
r0 = 0x92
r1 = 0x21
r0 = -r0
r2 = pc
r0 += r1

if (r0 <= 0) jump to r2
r0 = -r0
r0 += r1
r1 = 0xD0
M[r1] = r0

60 92
64 21
51
5B
11

72
51
11
64 D0
41
80
mov $0x92, %r0
mov $0x21, %r1
neg %r0
top:
add %r1, %r0
mov top, %r2
jump %r0, %r2
neg %r0
add %r1, %r0
mov $0xd0, %r1
mov %r0, (%r1)
halt

Assembling to Binary

We have provided an assembler to assemble (compile) our ToyASM to Toy ISA binary code. You can run this directly on portal using the following command:

/p/cso1/toyassemble my_asm_file.tasm

When run, our assembler prints out the corresponding hex digits for our binary program. You may then copy/paste this code into our online simulator or save it as a text file to use with your simulator from lab 4.

Your Task

In this lab, we will ask you to:

  1. Create a git repository (repos/cso1-code.git) and local working copy (cso1-code) on the portal, following the instructions in the git section above.
  2. In your local working copy, write a multiply program (multiply.tasm in our ToyASM that calculates \(\lvert x \times y \rvert\) (that is, the absolute value of x * y) and stores the final result in register 0.
    • It may help to start out similarly to how we began homework 1; for example, we could start by loading two immediate values into registers 2 and 3, then calculating r0 = r2 * r3.
         mov 0x10, %r2
         mov 0x03, %r3
      
    • Note how different and more (or less) readable your code is in assembly than your modulo code from homework 3 (and our examples above).
    • How does the assembled binary compare with the binary you wrote in Lab 5?
  3. Assemble your code with our assembler into Toy ISA binary (hex) and try it out on the online simulator.
  4. Commit your file to git (git add, git commit -m "...") and push it to the server (git push).
  5. Clone your repository to your local laptop and ensure that you can pull from the server (git pull).

Check-off with a TA

To check-off this lab, show a TA

  • Run git log in your cso1-code directory on the portal to show that you have changed files
  • Your multiply ToyASM assembly code (on the portal)
  • Run git log in your cso1-code directory on your laptop

Copyright © 2023 John Hott, portions Luther Tychonievich.
Released under the CC-BY-NC-SA 4.0 license.
Creative Commons License