Professional Documents
Culture Documents
Example (2.3): For the following C statement, what is the corresponding MIPS assembly code?
Assume that the variables f, g, h, i, and j are assigned to registers $s0, $s1, $s2, $s3, and $s4,
respectively. Assume that the base address of the arrays A and B are in registers $s6 and $s7,
respectively: B[8] = A[i-j]
# Allocate:
# $s0 = f, $s1 = g, $s2 = h, $s3 = i, $s4 = j
# $s6 = A, $s7 = B
Alternatively:
Example (2.9): Translate the following C code to MIPS. Assume that the variables f, g, h, i, and j are
assigned to registers $s0, $s1, $s2, $s3, and $s4, respectively. Assume that the base address of the
arrays A and B are in registers $s6 and $s7, respectively. Assume that the elements of the arrays A and
B are 4-byte words: B[8] = A[i] + A[j];
# Allocate:
# $s0 = f, $s1 = g, $s2 = h, $s3 = i, $s4 = j
# $s6 = A, $s7 = B
● the leftmost or “big end” byte as the word address. Thus big endian refers to reading the
memory address from left to right. Big endian has what's referred to as big end, i.e., the 2
leftmost bits.
● the rightmost or “little end” byte as the word address. Thus little endian refers to reading the
memory address from right to left. Little endian has what's referred to as little end, i.e., the 2
rightmost bits.
NOTE: MIPS is in the big-endian camp. Since the order matters only if you access the identical data
both as a word and as four bytes, few need to be aware of the endianness. Byte ordering is only a
problem when exchanging data among computers with different orderings.
Shift left << sll (shift left logical) Useful for multiplying by a power of 2
Shift right >> srl (shift right logical) Useful for dividing by a power of 2
Shifting
Shifts move all the bits in a word to the left or right, filling the emptied bits with 0s.
Shift Left Logical
The instruction sll shifts all bits in the 32-bit data word to the left of the specified number of places,
from 1 to 31. The vacated positions are automatically filled with zeroes, which are proportional to the
n-bit left shift (i.e., shift 𝑛 left, then 𝑛 right positions will be 0s). The 𝑛 bits shifted out of the word are
lost.
For example, assuming that $t0 = 0xC0FEFE (0000 0000 1100 0000 1111 1110 1111 1110𝑡𝑤𝑜), a left
shift of 3 looks as follows in MIPS:
Now $t1 = 0000 0110 0000 0111 1111 0111 1111 0000. In decimal, $t0 is 12648190 and the
3
result of shifting left by 3 in $t1 is 101185520, which is $𝑡0 × 8 = $𝑡0 × 2 . Shifting left by 𝑖 bits gives
𝑡ℎ
the same result as multiplying by 2 to the 𝑖 power, just as shifting a decimal number by 𝑖 digits is
𝑖
equivalent to multiplying by 10 .
● Integer division is not exact and thus any bits lost (shifted off the right side) mean the result is
inexact. We know this from integer division in general: 3/2 is 1 in integer division. This is
because the binary number 011 (decimal 3), when right-shifted one position becomes 001, and
0
the previous 2 bit is lost.
● What do we do when we right-shift a number that has its most-significant bit set? If we shift zero
bits in from the left, the sign bit is no longer set! This would be correct if the original number was
unsigned.
a. Example: 1100 in a four-bit unsigned number is decimal 12. If we right-shift this one
position and set the leftmost position to 0, the result is 0110, or 6 (base 10). This is the
correct answer. However, if the original number was interpreted as signed, its original
value would have been -4. When we right-shift -4 by 1 position it shouldn't become 6!
Instead we want to set the [shifted-in] most-significant bit to 1. This would produce 1110,
which, when interpreted as a signed four-bit number is -2.
b. These two types of right shifts are called logical (when we treat the number as unsigned,
and shift 0 bits in) and arithmetic (when we treat the number as signed, and replicate the
sign bit in the bits shifted in) respectively. Since there is only one type of left-shift and it
shifts 0 bits in, it is also called logical.
The srl instruction is specifically for doing logical shift, same as sll. For doing right arithmetic shift,
there’s the sra instruction.
AND (and)
AND is a logical bit-by-bit (each pair of bits is ANDed) operation with two operands that calculates a 1
only if there is a 1 in both operands.
Consider the instruction and $t1, $t2, $t3. Assuming $t2 contains 0xF38DB937 and $t3 contains
0xF, $t1 ends up with 0x7. It’s no easy to follow through a bit-by-bit operation using hex, so we convert
them to binary first:
Register $t3 acts as an erase/reset mask – removing all but the right four bits and giving a result of
0x7 stored in $t1. The and instruction is useful for applying a bit pattern (i.e., a mask) to a set of bits to
force 0s wherever there’s a 0 in the mask.
OR (or)
OR is logical bit-by-bit operation with two operands that calculates a 1 if there is a 1 in either operand.
Consider the instruction or $t1, $t2, $t3. Assuming $t2 contains 0xF38DB937 and $t3 contains
0x600, $t1 ends up with 0xF38DBF37.
If you squint hard enough, you’ll notice that $t3 (i.e., the mask) set bits 9-10 in $t2 and the result was
stored in $t1. Thus, register $t3 acts as an add/set mask. The or instruction is useful for applying a bit
pattern to a set of bits to force 1s wherever there is a 1 in the mask. A 0 in the mask just leaves the bit
as-is.
NOR (nor)
NOR is a bit-by-bit operation which calculates a 1 only if there’s a 0 in both operands. This is basically
calculating the NOT of the OR.
Assuming registers $t1 = 0xDC0 and $t2 = 0x3C00, the result of the MIPS instruction
XOR (xor)
XOR is a bit-by-bit operation which calculates a 1 if only one of the bits is 1, but will be 0 if both are 0 or
both are 1
Assuming registers $t1 = 0xDC0 and $t2 = 0x3C00, the result of the MIPS instruction
If you look closely at $t0’s contents, every bit 1 in $t2 flipped the corresponding bit in $t1 (0 to 1, and 1
to 0). Thus, register $t2 acts as a flip mask. The xor instruction is useful for applying a bit pattern to a
set of bits to flipping 0s to 1s (and vice versa) wherever there is a 1 in the mask.
Constants
Constants are useful in AND, OR, and XOR logical operations as well as in arithmetic operations, so
MIPS also provides the instructions: and immediate (andi), or immediate (ori), and xor immediate
(xori). Constants are rare for NOR, since its main use is to invert the bits of a single operand; thus, the
MIPS instruction set architecture has no immediate version of NOR.
Bit Masking
You already know about and, or, and xor. Bit-masking uses these operators to reset, set, and flip bits in
a given bit pattern.
Logic recap:
Example: Given the register $s4 (16 bits), reset the bits 11, 7, 5, and 0; set the bits 6, 3, and 1; and flip
the bits 9 and 2.
Reset bitmask 1111 1111 1111 1111 1111 0111 0101 1110 0xF75E andi
Set bitmask 0000 0000 0000 0000 0000 0000 0100 1010 0x004A ori
Flip bitmask 0000 0000 0000 0000 0000 0010 0000 0100 0x0204 xori
Notice that for each particular mask, we start with the mask’s neutral bit pattern and then change the
bits accordingly. For example,
● For the reset mask (AND) its neutral bit pattern is a sequence of 1s since for any bit pattern X,
X ^ 1 = X. Then to reset specific bits, we change those particular 1s into 0s.
● For the set mask (OR), its neutral bit pattern is a sequence of 0s since for any bit pattern X, X v
0 = X.
● As for the flip mask (XOR), its neutral bit pattern is also a sequence of 0s since for any bit
pattern X, X ⊻0 = X. In the table above, the bits that have been reset/set/flipped for that
particular mask are bold and highlighted in red.
For this example, we’re using immediates that are 16 bits. Thus, the MIPS instructions are
Branching Instructions
Branch if Equal (beq), Branch if Not Equal (bne) and Jump (j)
Decision making is commonly represented in programming languages using the if statement,
sometimes combined with goto statements and labels. MIPS assembly language includes two
decision-making instructions, similar to an if statement with a goto:
NOTE: In MIPS assembly, a label is simply a string of chars, digits, dot, or underscore characters,
followed by a colon that is on a line by itself used to name a location in memory. It may refer to the
location of a data value (variable) or of an instruction. Just think of a label as representing an address;
its aim is to make the Assembly programmer's life easier by allowing them to name an address and
jump straight to it instead of counting lines. Labels are used in loops, jumps, and variable names.
if (x == y) z = x - y;
else z = x + y;
z = 2 * z;
This example introduced the MIPS instruction j (unconditional jump). In general, jump instructions
modify the program counter (PC) so that execution continues at a specific memory address, no matter
the value of the current program counter. By contrast, branch instructions are always relative to the
current program counter. The j instruction is only one of the jump instructions; others are jal, jalr, and jr.
These latter ones will be discussed later on.
There’s nothing special about using beq for the conditional; we could also use bne and just move some
things around. Another way of accomplishing the same thing as above is as follows:
# Allocate $s0 = x, $s1 = y, $s2 = z
NOTE: The assembler relieves the compiler and the assembly language programmer from the tedium
of calculating addresses for branches, just as it does for calculating data addresses for loads and
stores.
means that register $t0 is set to 1 if the value in register $s3 is less than the value in register $s4;
otherwise, register $t0 is set to 0.
Constant operands are popular in comparisons, so there is an immediate version of the set on less than
instruction, namely slti. To test if register $s2’s contents is less than the constant 10, we can just
write
MIPS compilers use the slt, slti, beq, bne, and the fixed value of 0 (always available by reading
register $zero) to create all relative conditions: equal (=), not equal (≠), less than (<), less than or equal
(≤), greater than (>), greater than or equal (≥).
int c = 10;
if (a > b) c = c + b;