This lab writeup is a work in progress. Please do not begin if you see this message.
Lab 6 - Toy Assembly
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.
Lab Goals
After this lab, you should:
- Understand general format of assembly (similar to AT&T syntax of x86-64)
- Understand how ToyASM maps to our Toy ISA
- Be able to write code using assembly
Getting Started
In this lab, we will be using the CS portal to write and run our code. Please refer to Lab 1 for details on getting connected.
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), and memory at an immediate address to a register (icode 6.0).
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 value0x53
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)
. - 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 Programs
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:
- Rewrite your fibonacci code from Lab 5 in our ToyASM.
- Note how different and more readable your code is in the assembly
- How does the assembled binary compare with the binary you wrote in Lab 5?
- Write X in ToyASM.
Check-off with a TA
To check-off this lab, show a TA
- Your fibonacci ToyASM assembly code
- X in assembly and running in a simulator