LOGO
Lecture 4:
Language of the computer
(II)
Dr. Hakem Beitollahi
Department of Computer Engineering,
Iran University of Science and Technology
1/70
Outline
Logical operations
Instructions for making decision
Supporting procedures in computer hardware
Communicating with People
Addressing for 32-bit immediate and addresses
2/70 Compiler – assembler, linker
© by Hakem Beitollahi
Logical Operations
Instructions for bitwise manipulation
Operation C Java MIPS
Shift left << << sll
Shift right >> >>> srl
Bitwise AND & & and, andi
Bitwise OR | | or, ori
Bitwise NOT ~ ~ nor
Useful for extracting and inserting
groups of bits in a word
3/70
© by Hakem Beitollahi
Shift
Shift operations move all the bits in a word to the left or
right, filling the emptied bits with 0s
Sll is shift to left
Example: sll $t2, $s0, 4
Suppose: $s0 = 0000 0000 0000 0000 0000 0000 0000 1001
$t2 = 0000 0000 0000 0000 0000 0000 1001 0000
Srl is shift to right
Example: srl $t2, $s0, 4
Suppose: $s0 = 0000 0000 0000 0000 0000 0000 0000 1001
$t2 = 0000 0000 0000 0000 0000 0000 0000 0000
4/70
© by Hakem Beitollahi
Shift Operations
op rs rt rd shamt funct
6 bits 5 bits 5 bits 5 bits 5 bits 6 bits
shamt: how many positions to shift
Shift left logical
Shift left and fill with 0 bits
sll by i bits multiplies by 2i
Field of “rs” is filled with 0
Shift right logical
Shift right and fill with 0 bits
srl by i bits divides by 2i (unsigned only)
5/70 Field of “rs” is filled with 0 © by Hakem Beitollahi
AND Operations
Useful to mask bits in a word
Select some bits, clear others to 0
and $t0, $t1, $t2 #t0 = t1 && t2
$t2 0000 0000 0000 0000 0000 1101 1100 0000
$t1 0000 0000 0000 0000 0011 1100 0000 0000
$t0 0000 0000 0000 0000 0000 1100 0000 0000
6/70
© by Hakem Beitollahi
OR Operations
Useful to include bits in a word
Set some bits to 1, leave others unchanged
or $t0, $t1, $t2 #t0 = t1 || t2
$t2 0000 0000 0000 0000 0000 1101 1100 0000
$t1 0000 0000 0000 0000 0011 1100 0000 0000
$t0 0000 0000 0000 0000 0011 1101 1100 0000
7/70
© by Hakem Beitollahi
NOT Operations
Useful to invert bits in a word
Change 0 to 1, and 1 to 0
MIPS has NOR 3-operand instruction
a NOR b == NOT ( a OR b )
nor $t0, $t1, $zero Register 0: always
read as zero
$t1 0000 0000 0000 0000 0011 1100 0000 0000
$t0 1111 1111 1111 1111 1100 0011 1111 1111
8/70
© by Hakem Beitollahi
Format of AND, OR
and NOR
And, Or and Nor are R-format
instructions
op rs rt rd shamt funct
6 bits 5 bits 5 bits 5 bits 5 bits 6 bits
OP = 000000
funct= 100100 (36) for and
funct= 100101 (37) for or
funct= 100110 (38) for nor
9/70
© by Hakem Beitollahi
Immediate OR and
AND
In order to and operation of a register
with immediate number, use andi
andi $t0, $s0, 57 # $t0 = $s0 && 57
Same rule for ori
ori $t0, $s0, 15 # $t0 = $s0 || 15
Both andi and ori locate in category of
I-format instruction
10/70
© by Hakem Beitollahi
Summary till now
11/70
© by Hakem Beitollahi
Outline
Logical operations
Instructions for making decision
12/70
© by Hakem Beitollahi
Conditional Operations
Branch to a labeled instruction if a
condition is true
Otherwise, continue sequentially
beq rs, rt, L1
if (rs == rt) branch to instruction labeled L1;
bne rs, rt, L1
if (rs != rt) branch to instruction labeled L1;
j L1
unconditional jump to instruction labeled L1
13/70
© by Hakem Beitollahi
Compiling If
Statements
C code:
i ==j
if (i==j) f = g+h;
else f = g-h; true false
f, g, … in $s0, $s1, … f=g+h f =g-h
Compiled MIPS code:
bne $s3, $s4, Else
add $s0, $s1, $s2
j Exit
Else: sub $s0, $s1, $s2
Exit: … Assembler calculates addresses
14/70
© by Hakem Beitollahi
Compiling Loop
Statements
C/C++ code:
while (save[i] == k) i += 1;
i in $s3, k in $s5, address of save in $s6
Compiled MIPS code:
Loop: sll $t1, $s3, 2 #temp reg $t1 = i×4
add $t1, $t1,$s6 #$t1 = address of save[i]
lw $t0, 0($t1) # temp reg $t0 = save[i]
bne $t0, $s5, Exit #goto exit if save[i]≠k
addi $s3, $s3, 1 # i = i + 1
j Loop #goto loop
Exit: …
15/70
© by Hakem Beitollahi
Basic Blocks
A basic block is a sequence of
instructions with
No embedded branches (except at end)
No branch targets (except at beginning)
A compiler identifies basic
blocks for optimization
An advanced processor
can accelerate execution
of basic blocks
16/70
© by Hakem Beitollahi
More Conditional
Operations
The test for equality or inequality is important,
but sometimes we need to know if a variable is
less than or greater than something
Set result to 1 if a condition is true Otherwise,
set to 0
slt rd, rs, rt
if (rs < rt) rd = 1; else rd = 0;
slti rt, rs, constant
if (rs < constant) rt = 1; else rt = 0;
Use in combination with beq, bne
slt $t0, $s1, $s2 # if ($s1 < $s2)
bne $t0, $zero, L # branch to L
17/70
© by Hakem Beitollahi
Signed vs.
Unsigned
Signed comparison: slt, slti
Unsigned comparison: sltu, sltui
Example
$s0 = 1111 1111 1111 1111 1111 1111 1111 1111
$s1 = 0000 0000 0000 0000 0000 0000 0000 0001
slt $t0, $s0, $s1 # signed
• –1 < +1 $t0 = 1
sltu $t0, $s0, $s1 # unsigned
• +4,294,967,295 > +1 $t0 = 0
18/70
© by Hakem Beitollahi
Check Yourself
C has many statements for decisions and loops
while MIPS has few. Which of the following do or
do not explain this imbalance? Why?
1. More decision statements make code easier to read
and understand.
2. Fewer decision statements simplify the task of the
underlying layer that is responsible for execution.
3. More decision statements mean fewer lines of code,
which generally reduces coding time.
4. More decision statements mean fewer lines of code,
which generally results in the execution of fewer
operations.
19/70
© by Hakem Beitollahi
Outline
Logical operations
Instructions for making decision
Supporting procedures in computer hardware
20/70
© by Hakem Beitollahi
Supporting procedures in
computer hardware
A procedure or method is one tool programmers
use to structure programs, both for make them
easier to understand and to allow code to be
reused
Example: int average(int a, int b, int c);
A Procedure (method) is similar to spy who
leaves with a secret plan, acquires resources,
performs the task, covers his tracks, and then
returns to the point of origin with the desired
result.
21/70
© by Hakem Beitollahi
Procedure Calling
Steps required
1. Place parameters in registers such that
procedure can access them
2. Transfer control to the procedure
3. Acquire the storage resources needed for
procedure
4. Perform procedure’s operations
5. Place result in register for caller
6. Return to place of call
22/70
© by Hakem Beitollahi
Register Usage
$a0 – $a3: arguments (reg’s 4 – 7) to
pass parameters
$v0, $v1: result values (reg’s 2 and 3)
$t0 – $t9: temporaries
Can be overwritten by callee
$s0 – $s7: saved
Must be saved/restored by callee
$gp: global pointer for static data (reg 28)
$sp: stack pointer (reg 29)
$ra: return address (reg 31) to return the
address of origin
23/70
© by Hakem Beitollahi
Procedure Call Instructions
Procedure call: jump and link
jal ProcedureLabel
Address of following instruction put in $ra and then
Jumps to target address
Procedure return: jump register
jr $ra
Jumps to address stored in register $ra
Perform the procedure
Calling a procedure puts the parameter values in $a0-$a3
Uses jal x to jump to procedure x (a.k.a callee)
Callee performs the calculation and places the results in
$v0 and $v1
Returns control of the program to the caller using jr $ra
24/70
© by Hakem Beitollahi
Procedure Call
We need to have a register to hold the
address of the current instruction being
executed.
Historically the name of this register
program counter (PC).
Another name: instruction address
register.
Jal instruction actually saves PC+4 in
register $ra to link to the following
instruction to set up the procedure return.
25/70
© by Hakem Beitollahi
How to restore the
values of registers
We must cover our tracks after finishing
the procedure.
Any registers needed by the procedure must
be restored to the values that they contained
before the procedure was invoked.
We should spill registers into memory and
after finishing the procedure restore them.
The ideal data structure for this propose is
stack
Stack: a last-in-first-out queue
26/70
© by Hakem Beitollahi
How to restore the
values of registers
A stack needs a pointer to the most recently allocated
address in the stack
To show where the next procedure should place the registers to
be spilled or
To find the place of registers of the previous procedure
$sp register (stack pointer): reg number 29
Placing a data on stack: push
Removing a data from the stack: pop
Stacks grow from higher addresses to lower addresses:
Push values onto the stack by subtracting from the stack pointer
• addi $sp, $sp, -4
• sw $s0, 0(sp)
Removing a data (pop) is done by adding to the stack pointer
• lw $s0, 0(sp)
27/70 • addi $sp, $sp, 4
© by Hakem Beitollahi
Procedure Example
C code:
int leaf_example (int g, int h, int i,int j)
{ int f;
f = (g + h) - (i + j);
return f;
}
Arguments g, …, j in $a0, …, $a3
f in $s0 (hence, need to save $s0 on stack)
Result in $v0
28/70
© by Hakem Beitollahi
MIPS code:
leaf_example:
CPU
$s0
addi $sp, $sp, -4
Save $s0 on stack
sw $s0, 0($sp)
add $t0, $a0, $a1
add $t1, $a2, $a3 Procedure body
sub $s0, $t0, $t1 $sp
$s0
add $v0, $s0, $zero Result
lw $s0, 0($sp)
Restore $s0
addi $sp, $sp, 4
jr $ra Return
29/70
© by Hakem Beitollahi
Nested Procedures
30/70
© by Hakem Beitollahi
Nested procedures
(I)
Procedures that do not call others are leaf
procedures
Non-leaf procedures are the procedures that call
procedures on their body
Just as a spy might employ other spies as part of
a mission, who in turn might use even more
spies, so do procedures invoke other procedures.
Recursive procedures even invoke “clones” of
themselves.
We need to be careful when using registers in
nested procedures
31/70
© by Hakem Beitollahi
Nested procedures
(II)
Suppose that the main program calls procedure A
with an argument of 3, by placing the value 3
into register $a0 and then using jal A.
Then suppose that procedure A calls procedure B via
jal B with an argument of 7, also placed in $a0.
• Problem 1: Since A hasn’t finished its task yet, there is a
conflict over the use of register $a0.
• Problem 2: There is a conflict over the return address in
register $ra, since it now has the return address for B.
For nested call, caller needs to save on the stack:
Its return address
Any arguments and temporaries needed after the call
Restore from the stack after the© call
32/70
by Hakem Beitollahi
Non-Leaf Procedure
Example
C code:
int fact (int n)
{
if (n < 1) return 1;
else return n * fact(n - 1);
}
Argument n in $a0
Result in $v0
33/70
© by Hakem Beitollahi
Non-Leaf
Procedure Example
MIPS code:
fact:
addi $sp, $sp, -8 # adjust stack for 2 items
sw $ra, 4($sp) # save return address
sw $a0, 0($sp) # save argument
slti $t0, $a0, 1 # test for n < 1
beq $t0, $zero, ELSE
addi $v0, $zero, 1 # if so, result is 1
addi $sp, $sp, 8 # pop 2 items from stack
jr $ra # and return to after jal
ELSE: addi $a0, $a0, -1 # n >= 1: argument gets (n – 1)
jal fact # call fact with (n – 1)
lw $a0, 0($sp) # restore original n
Where
fact
lw $ra, 4($sp) # and return address
returns addi $sp, $sp, 8 # pop 2 items from stack
mul $v0, $a0, $v0 # multiply to get result
jr $ra # and return to the caller
34/70
© by Hakem Beitollahi
Memory Layout
35/70
© by Hakem Beitollahi
Memory Layout
The stack starts in the high end of memory
and grows down.
The first part of the low end of memory is
reserved, followed by the home of the MIPS
machine code (text segment)
The static data segment: The place for
constants and other static variables (e.g.,
array).
Dynamic data: Data structures like linked
lists tend to grow and shrink during their
lifetimes.
The segment is traditionally called the heap.
This allocation allows the stack and heap to
grow toward each other, thereby allowing
the efficient use of memory as the two
segments wax and wane.
36/70
© by Hakem Beitollahi
Registers Number
37/70
© by Hakem Beitollahi
Check Yourself
Which of the following statements about C
and Java are generally true?
C programmers manage data explicitly while
it’s automatic in Java.
C leads to more pointer bugs and memory
leak bugs than does Java.
C passes parameters in registers while Java
passes them on the stack.
38/70
© by Hakem Beitollahi
Outline
Logical operations
Instructions for making decision
Supporting procedures in computer hardware
Communicating with People
39/70
© by Hakem Beitollahi
Communicating
with People
Computers were invented to crunch
numbers,
As soon as they became commercially viable
they were used to process text
Most computers today use 8-bit bytes to
represent characters (ASCII Code),
A series of instructions can extract a byte
from a word,
Load word and Store word are sufficient for
transferring bytes.
40/70
© by Hakem Beitollahi
Byte/Halfword Operations
Two instructions to load/store bytes from/to memory
Instruction lb loads a byte from memory, placing it in the
rightmost 8 bits of a register.
lb $t0, 0($sp) # read byte from source
The rest of bits of the register are filled by the sign bit (last
bit of the byte)
10010101 111111111111111111111110010101
Instruction sb takes a byte from the rightmost 8 bits of a
register and writes it to memory
sb $t0, 0($gp) # write byte to destination
Load an unsigned byte to a register we use lbu instruction
lbu $t0, 0($sp)
In lbu instruction the rest of bits are filled by zero
41/70
10010101 000000000000000000000010010101
© by Hakem Beitollahi
Strings
Characters are normally combined into strings,
which have a variable number of characters.
Three choices for representing a string:
The first position of the string is reserved to give the
length of a string.
An accompanying variable has the length of the string
The last position of a string is indicated by a character
used to mark the end of a string.
C uses the third choice, terminating a string with
a byte whose value is 0 (named null in ASCII).
The string “Cal” is represented in C
The following 4 bytes, shown as decimal numbers:
42/70
67, 97, 108, 0. © by Hakem Beitollahi
Strings
Example
void strcpy (char x[], char y[])
{
int i;
i = 0;
while ((x[i] = y[i]) != ‘\0’) /* copy & test byte */
i += 1;
}
Translate the strcpy method to MIPS
assembly language
Suppose i is stored at $s0
43/70
© by Hakem Beitollahi
Strcpy Example
MIPS code:
strcpy:
addi $sp, $sp, -4 # adjust stack for 1 item
sw $s0, 0($sp) # save S0 register
add $s0, $zero, $zero # i= 0 + 0
L1: add, $t1, $s0, $a1 # address of y[i] in $t1
lb $t2, 0($t1) # $t2= y[i]
add $t3, $s0, $a0 # address of x[i] in $t3
sb $t2, 0($t3) # x[i] = y[i]
beq $t2, $zero, L2 # if y[i] == 0, go to L2
addi $s0, $s0, 1 # i = i + 1
j L1 # go to L1
L2: lw $s0, 0($sp) # y[i] == 0: end of string;
# restore old $s0
addi $sp, $sp, 4 # pop 1 item from stack
jr $ra # return to the caller
44/70
© by Hakem Beitollahi
Outline
Logical operations
Instructions for making decision
Supporting procedures in computer hardware
Byte/Halfword Operations
Addressing for 32-bit immediate and addresses
45/70
© by Hakem Beitollahi
Large constant (32 bits)
Most constants are small
16-bit immediate is sufficient
For the occasional 32-bit constant, what should
we do?
The instruction lui (load upper immediate) copies
the leftmost 16 bits of the constant to the
leftmost 16 bits of the register
lui rt, constant
• Copies 16-bit constant to left 16 bits of rt
• Clears right 16 bits of rt to 0
using ori instruction copies the rightmost 16 bits
of constant into rightmost 16 bits of the register
46/70
© by Hakem Beitollahi
Large constant (32 bits)
Example: what is the MIPS assembly code to load this 32
bits constant into register $s0?
0000 0000 0011 1101 0000 1001 0000 0000
Solution: first load the leftmost 16 bits
lui $s0, 61 # 61 decimal = 0000 0000 0011 1101 binary
The value of $s0 afterwards is
0000 0000 0011 1101 0000 0000 0000 0000
The next step is to insert the lower 16 bits (the rightmost 16
bits) using ori
ori $s0, $s0, 2304 #2304 decimal = 0000 1001 0000 0000
The final value of $s0 is the desired value:
0000 0000 0011 1101 0000 1001 0000 0000
47/70
© by Hakem Beitollahi
Branch Addressing
Branch instructions specify
Opcode, two registers, target address
Most branch targets are near branch
Forward or backward
op rs rt constant or address
6 bits 5 bits 5 bits 16 bits
PC-relative addressing
Target address = PC + offset × 4
PC already incremented by 4 by this time
48/70
© by Hakem Beitollahi
Jump Addressing
Jump (j and jal) targets could be
anywhere in text segment
Encode full address in instruction
op address
6 bits 26 bits
(Pseudo)Direct jump addressing
Target address = PC: (address × 4)
49/70
© by Hakem Beitollahi
Target Addressing
Example
Loop code from earlier example
Assume Loop at location 80000
Loop: sll $t1, $s3, 2 80000 0 0 19 9 2 0
add $t1, $t1, $s6 80004 0 9 22 9 0 32
lw $t0, 0($t1) 80008 35 9 8 0
bne $t0, $s5, Exit 80012 5 8 21 2
addi $s3, $s3, 1 80016 8 19 19 1
j Loop 80020 2 20000
Exit: … 80024
50/70
© by Hakem Beitollahi
Addressing Mode
Summary
51/70
© by Hakem Beitollahi
Check Yourself
What is the range of addresses for
conditional branches in MIPS (K = 1024)?
1. Addresses between 0 and 64K – 1
2. Addresses between 0 and 256K – 1
3. Addresses up to about 32K before the
branch to about 32K after
4. Addresses up to about 128K before the
branch to about 128K after
52/70
© by Hakem Beitollahi
Check Yourself
In the following instruction, suppose
L1 is more than 16 bits or suppose L1
is far away from Beq. How do you
treat?
Beq $s0, $s1, L1
Answer:
Bne $s0, $s1, L2
J L1
L2:
53/70
© by Hakem Beitollahi
Outline
Logical operations
Instructions for making decision
Supporting procedures in computer hardware
Byte/Halfword Operations
Addressing for 32-bit immediate and addresses
54/70 Compiler – assembler, linker
© by Hakem Beitollahi
Translation and
Startup
Many compilers produce
object modules directly
Static linking
55/
Compilers
The compiler transfers a high level language
(e.g., C++, java) into assembly language
program.
High level languages take many fewer lines
of codes than assembly language
In 1975, many operating systems were
written in assembly language because
memories were small and compiler were
inefficient
Compilers generates more assembly language lines
than human
56/70
© by Hakem Beitollahi
Producing an Object
Module (Assembler)
Assembler translates program into machine
instructions
pseudoinstruction A common variation of
assembly language instructions often treated as if
it were an instruction in its own right.
The MIPS assembler accepts MOV instruction even
though it is not found in the MIPS architecture:
move $t0,$t1 # register $t0 gets register $t1
• The assembler converts this assembly language
instruction into the machine language equivalent of
the following instruction:
add $t0,$zero,$t1 # register $t0 gets 0 + register $t1
57/70
© by Hakem Beitollahi
Producing an Object
Module (Assembler II)
Other pseudoinstruction in MIPS
blt (branch on less than)
• into the two instructions slt and bne
Other examples include bgt, bge, and ble.
It also converts branches to faraway locations into a branch
and jump.
pseudoinstructions give MIPS a richer set of assembly
language instructions than those implemented by the
hardware
Assemblers will also accept numbers in a variety of bases:
binary, octal and hex
The assembler turns the assembly language program into
an object file, which is a combination of machine
language instructions, data, and information needed to
58/70 place instructions properly in memory.
© by Hakem Beitollahi
Producing an Object
Module (Assembler III)
The assembler must determine the addresses
corresponding to all labels.
Assemblers keep track of labels used in branches and data
transfer instructions in a symbol table.
The object file for UNIX systems typically contains six
distinct pieces:
Header: described contents of object module (the size and
position of the other pieces)
Text segment: translated instructions (machine language code)
Static data segment: data allocated for the life of the program
Relocation info: identifies instructions and data words that
depend on absolute addresses when the program is loaded into
memory
Symbol table: address of labels
The debugging information
59/70
© by Hakem Beitollahi
Producing an Object
Module (Assembler IV)
60/70
© by Hakem Beitollahi
Linker (I)
Linker creates an executable file that can be run
on a computer
The executable file has the same format as
object file, except it contains no unresolved
references, no header, no data segment
When just one line of a procedure is changed,
what should we do?
Compile and assemble whole program! Or
Compile and assemble each procedure
independently, so that a change to one line would
require compiling and assembling only one procedure
This issue is done via Linker (Link Editor)
61/70
© by Hakem Beitollahi
Linker (II)
Produces an executable image
1. Merges segments
2. Resolve labels (determine their addresses)
• Labels in branches, jumps, etc.
3. Patch location-dependent and external refs
The linker uses the relocation information and symbol table
in each object module to resolve all undefined labels.
Editing is the origin of the name “link editor,” or linker for
short
The reason a linker makes sense is that it is much faster to
patch code than it is to recompile and reassemble.
If all external references are resolved, the linker next
determines the memory locations each module will occupy
62/70
© by Hakem Beitollahi
Loader
Now that the executable file is on disk, the
operating system reads it to memory and
starts it.
63/70
© by Hakem Beitollahi
Check Yourself
Swap procedure (leaf)
void swap(int v[], int k)
{
int temp;
temp = v[k];
v[k] = v[k+1];
v[k+1] = temp;
}
v in $a0, k in $a1, temp in $t0
64/70
© by Hakem Beitollahi
The Procedure Swap
swap: sll $t1, $a1, 2 # $t1 = k * 4
add $t1, $a0, $t1 # $t1 = v+(k*4)
# (address of v[k])
lw $t0, 0($t1) # $t0 (temp) = v[k]
lw $t2, 4($t1) # $t2 = v[k+1]
sw $t2, 0($t1) # v[k] = $t2 (v[k+1])
sw $t0, 4($t1) # v[k+1] = $t0 (temp)
jr $ra # return to calling routine
65/70
© by Hakem Beitollahi