Transcript document

Chapter 3: Instructions
CS 447
Jason D. Bakos
1
Assembly Language
Instructions
• We’re 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
2
Arithmetic/Logical
Instructions
• Arithmetic instructions are composed of an
operation and three registers
– <op> <destreg> <operand1> <operand2>
– 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
3
Immediate
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
4
A/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
5
Pseudoinstructions
• Pseudoinstructions are assembled into
more than 1 machine instruction
– There’s 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 haven’t covered conditional branches yet
• subtract rdest from 0
– Appendix A specifies which are
pseudoinstructions
6
Design 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.
7
Registers
•
MIPS assembly language also has symbolic names for the registers
– $0 => constant 0
– $1 => $at (reserved for assembler)
– $2,$3 => $v0,$v1 (expression evaluation and results of a function)
– $4-$7 => $a0-$a3 (arguments 1-4)
– $8-$15 => $t0-$t7 (temporary values)
• Used when evaluating expressions that contain more than two
operands (partial solutions)
• Not preserved across function calls
– $16-$23 => $s0->$s7 (for local variables, preserved across function
calls)
– $24, $25 => $t8, $t9 (more temps)
– $26,$27 => $k0, $k1 (reserved for OS kernel)
– $28 => $gp (pointer to global area)
– $29 => $sp (stack pointer)
– $30 => $fp (frame pointer)
– $31 => $ra (return address, for branch-and-links)
8
Memory and Load/Store
Instructions
• As we’ve 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
9
Memory
• 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
10
Load/Store Instructions
• Most commonly used:
– lw, sw, lh, sh, lb, sb, la
• Use:
– lw <rdest>, 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
$basereg+decimal_offset
11
Load/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
12
Load/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
13
Constant-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
14
Encoding 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 we’ve only covered 3 of
these classes, let’s look at how we
encode the instructions we’ve
learned…
15
Encoding/Translating A/L
Instructions
• First (most significant, left-most) 6bits of ALL instructions is the opcode
– The opcode defines the instruction
– Doesn’t this only give us 26=64 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
16
Encoding/Translating A/L
Instructions
• Non-immediate A/L instructions:
–
–
–
–
–
–
6
5
5
5
5
6
bits
bits
bits
bits
bits
bits
–
–
–
–
–
–
opcode (usually 0)
rs (operand 1)
rt (operand 2)
rd (destination)
0’s or shift amount
operation code
17
Encoding/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 0extended)
18
Encoding/Translating
Load/Store Instructions
• 6 bits – opcode
• 5 bits – rs (base register)
• 5 bits – rt (load from/store to)
– Sometimes the whole register isn’t used
• Half words and bytes
• 16 bits – offset
19
Encoding/Translating
Constant-Manip. Instructions
• 6 bits – opcode
• 5 bits – 0’s
• 5 bits – rt dest. register
– Half of this register will be assigned 0’s
• 16 bits – immediate
20
Examples
•
Let’s compile the following C++ code segment into
assembly code:
–
–
z=(a*b)+(c/d)-(e+f*g);
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
21
Examples
• Note: There were many ways we
could have compiled the C++
statement
• Now let’s 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…
22
Examples
• 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 => 3C011001
10001100000100000000000000000000 => 8C100000
23
Examples
• mult $s0, $s1
–
00000010000100010000000000011000 => 02110018
24
Branch/Jump Instructions
•
•
Branch and jump instructions are needed for program control
– if-statements (conditionals)
– loops
– procedure calls
Most common:
– b <label> -- unconditional branch
• label is a memory address (we can be symbolic ones, of
course)
– beq, bgez, bgezal, bgtz, blez, etc.
• Conditional branches, where we’re comparing a register
to 0 or two registers to determine if we’re 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
25
Branch/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
26
Encoding/Translating
Branch/Jump Instructions
• See Appendix A
– These are very similar to the encoding
we covered before
27
Data Movement and
Comparison Instructions and
Their Encoding
• I’m going to leave the study of these
instructions (from Appendix A) up to
you as an exercise!
28
Examples
• if ((a>b)&&(c=d)) e=0; else e=f;
lw $s0,a
next0:
nope:
yup:
out:
lw $s1,b
bgt $s0,$s1,next0
b nope
lw $s0,c
lw $s1,d
beq $s0,$s1,yup
lw $s0,f
sw $s0,e
b out
xor $s0,$s0,$s0
sw $s0,e
…
29
Examples
• 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…
30
Examples
• How about a for loop?
•
for (i=0;i<a;i++) b[i]=i;
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:
…
31
Examples
• How about a pretest while loop?
•
while (a<b) {
a++;
}
loop0:
loop1:
out:
lw $s0,a
lw $s1,b
blt $s0,$s1,loop1
b out
addi $s0,Ss0,1
sw $s0,a
b loop0
…
32
Examples
• How about a posttest while loop?
•
do {
a++;
} while (a<b);
lw $s0,a
lw $s1,b
loop0:
addi $s0,$s0,1
sw $s0,a
blt $s0,$s1,loop0
…
33
Procedure Calls
• How about a procedure call?
– The full-blown C/Pascal recursive
procedure call convention is beyond the
scope of this class, so we’ll skip it for
now…
– This is described in detail in Appendix A
• You can arbitrarily implement your
own procedure call convention…
34
Procedure Calls
• Say we want to write a procedure
that computes the factorial of a
number, like this:
int factorial (int val) {
int temp=val;
while (val)
temp*=(--val);
return temp;
}
35
Procedure Calls
• Let’s adopt the following simple
convention:
– We’ll pass the arguments through $a0-$a3
• Only allows for up to 4 arguments
– We’ll set our return value in $v0
– The return address will be stored in $ra
• This limits us to 1-level of procedure calls
– We’ll assume the callee (procedure) will save
registers $s0-$s7 starting at memory address
FF000000 when it’s called, and restore the
registers before it returns
• This may not be necessary for all procedures
36
Procedure Calls
• So here’s our procedure…
factorial:
loop0:
loop1:
out:
lui $t1,0xFF00
sw $s0,0($t1)
sw $s1,4($t1)
…
sw $s7,28($t1)
move $s0,$a0
move $s1,$a0
bgtz $s0,loop1
b out
mult $s0,$s1
mflo $s1
subi $s0,$s0,1
b loop0
move $v0,$s1
lw $s0,0($t1)
…
jr $31
# new instruction
# load back registers
37
Procedure Calls
• In order to call our procedure…
– load a value into $a0
– bal factorial
– look in $v0 for the result!
38
I/O
• Doing I/O with SPIM is also
described in Appendix A, but we’re
going to use the system calls that
are set up for us to do I/O…
39
I/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)
40
Example 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)
41