Title: Chapter 3: Instructions
1Chapter 3 Instructions
2Assembly Language Instructions
- Were going to use the MIPS R2000 instruction set
for the projects in this course - Review Assembly language instructions are
English words that represent binary machine
language instructions
3Arithmetic/Logical Instructions
- Arithmetic instructions are composed of an
operation and three registers - ltopgt ltdestreggt ltoperand1gt ltoperand2gt
- There are 32 32-bit general-purpose integer
registers that we can use (R0 is hardwired to
value 0 for A/L operands) - Ex add 1, 2, 3
- When writing assembly language programs, comments
can be added after any instruction by using the
character - Some architectures only use 2 registers
- The result is stored in the first operand
register - Some of our instructions will use this convention
- Appendix A in the textbook lists all
4Immediate Arithmetic/Logical Instructions
- Most arithmetic/logical instructions have an
immediate version - Immediate instructions have an i at the end of
the instruction name - Immediate instructions allow us to specify an
immediate/constant/literal in lieu of a register
operand - Ex add 1, 2, 16
- We only have 16-bits for the immediate, so we can
only represent 216 unique values - Use decimal numbers for the immediate value in
the assembly-language instruction
5A/R Instructions
- MIPS R2000 A/L-instructions (complete)
- add, addu, addi, addiu
- and, andi
- div, divu (two registers)
- mult, multu (two registers)
- nor
- or, ori
- sll, sllv, sra, srav, srl, srlv
- sub, subu
- xor, xori
6Pseudoinstructions
- Pseudoinstructions are assembled into more than 1
machine instruction - Theres no real machine instruction for them
- Ex. abs rdest, rsrc
- Assembles into three instructions
- move the contents of rsrc into rdest
- if rdest is greater than 0, skip over the next
instruction - We havent covered conditional branches yet
- subtract rdest from 0
- Appendix A specifies which are pseudoinstructions
7Design Considerations
- Making most arithmetic instructions have 3
operands simplifies the hardware - This is a design decision
- Having a variable number of operands would
greatly complicate the hardware - Limiting ourselves to 32 registers is also a
design decision to keep things on the processor
die smaller - Influences clock cycle time
- Gives us more real estate for other things on our
core - Less registers, less decoding logic, etc.
8Registers
- MIPS assembly language also has symbolic names
for the registers - 0 gt constant 0
- 1 gt at (reserved for assembler)
- 2,3 gt v0,v1 (expression evaluation and
results of a function) - 4-7 gt a0-a3 (arguments 1-4)
- 8-15 gt t0-t7 (temporary values)
- Used when evaluating expressions that contain
more than two operands (partial solutions) - Not preserved across function calls
- 16-23 gt s0-gts7 (for local variables,
preserved across function calls) - 24, 25 gt t8, t9 (more temps)
- 26,27 gt k0, k1 (reserved for OS kernel)
- 28 gt gp (pointer to global area)
- 29 gt sp (stack pointer)
- 30 gt fp (frame pointer)
- 31 gt ra (return address, for branch-and-links)
9Memory and Load/Store Instructions
- As weve already seen, a processor can only use
data stored in its registers as operands and
targets for computation - Typically, before computation can be performed,
data must be loaded from main memory - After the computation is complete, the results
must be stored back to main memory
10Memory
- Computer memory is byte-addressed but the MIPS
architecture requires alignment of loads and
stores on the 32-bit (4 byte/word) boundary - This means that all memory references must be an
even multiple of 4 - When addressing 4-byte words, you need to provide
the address of the lowest-addressed byte in the
word
11Load/Store Instructions
- Most commonly used
- lw, sw, lh, sh, lb, sb, la
- Use
- lw ltrdestgt, address
- address can be represented as
- symbolic address (that you declare in SPIM)
- symbolic address with register index
- decimal_offset(basereg)
- This is the way that the instruction is
translated - loads/stores from contents of baseregdecimal_off
set
12Load/Store Instructions
- SPIM treats loads and stores with symbolic
addresses as pseudoinstructions - loads the address of the data segment as an
immediate into 1 - lui 1, 4097
- data starts at hex address 10010000
- If an index register is provided, adds the
contents of the index reg to 1 - addu 1, 1, rindex
- loads 0(1) into rdest
- lw rdest, offset_of_variable(1)
- This is an example of base-displacement
addressing - This is why R1 is reserved when you write your
programs
13Load/Store Instructions
- When loading or storing halfwords and bytes, the
address points to a aligned word - The halfword would be the LOWER (least
significant) halfword of the word that the
address is pointing to - The byte world be the LOWEST (least significant)
byte of the word being that the address is
pointing to
14Constant-Manipulating Instructions
- lui rt, imm
- Load the immediate imm into the upper halfword of
register rt - The lower bits are set to 0
- li rt, imm
- Load the imm into the lower halfword of register
rt - The upper bits are set to 0
15Encoding Instructions
- The MIPS architecture has a 32-bit binary
instruction format for each class of instruction - A/L, constant manip, comparison, branch, jump,
load/store, data movement, floating-point - Even though weve only covered 3 of these
classes, lets look at how we encode the
instructions weve learned
16Encoding/Translating A/L Instructions
- First (most significant, left-most) 6-bits of ALL
instructions is the op-code - The opcode defines the instruction
- Doesnt this only give us 2664 different
instructions? - Yes! But all A/L instructions, excluding the
ones which have immediates, has an opcode of 0
but has a 6-bit field at the end of the
instruction that specifies the operation
17Encoding/Translating A/L Instructions
- Non-immediate A/L instructions
- 6 bits opcode (usually 0)
- 5 bits rs (operand 1)
- 5 bits rt (operand 2)
- 5 bits rd (destination)
- 5 bits 0s or shift amount
- 6 bits operation code
18Encoding/Translating A/L Instructions
- Immediate A/L instructions
- 6 bits opcode (now unique)
- 5 bits rs (operand 1)
- 5 bits rt (destination)
- 16 bits immediate (understood to be 0-extended)
19Encoding/Translating Load/Store Instructions
- 6 bits opcode
- 5 bits rs (base register)
- 5 bits rt (load from/store to)
- Sometimes the whole register isnt used
- Half words and bytes
- 16 bits offset
20Encoding/Translating Constant-Manip. Instructions
- 6 bits opcode
- 5 bits 0s
- 5 bits rt dest. register
- Half of this register will be assigned 0s
- 16 bits immediate
21Examples
- Lets compile the following C code segment into
assembly code - z(ab)(c/d)-(efg)
- lw s0,a
- lw s1,b
- mult s0,s1
- mflo t0 new instruction
- lw s0,c
- lw s1,d
- div s0,s1
- mflo t1
- add t0,t0,t1
- lw s0,e
- lw s1,f
- lw s2,g
- mult s1,s2
- mflo t1
- add t1,s0,t1
- sub t0,t0,t1
- sw t0,z
22Examples
- Note There were many ways we could have
compiled the C statement - Now lets assemble the first three instructions
to machine code - Assume the variables are all stored as words and
are stored sequencially, starting with a, from
the start of the data segment
23Examples
- lw s0,a
- We know s0 is 16
- There are a few different ways we can do this,
too - First, we need to convert this instruction to a
small series of instructions - lui 1,4097 4097 is 1001 in hex
- lw 16,0(1) 0 offset because a is first var
-
- 00111100000000010001000000000001 gt 3C011001
- 10001100000100000000000000000000 gt 8C100000
24Examples
- mult s0, s1
- 00000010000100010000000000011000 gt 02110018
25Branch/Jump Instructions
- Branch and jump instructions are needed for
program control - if-statements (conditionals)
- loops
- procedure calls
- Most common
- b ltlabelgt -- unconditional branch
- label is a memory address (we can be symbolic
ones, of course) - beq, bgez, bgezal, bgtz, blez, etc.
- Conditional branches, where were comparing a
register to 0 or two registers to determine if
were going to branch or not - Also have al (and-link) variants, that link a
return address (instruction following branch)
into 31 so we can return - Branch targets are 16-bit immediate offset
- offset in words it is shifted to the left 2
bits to get byte length
26Branch/Jump Instructions
- j, jal
- Unconditionally branches to a 26-bit pseudodirect
address (not offset) - jalr, jr
- Unconditionally branches to an address stored in
a register
27Encoding/Translating Branch/Jump Instructions
- See Appendix A
- These are very similar to the encoding we covered
before
28Data Movement and Comparison Instructions and
Their Encoding
- Im going to leave the study of these
instructions (from Appendix A) up to you as an
exercise!
29Examples
- if ((agtb)(cd)) e0 else ef
- lw s0,a
- lw s1,b
- bgt s0,s1,next0
- b nope
- next0 lw s0,c
- lw s1,d
- beq s0,s1,yup
- nope lw s0,f
- sw s0,e
- b out
- yup xor s0,s0,s0
- sw s0,e
- out
30Examples
- Again, there are many other ways we could have
tackled this - You will eventually come up with your own
strategies for compiling the types of
constructs you want to perform
31Examples
- How about a for loop?
- for (i0iltai) bii
- lw s0,a
- xor s1,s1,s1
- loop0 blt s1,s0,loop1
- b out
- sll s2,S1,2
- loop1 sw s1,b(s2)
- addi s1,s1,1
- b loop0
- out
32Examples
- How about a pretest while loop?
- while (altb)
- a
-
- lw s0,a
- lw s1,b
- loop0 blt s0,s1,loop1
- b out
- loop1 addi s0,Ss0,1
- sw s0,a
- b loop0
- out
33Examples
- How about a posttest while loop?
- do
- a
- while (altb)
- lw s0,a
- lw s1,b
- loop0 addi s0,s0,1
- sw s0,a
- blt s0,s1,loop0
-
34Procedure Calls
- How about a procedure call?
- The full-blown C/Pascal recursive procedure call
convention is beyond the scope of this class, so
well skip it for now - This is described in detail in Appendix A
- You can arbitrarily implement your own procedure
call convention
35Procedure Calls
- Say we want to write a procedure that computes
the factorial of a number, like this - int factorial (int val)
- int tempval
- while (val)
- temp(--val)
- return temp
36Procedure Calls
- Lets adopt the following simple convention
- Well pass the arguments through a0-a3
- Only allows for up to 4 arguments
- Well set our return value in v0
- The return address will be stored in ra
- This limits us to 1-level of procedure calls
- Well assume the callee (procedure) will save
registers s0-s7 starting at memory address
FF000000 when its called, and restore the
registers before it returns - This may not be necessary for all procedures
37Procedure Calls
- So heres our procedure
- factorial lui t1,0xFF00
- sw s0,0(t1)
- sw s1,4(t1)
-
- sw s7,28(t1)
- move s0,a0 new instruction
- move s1,a0
- loop0 bgtz s0,loop1
- b out
- loop1 mult s0,s1
- mflo s1
- subi s0,s0,1
- b loop0
- out move v0,s1
- lw s0,0(t1) load back registers
-
- jr 31
38Procedure Calls
- In order to call our procedure
- load a value into a0
- bal factorial
- look in v0 for the result!
39I/O
- Doing I/O with SPIM is also described in Appendix
A, but were going to use the system calls that
are set up for us to do I/O
40I/O
- SPIM provides some operating system services
through the syscall instruction - To use the system calls
- load system call code (from pg. a49) into v0 and
argument into a0 - return values in v0 (or f0 for fp results)
41Example I/O
- str
- .asciiz the answer
- .text
- li v0,4
- la a0, str
- syscall
- li v0,1
- la a0,5
- syscall
- (Refer to page A-49)