CSc 116 notes
Back
Next
Contents
4) Basic assembly language instructions
In this course we will be dealing with instructions on 3 different, relatively
low, levels. Starting from the lowest (found left to right in the SPIM
text segment window) they are:
-
binary machine instructions (shown in hexadecimal)
-
symbolic actual machine instructions. Registers shown numerically ($31)
-
assembly language (nicer) instructions, the ones you write in a source
file, registers can be referred to symbolically ($ra)
The correspondance is usually 1:1, however, since RISC is a Reduced
instruction set, some normal and useful assembly language instructions
can be coded as one or two other, less intuitive, instructions, so the
assembler provides a limited translation service. In this section, I will
only describe the nice instructions at level 3.
Load and store instructions
These instructions are used to move data between memory and the processor.
There are always 2 operands, a register and an address. Addresses can take
several forms, as we shall see, the simplest is the label of a data item.
In this example, a word (32 bits) is moved from Num1 to Num2, and a
copy is left in register $t0:
lw $t0, Num1 # load word, $t0 := Num1
sw $t0, Num2 # store word, Num2 := $t0
Note the order of the operands, the register is always first. The direction
of movement is opposite.
There are similar instructions to load and store bytes (8 bits), half-words
(16 bits), and double-words (64 bits)
Load immediate (constant)
There are also 2 instructions that load a constant, which is incorporated
into the instruction itself (immediate):
-
load immediate: li Rdest, Imm
# example: li $v0, 4
-
load address: la Rdest, label
# example: la $a0, prompt_message
Since a label represents a fixed memory address after assembly, la
is actually a special case of load immediate.
Note the difference between lw and la: If Num1 is at location [0x10001000]
and contains 0xfffffffe (-2), then
-
la $a0, Num1 loads 0x10001000,
while
-
lw $a0, Num1 loads 0xfffffffe
Arithmetic
Arithmetic is done in registers. There are 3 operands to an arithmetic
operation:
-
destination register
-
Source 1 register
-
Source 2 register or constant
The compact way of writing this pattern is: add
Rdest, Rsrc1, Src2
The following code calculates the expression (x + 5 - y) * 35 / 3
lw $t0, x #load x from memory
lw $t1, y #load y from memory
add $t0, $t0, 5 # x + 5
sub $t0, $t0, $t1 # x + 5 - y
mul $t0, $t0, 35 #(x + 5 - y)*35
div $t0, $t0, 3 #(x + 5 - y)*35/3
Arithmetic overflow, signed numbers
add, sub, mulo, & div check for overflow of signed
numbers, an incorrect result, in which the sign bit is improperly altered.
(mul doesn't do any checking). Usually we want to work with signed
numbers. The processor generates an exception, "arithmetic overflow," and
stops the program. This is preferable to generating incorrect results,
as is usually the case with older processors, which generate a "flag" which
programmers typically ignore.
Unsigned numbers
Sometimes we want to work with unsigned numbers. In this case overflow
checking is unwanted. Generally we append a u to the operation
code to express our intent. The unsigned operation codes are:
addu, subu, mulou, divu
This also applies to the short load instructions, lb and lh.
They normally fill the unused part of the register with the sign bit of
the short data. If we want to guarantee that the high part of the register
is filled with 0's, we can use lbu & lhu instead. For example,
we generally think of a character as an unsigned value.
Input and Output - System calls
Controlling the hardware responsible for input and output is a difficult
and specialized job, and beyond the scope of this course. All computers
have an operating system that provides many services for input/output anyway.
The SPIM simulator provides 10 basic services. The ones we will be using
right now are given here. The others are for floating point (real) numbers.
The call code always goes in $v0, and the system is called with syscall.
Service |
Call code |
Arguments
(input) |
Results |
print integer |
1 |
$a0 = integer |
signed decimal integer
printed in console window |
print string |
4 |
$a0 = address
of string |
string printed in console window |
read integer |
5 |
(none) |
$v0 holds integer
that was entered |
read string |
8 |
$a0=address to store
$a1= length limit |
characters are stored |
exit |
10 |
(none) |
Ends the program |
An example: A simple program to input and add 2 numbers
Prepared by Lin Jensen, Bishop's University, 20 January
1999
Back
Next
Contents