03 mips assembly language


Published on


Published in: Education, Technology
1 Like
  • Be the first to comment

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

03 mips assembly language

  1. 1. 5/20/2013 EEL 3801C: Computer Organization MIPS Assembly Language Instructor: Zakhia (Zak) Abichar Department of Electrical Engineering and Computer Science University of Central Florida MIPS Assembly Language • A MIPS machine code runs only a MIPS CPU • Conversely, a MIPS CPU can only runs a MIPS machine code • The assembly language consists of a number of instructions – All the instructions in an assembly language are called instruction set • When we invent an instruction set: – We think of simplicity so the hardware design is easy – We think versatility so the machine is powerful 2 1
  2. 2. 5/20/2013 The high‐level languages are not machine‐ dependent. We have a C code. We can compiled it for  various types of machines: UNIX,  Windows,… The low‐level language is machine‐ dependent. The MIPS assembly language and machine  language can run only on a MIPS  processor. 3 Stored‐Program Concept • All computers nowadays use the stored‐program concept • It means the program, along with the data, are stored in the computer  (on the hard disk) • Older computer, of the 1950s, used to store the program on punch  cards which are given to the computer to do the computation • The stored‐program concept is the innovation of John Von Neumann  (it’s called a ‘Von Neumann machine’) • Von Neumann built the first stored‐program computer at Princeton  University • It was called IAS, after Princeton’s Institute for Advanced Studies • The move towards a stored‐program concept was made possible by the  increasing availability of memory and storage in the computer 4 2
  3. 3. 5/20/2013 MIPS Instruction Set • The instruction set contains all the instructions that run on a MIPS  processor • This is a MIPS instruction • add    a, b, c • This instruction will do: a = b + c – The left side variable is the result – The other two variables are the operands • Now we want to add 4 numbers (b, c, d, e) and put the result in variable  a There is no instruction to add b+c+d+e  • The assembly code is: directly. Why? Because such instruction is  • add    a, b, c # a = b + c hard to implement in hardware. • add    a, a, d # add d to a • add    a, a, e # add e to a; now a contains b+c+d+e 5 Reduced Instruction Set Computer (RISC) • To add b,c,d,e we wrote a code of 3 instructions • There is no one instruction in MIPS to do this – Why? Because such instruction is hard to implement in hardware • MIPS assembly language instructions style – Each instruction does a simple task – It’s easy to implement in hardware – The instruction execution time is fast MIPS code to make: a = b+c+d+e add    a, b, c add    a, a, d add    a, a, e • This approach is called Reduced Instruction Set Computer  (RISC) • MIPS is a RISC architecture (so is ARM) Intel x86 architecture (IA‐32 and IA‐64) are Complex Instruction Set Computer (CISC)  since they have some complex instructions. 6 3
  4. 4. 5/20/2013 C to MIPS Assembly • We have the C code: a = b + c; d = a – e; • The compiler translates the C code to the following MIPS  assembly code: add    a, b, c sub    d, a, e 7 C to MIPS Assembly • We have the C code: f = (g + h) – (i + j); • One possible assembly code generated by the compiler is: add    t0, g, h # t0 is a temporary variable add    t1, i, j # t1 is a temporary variable sub    f, t0, t1 When translating from C to assembly language,  there is more than one answer. (Note: f=g+h‐i‐j) Another answer is: add    f, g, h sub    f, f, i sub    f, f, j 8 4
  5. 5. 5/20/2013 Registers • In MIPS assembly language, we have such instructions add    a, b, c sub    d, e, f • • • • Where do these operands (a,b,c,d,e,f) reside? These variables are registers that are located in the CPU A register in MIPS is 32 bits; we call this a word There are 32 registers in the MIPS CPU The MIPS processor can operate on registers only. If we need to  operate on a number that’s in memory, first we bring it from the  memory to a register, then we can use this number in an instruction. 9 Registers in the Assembly Language • A variable in C language (like a,b,c) is mapped to one of the  registers called: $s0, $s1, … • A temporary result is stored in the registers: $t0, $t1,… • The C code: f = (g + h) – (i + j) • The compiler maps f,g,h,i,j to register $s0, $s1, $s2, $s3, $s4 • The compiled MIPS code is: add    $t0, $s1, $s2 # Register $t0 contains g+h add    $t1, $s3, $s4 # Register $t1 contains i+j sub    $s0, $t0, $t1 10 5
  6. 6. 5/20/2013 Variables in Memory • The MIPS CPU has 32 registers only – So we can have a limited amount of data on the CPU • In C programming, we might declare an array of 100 words – int n[100]; – These 100 integers are stored in memory (not on the CPU) – If we need to use one element of the array in an operation (addition,  subtraction,…), we bring it to the CPU and put it in a register – Then, the CPU can perform an operation on it • After we get a result from a CPU instruction, we might need  to write it back to the array – Then we take this result (from a register) and we write it back to the  memory (we put it in the array) 11 Movement of Data and Processing Memory CPU (1) Move data to  registers Large data capacity (2) Perform  operations on  the data Limited storage on the 32 Registers (3) Write the result back to the memory 12 6
  7. 7. 5/20/2013 Moving Data between Memory and CPU • MIPS has instructions to transfer data b/w memory and CPU • They are called data transfer instructions – A data transfer instruction has the address of the data in memory • Transfer a data word (32 bits) from memory to CPU – This is load instruction – The instruction is called “load word” or lw for short • Transfer a data word from the CPU to memory – This is a store instruction – The instruction is called “store word” or sw for short • The address in MIPS is made of two parts: – A base number, which is a number in a register – An offset number, which is a constant number The address is the addition of the base number and the offset number. 13 Memory in MIPS • The memory is byte‐addressable – Every byte has an address 0 1 2 3 These 4 bytes are a  word at address 0 4 5 6 7 Word at address 4 8 9 10 11 12 13 14 15 Word at address 8 Word at address 12 • In MIPS, a data unit is a word, which is 4 bytes • The valid addresses in MIPS are multiples of 4 – MIPS addresses: 0, 4, 8, 12, 16, …, 256, …, 1024, … 14 7
  8. 8. 5/20/2013 Big‐Endian vs. Little Endian • We have 4 bytes that represent a 32‐bit number • We can write the 32‐bit number in two ways Big‐Endian 0 1 2 Little‐Endian 3 0 1 2 3 ‐Write the 32 bits from left to right ‐Write the 32 bits from right to left ‐The Most Significant Bit (MSB) will be  at the smallest address ‐The Least Significant Bit (LSB) will be  at the smallest address • MIPS uses the Big‐Endian representation We have a binary number: 10100010 The leftmost bit is the Most Significant Bit (MSB); it has more weight=27=128 The rightmost bit is the Least Significant Bit (LSB); it has the least weight=1 15 Addresses of an Array • We have an array that is stored in memory • The first element of the array is stored at address 100 – We say that 100 is the base address of the array • The elements of the array are in adjacent locations in the  memory @ address 100 array[0] @ address 104 array[1] @ address 108 array[2] @ address 112 array[3] • Every element takes 4 bytes (word=32bits in MIPS) Element i is at the address: Base address + 4*i = Base address + Offset Ex: element 2 is at the address: 100 + 4*2 = 108 16 8
  9. 9. 5/20/2013 Loading a Word from Memory • We have the C code: g = h + A[8]; • The variables g,h are associated with register $s1 and $s2 • The base address of the array A is in register $s3 – The address of the 1st element in A is equal to $s3 • The MIPS assembly code is: lw      $t0, 32($s3) # Load A[8] in a temporary register add   $s1, $s2, $t0 Format of lw $t0, 32($s3) ‐The register on the left side ($t0) is where the word is loaded (from memory to $t0) ‐The address of the word in memory is 32+[the value in register $s3] 17 Storing a Word • We have the C code: A[12] = h + A[8]; • h is associated with $s2 and the base address of A is in $s3 • First we load A[8] into a register • Then we add the variable h to it • Then we take the result and store it in memory at address A[12] • The assembly code is: lw       $t0, 32($s3) add    $t0, $s2, $t0 sw      $t0, 48($s3) # Load A[8] in register $t0 # Do $t0=h+A[8] # Store the result in A[12] Format of sw $t0, 48($s3) ‐The register on the left side ($t0) is the data that we will write to memory ‐The address in memory where we will write is 48+[the value in register $s3] 18 9
  10. 10. 5/20/2013 Constant Number • The MIPS instruction “addi” allows adding a constant number  to a register – The result is stored in a register addi    $s0, $s0, 4 • This instruction increments the content of register $s0 by 4 • In MIPS terminology, a constant number is called an  immediate number • “addi” stands for “add immediate” 19 Summary so far… 20 10
  11. 11. 5/20/2013 Encoding the Instruction • MIPS has 32 registers; they are numbered from 0 to 31 • In the assembly language, we call them: $s0, $s1, … and $t0, $t1, … – The mapping: $s0 to $s7 map to registers 16 to 23 – Mapping: $t0 to $t7 map to register 8 to 15 • The following instruction: add $t0, $s1, $s2 • is broken down to the following fields Register $s2 Register $s1 Register $t0 The 1st and last fields tell the CPU  that this is an “add” instruction Unused in add  instruction • The CPU looks at this instruction and knows what to do: – It’s an add operation; add $s1 and $s2; put the result in $t0 21 Encoding the Instruction add $t0, $s1, $s2 • The corresponding fields: • In binary: • The instruction is 32 bits • Every instruction in MIPS is 32 bits • In the computer it is stored as: 0000001000110010010000000010000 The first field (6 bits) is called “Operation Code” or “opcode”. This tells the CPU what  instruction it is. Arithmetic and logic instruction have the same opcode (000000). So,  the last 6 bits are used to differentiate between (add, sub, AND, OR, …) 22 11
  12. 12. 5/20/2013 Assembly Language vs. Machine Language • An instruction written like this is called assembly language add $t0, $s1, $s2 • When we write its binary encoding: 0000001000110010010000000010000 • We call it machine language • If we have multiple of them, we call them machine code • For our convenience, we might also write the instruction in  hexadecimal Notice: A MIPS instruction is 32 bits. Also, a MIPS data word is 32 bits. 23 Instruction Format • The fields are given names • This is the format of the arithmetic and logic instruction (add, sub, mul, …,  AND, OR, …) • We call these instructions: R‐type (since they operate on registers only) • All of these instructions have the format • The fields are: – – – – – All the R‐type instructions have the  opcode=000000. We differentiate  between them using the funct code.  A few slides back, we saw that for  “add”, funct=100000. op: the operation of the instruction, or opcode rs: register source operand rt: second register source operand rd: register destination; the result is stored in this register shamt: shift amount; this field is used only in the “shift” instruction; for others it’s set  to: 00000 – funct: function code; when multiple instructions have the same opcode, this field tells  us which instruction it is 24 12
  13. 13. 5/20/2013 “Load Word” (lw) Instruction Format • This is a load word instruction lw $t0, 32($s3) • This is the corresponding instruction format • • • • Register $rs = $s3 = 19 Register $rt = $t0 = 8 Constant = 32 Op = 35 • Notice: in the R‐type instruction, the rt register was used as the second  source. In the load instruction, it’s used as the destination. 25 “Add Immediate” (addi) Instruction Format • This is an add immediate instruction addi $s0, $s1, 4 • This is the corresponding instruction format • • • • Register $rs = $s1 = 17 Register $rt = $s0 = 16 Constant = 4 Op = 8 • The “load word” (lw) and “add immediate” (addi) instructions have the  same format • This format is called Immediate‐Type, or I‐Type 26 13
  14. 14. 5/20/2013 R‐Type Instruction Format Example: [add $s0, $s1, $s2], [sub $s0, $s1, $s2], [and $s0, $s1, $s2], [or $s0, $s1, $s2], … I‐Type Instruction Format Example: [lw $s0, 12($s1)], [sw $s0, 20($s1)], [addi $s0, $s1, 15], … Summary of instruction format so far… 27 • We have the following C code statement Example A[300] = h + A[300]; • Translate this code into MIPS assembly language. The base of the array is in  $t1 and the variable h is mapped to $s2. • Also, write the machine code for the assembly language that you obtained. • In MIPS assembly language lw $t0, 1200($t1) Using the table and add $t0, $s2, $t0 sw $t0, 1200($t1) $t0 to $t7  8 to 15 $s0 to $s7  16 to 23 28 14
  15. 15. 5/20/2013 • The machine code is in binary Example • In binary… 29 Why is there no “subtract immediate”? • Why MIPS assembly language doesn’t have a “subtract immediate”  instruction? • This is the format of the I‐Type (including “addi”) • The 16‐bit constant number is represented in 2’s complement • If we need to subtract, we put a negative number • On 16 bits and using 2’s complement representation – We can write from: ‐32,768 to +32,767 30 15
  16. 16. 5/20/2013 Machine Code • The machine code, encoded in binary, is sometimes called the binary  executable file • This is what we get when we buy a program • The seller keeps the source code (eg: C code…) to themselves since it’s  their intellectual property – We have the right to use the software only • The binary file runs on our computer • Our CPU supports the instructions in the file • For different platforms (Windows, Apple OS, Unix), the binary file is  different • Intel plans their CPU architectures to be backward compatible – I have a program that I bought for WinXP, I run it on Windows 7 – If they were not, the software I bought for my previous computers can’t be used 31 Logical Operations • The table shows some of the logical operations that are supported in the  MIPS assembly language • These operations allow us to access one or more bits inside the word • Example: we need to read the upper (leftmost) 16 bits of a register • We shift this register to the right by 16 bits srl $t0, $s0, 16 • If $s0 = 10101010 11111111 00000000 00110011 • Then, we have: $t0 = 00000000 00000000 10101010 11111111 32 16
  17. 17. 5/20/2013 Shift Left Logical (sll) • This instruction shifts the number to the left • The emptied bits on the right side are filled with 0 • This is a sll instruction: sll    $t2, $s0, 4 • Example: Shift Right Logical (srl)  shifts the number to  the right. It puts 0 in  the emptied bits on the  left side. – Register $s0 = 9. In binary, it is: 00000000 00000000 00000000 00001001 – After the instruction, $t2 = 00000000 00000000 00000000 10010000 = 144 • Shifting to the left by n bits is like multiplying the number by 2n • The “sll” instruction has the format of R‐type • This is the format for: sll $t2, $s0, 4 • Field rs is not used (we put 0), register $s0:16, and register $t2:10  33 AND operation • • • • This is a bit‐by‐bit operation AND can be used to read a field in a word We want to read the rightmost 8 bits in a word The word is: $s0 = 10101010 00001111 01100110 10011001 • First, we load a mask in a register – $t0 = 00000000 00000000 00000000 11111111 • Then, we do: and    $t1, $s0, $t0 • Now, $t1 contains the lowermost 8 bits of register $s0 – We have: $t1 = 00000000 00000000 00000000 10011001 • We call this operation masking because we hid (or masked) the leftmost  24 bits of register $s0 34 17
  18. 18. 5/20/2013 OR operation • • • • This is a bit‐by‐bit operation OR can be used to make some bits in a word become 1 We want to make the leftmost 8 bits in a word become 1 The word is: $s0 = 10101010 00001111  01100110  10011001 • First, we load a mask in a register – $t0 = 11111111 00000000 00000000 00000000 • Then, we do: or    $t1, $s0, $t0 • Now, $t1 contains 1 in the leftmost 8 bits, and is equal to $s0 in the  lowermost 24 bits – We have: $t1 = 11111111 00001111 01100110 10011001 35 NOT Operation • The “inverse” or “not” operation should inverse the bits of a word – 1 becomes 0; and 0 becomes 1 • MIPS doesn’t provide a NOT opertion • We should use the “nor” operation – Use a words=0 as one of the operands • A nor 0 = not(A or 0) = not(A) • To inverse a word bit‐by‐bit, we can do: nor    $t0, $s0, $zero • In MIPS, register number 0 is referred to as $zero – This register always contains the number 0 in it It turns out that zero is a useful value. So a register is dedicated to be always equal to 0. 36 18
  19. 19. 5/20/2013 Summary of instructions so far… Notice, you can also use: •“OR immediate” (ori) •“AND immediate” (andi) 37 Instructions for Making Decisions “The utility of an automatic computer lies in the possibility of using a given  sequence of instructions repeatedly, the number of times it is iterated being  dependent upon the results of the computation. When the iteration is  completed a different sequence of [instructions] is to be followed, so we  must, in most cases, give two parallel trains of [instructions] preceded by an  instruction as to which routine is to be followed. This choice can be made to  depend upon the sign of a number (zero being reckoned as plus for machine  purposes). Consequently, we introduce an [instruction] (the conditional  transfer [instruction]) which will, depending on the sign of a given number,  cause the proper one of two routines to be executed.” ‐ Burks, Goldstine, and von Neumann, 1947 •This quote by von Neumann describes how the computer can make a decision via an if‐ else statement type of instruction. This article might represent the invention of the if‐else  statement in computing. •Notice in the first sentence the term “automatic computer”. Early computer were used  to compute only without decision making. The term “automatic” is used because the  computer can make if‐else or loop style decisions. 38 19
  20. 20. 5/20/2013 Instructions for Making Decisions • High‐level languages have if‐else • In MIPS, we have “branch on equal” (beq) beq $s0, $s1, L1 • If register $s0 is equal to register $s1, the code will go to the instruction  that is labeled L1 “beq” and “bne” are called  conditional branches since  they have a condition. • In MIPS, we also have “branch on not equal” (bne) bne $s0, $s1, L1 • If registers $s0 and $s1 are not equal, the code will jump to label L1 • MIPS also have the “jump” (j) instruction j L1 • The code will jump to label L1 39 Example with Branching • We have the C code: if (i==j) f = g + h; else f = g – h; • This is the translation in MIPS assembly language: (f,g,h,i,j are  mapped to registers $s0 through $s4) bne i, j, Else If the program doesn’t branch, it goes to the  next instruction. add f, g, h The same code using the register numbers: j Exit bne $s3, $s4, Else Else:  sub f, g, h add $s0, $s1, $s2 j Exit Exit: Else: Exit: sub $s0, $s1, $s2 40 20
  21. 21. 5/20/2013 Example with Branching • We have the C code: if (i==j) f = g + h; else f = g – h; • This is the translation in MIPS assembly language: (f,g,h,i,j are mapped  to registers $s0 through $s4) • We can write the code in a different way by using the “beq” instruction beq i, j, Equal sub f, g, h The same code using the register numbers: j Exit beq $s3, $s4, Equal sub $s0, $s1, $s2 Equal:  add f, g, h j Exit Exit: Equal: Exit: add $s0, $s1, $s2 41 Loop • This C code increments the first 5 elements in the array by 1 i=0; while (i <= 4) array[i] = array[i]+1; • The MIPS assembly translation is: (the base of the array is in $s0) add $t0, $s0, $zero # This is the address in the array to load; we will increment it. # We could have used $s0, but we want to leave it unchanged. addi $t1, $s0, 20 # This is the cut off point to stop the loop; array[5] Start: beq $t0, $t1, Exit # $t0 will keep increasing until it reaches $t1 lw $t2, 0($t0) # Load the data in $t2 addi $t2, $t2, 1 # Increment the data by 1 sw $t2, 0($t0) # Write the data back to the same address addi $t0, $t0, 4 # Increment the address to the next element j Start # Jump back to the start Exit: 42 21
  22. 22. 5/20/2013 Example • This is the C code to swap two elements in an array: temp = array[i]; // Code to swap array[i] and array[j] array[i] = array[j]; array[j] = temp; • This is a MIPS assembly language translation. The base of the array is in  $s0, variables i and j are in $s1 and $s2. # $t0 = i*4 sll $t0, $s1, 2 add $t0, $t0, $s0 # $t0 contains the address of array[i] sll $t1, $s2, 2 # $t1 = j*4 add $t1, $t1, $s0 # $t1 contains the address of array[j] lw lw sw sw $t2, 0($t0) $t3, 0($t1) $t2, 0($t1) $t3, 0($t0) # $t2 = array[i] # $t3 = array[j] # array[j] = array[i] # array[i] = previous values of array[j] 43 Comparing Two Registers • The “set‐on‐less‐than” (slt) instruction compares two  registers slt $t0, $s1, $s2 • If $s1 < $s2, then $t0 will become equal to 1 • Else, $t0 will become equal to 0 • A variant of “slt” compares a register to a constant value • ‘slti’: set‐on‐less‐than‐immediate slti $t0, $s1, 7 • If $s1 < 7, then $t0 will become equal to 1 • Else, $t0 will become equal to 0 44 22
  23. 23. 5/20/2013 Example • Compare $s0 and $s1: – Case 1: $s0 = $s1, then write 0 in register $s2 – Case 2: $s0 < $s1, then write 1 in register $s2 – Case 3: $s0 > $s1, then write 2 in register $s2 beq $s0, $s1, Case1 slt $t0, $s0, $s1 bne $t0, $zero, Case2 addi $s2, $zero, 2 j Exit Case2: addi $s2, $zero, 1 j Exit Case1: add $s2, $zero, $zero Exit: # See if it’s Case1. If yes, jump to label “Case1” # (If s0<s1t0=1), (If s0>=s1t0=0) # If $t0 is 1, then it’s Case 2. Branch. # It’s not Case 1 or 2, then it’s Case 3 # We go to “Exit” so we don’t do what’s below # We go to “Exit” so we don’t do what’s below 45 Example • Write a MIPS assembly language code to check if the content of $s0 is  even or odd • If it’s even, write 0 in $s1. Otherwise, write 1 in $s1. • Hint: a binary number that’s even ends with 0; if it’s odd, it ends with 1. addi and $t0, $zero, 1 $t1, $t0, $s0 # This is a mask. It’s equal to 000…00001 # This preserves the rightmost bit of $s0 beq addi j Even: add End: $t1, $zero, Even $s1, $zero, 1 End # If $s0 is even, go to label “Even” # If $s0 is odd, write 1 in $s1 # Skip the case “Even” $s1, $zero, $zero # Write 0 in $s1 46 23
  24. 24. 5/20/2013 Example 2 • An array has n elements. Count the number of elements that are equal to zero. The  base array is in register $s0 and n is in $s1. add $t0, $s0, $zero sll $t1, $s1, 2 add $t1, $t1, $s0 add $t2, $zero, $zero Start: beq $t0, $t1, Exit lw $t3, 0($t0) bne $t3, $zero, NotZero addi $t2, $t2, 1 NotZero: addi $t0, $t0, 4 j Start Exit: # $t0 initialized to the address of 1st element We will access from: # $t1 contains 4*n A[0] to … A[n‐1]. The addresses are: # $t1 contains: $s0 + 4n $s0 to … $s0+4n‐4 # Counter initialized to zero We stop when we get to $s0+4n # Start of loop # $t0 will go up to $t1. Loop stops when $t0=$t1 # Read a word from the array # Skip counting if the word is not zero # Increment the counter by 1 # $t0 has the address of the next element in the array # Go to the start of the loop 47 Additional Instructions • Other instructions similar to ‘slt’ • • • • • ‘sle’: ‘sge’: ‘sgt’: ‘seq’: ‘sne’: set‐on‐less‐or‐equal set‐on‐greater‐or‐equal set‐on‐greater‐than set‐on‐equal set‐on‐not‐equal sle sge sgt seq sne $t0, $s0, $s1 $t0, $s0, $s1 $t0, $s0, $s1 $t0, $s0, $s1 $t0, $s0, $s1 (s0≤s1) (s0≥s1) (s0>s1) (s0=s1) (s0≠s1) • Some of these instructions are pseudo‐instructions, which means  they’re not really implemented by the hardware • They are converted to other instructions by the assembler There are pseudo‐instructions variants of ‘beq’ such as ‘bgt’… find them  in Appendix A starting on page 55. 48 24
  25. 25. 5/20/2013 Pseudo‐instructions • To make assembly programming easier for the programmer,  the assembler recognizes pseudo‐instructions • When the programmer uses a pseudo‐instruction, the  assembler changes it to another instruction that actually  exists (implemented by the hardware) • For example, the ‘mov’ instruction is a pseudo‐instruction mov $t0, $s0 # will do: $t0 = $s0 • The assembler changes it to: add $t0, $s0, $zero 49 MIPS Instructions so far… 50 25
  26. 26. 5/20/2013 Instruction Format 51 Procedures • In assembly language, a function is called ‘procedure’ • The C code below takes two numbers from the user and  passes them to the function • The function returns the larger number among the two int main() { int x, y, bigger; scanf(“%d”, &x); // Prompt the user for the 1st number scanf(“%d”, &y); // Prompt the user for the 2nd number bigger = FindBigger(x, y);       // Call the function. The function returns the larger value printf(“This is the bigger number: %dn”, bigger); // Print the larger value } int FindBigger(int x, int y) { if (x > y) return x; else return y; } // If x is equal to y, the function returns their value. 52 26
  27. 27. 5/20/2013 Supporting Procedures • The architecture provides the following features to support  procedures: – Placing the parameters in a place where the procedure can access  them – Transferring control to the procedure – Reserving storage space that the procedure needs – The procedure should then perform the required task – Placing the result in a place where the calling program can access it – Returning control to the point of origin • Use of registers in MIPS – $a0 to $a3: argument registers; these are used to pass parameters to  procedures – $v0 and $v1: the procedure returns values in these registers – $ra: ‘return address’ register is used to return to the calling code 53 “Jump‐and‐link” (jal) and “jump‐to‐register” (jr) Instructions • These two instructions are used to jump to and return from  procedures • The jump‐and‐link (jal) instruction jumps to a label at the start  of a procedure – “jal” also saves the address of the instruction that is after “jal” in  register $ra (return address register). So, we get: $ra=PC+4 – When the procedure finishes, we return to the address in $ra to get  back to the main code • The jump‐to‐register (jr) instruction jumps to the instruction  whose address is in the specified register – At the end of a procedure, we put [jr $ra], so we jump back to where  we left off in the main code 54 27
  28. 28. 5/20/2013 Assembly Code with a Procedure 100: 104: 108: 112: 116: 120: … ... 320: 324: 328: 332: 336: 340: … lw lw jal sw … $a0, 0($s0) $a1, 4($s0) Procedure1 $v0, 0($s1) This code loads two numbers from the memory  and then calls a procedure to find the larger  number of the two. # Load the 1st number  # Load the 2nd number # Jump to procedure # Store the result It saves 116 in  register $ra Procedure1: slt $t0, $a0, $a1 # (If a0<a1t0=1),(If a0>=a1,t0=0) beq $t0, $zero, Return_a0 add $v0, $a1, $zero # Return $a1 j End Return_a0: add $v0, $a0, $zero # Return $a0 End: jr $ra 55 Assembly Code with a Procedure 100: 104: 108: 112: 116: 120: … ... 320: 324: 328: 332: 336: 340: … lw lw jal sw … We loaded the numbers in $a0 and  $a1 registers because we want to pass  them to the procedure as arguments $a0, 0($s0) $a1, 4($s0) Procedure1 $v0, 0($s1) # Load the 1st number  # Load the 2nd number # Jump to procedure The main function can  use the returned value  # Store the result in register $v0 ‘jal’ jumps to the procedure. Also, the address of the subsequent instruction is  saved in $ra = PC+4 = 116 (when we are executing jal, PC=112) Procedure1: slt $t0, $a0, $a1 # (If a0<a1t0=1),(Ifa0>=a1,t0=0) beq $t0, $zero, Return_a0 add $v0, $a1, $zero # Return $a0 j End $v0 register is used to return the value to the  Return_a0: main function add $v0, $a0, $zero # Return $a1 End: In $ra, we saved 116, now we jump to address  jr $ra 116. This takes us to the main code at the “sw”  instruction. 56 28
  29. 29. 5/20/2013 Saved Registers vs. Temporary Registers • The ‘main’ function in the assembly language program uses the  32 registers in MIPS to make the computations • The ‘main’ function might call a procedure • The procedure uses the same 32 registers of the CPU to make  the computations • Potential problem: the procedure might delete some register  values that the main code needs to use in the future • Solution: – A procedure is allowed to overwrite the temporary registers: $t0 to $t7 – A procedure is not allowed to overwrite the saved registers: $s0 to $s7 – If a procedure needs to use one or more saved registers, it needs to  preserve their values before using them (save them on the stack) 57 The Stack • The stack is a space in the memory where a procedure saves the  registers ($s0 to $s7) before it alters them • The stack is a Last‐In First‐Out (LIFO) structure; it supports these  operations: – Push: save a word on the stack – Pop: retrieve a word from the stack • The stack pointer ($sp) is a register that contains the memory address  of the last word that was pushed on the stack • In MIPS, the stack grows towards smaller addresses 58 29
  30. 30. 5/20/2013 The Stack Before the procedure is  called, there is nothing  on the stack. Before the procedure  modifies $s0, $s1, $s2, it  saves their values on the  stack. In MIPS, the Stack Pointer points at a filled  location on the stack (top value). In other types of  CPUs, the Stack Pointer points at an empty  location that’s one spot after the top of the stack. The procedure returns  its results, if any, in $v0  and $v1. When it  finishes, it doesn’t need  $s0, $s1, $s2 anymore. It  restores their original  values that were saved  on the stack. Now the  stack is empty again. 59 Example: Using the Stack • This is a procedure in C language: int function1(int g, int h, int i, int j) { int f; f = (g + h) – (i + j); return f; } • This is the MIPS assembly code: addi sw add add sub add lw addi jr Notice, below we didn’t  save $t0 and $t1 on the  stack since they are  temporary. $sp, $sp, ‐4 # The stack grows towards smaller addresses $s0, 0($sp) # Save $s0 because the procedure will use it $t0, $a0, $a1 # $a0 and $a1 are the arguments g and h $t1, $a2, $a3 # $a2 and $a3 are the arguments i and j $s0, $t0, $t1 # The result is in $s0 # We return the result in $v0 $v0, $s0, $zero $s0, 0($sp) # We change $s0 to its original value $sp, $sp, 4 # We shrink the stack $ra # Jump back to the calling code 60 30
  31. 31. 5/20/2013 Example 2: Using the Stack • A procedure uses $s0, $s1 and $s2 • It saves all of these on the stack and restores them at the end  of the procedure addi $sp, $sp, ‐12 # Make space for 3 words on the stack sw $s0, 8($sp) # Store the 1st register on the stack sw $s1, 4($sp) # Store the 2nd register on the stack sw $s2, 0($sp) # Store the 3rd register on the stack … <This is where the procedure code is written…> … lw $s2, 0($sp) # Retrieve the register value from the stack lw $s1, 4($sp) lw $s0, 8($sp) addi $sp, $sp, 12 # We shrink the stack jr $ra # Jump back to the calling code 61 Nested and Recursive Procedures • A procedure that doesn’t call another procedure is called a  leaf procedure • A procedure that calls another procedure is called a nested  procedure • A procedure that calls itself is called a recursive procedure int bigger(int x, int y) { if(x > y) return x; else return y; } int fn1(int x, int y) { if(x>0 && y>0) return avg(x,y); else return y; } int factorial(int n) { if(n<1) return 1; else return (n*factorial(n‐1)); } This is a leaf function. It  doesn’t call any other  function. This is a nested function.  It calls another function  (the function “avg”). This is a recursive function. It  calls itself. 62 31
  32. 32. 5/20/2013 Recursive Procedure • A procedure that calls itself • Some problems are easy to program via a recursive algorithm – A problem that can be reduced into a similar problem of smaller size • • • • Computing the factorial of an integer n! = n.(n‐1).(n‐2)…3*2*1 Eg: 4! = 4*3*2*1 = 24 By definition 0! = 1 • Observe: n! = n * (n‐1)! – We reduced the problem (finding n!) into a smaller problem of  smaller size (finding (n‐1)!) 63 Factorial Algorithm • This is the C code for a recursive factorial algorithm int factorial(int n) { if (n<1) // By definition 0!=1 return 1; else return (n*factorial(n‐1)); // Recursive call } • We don’t want the recursive function to keep calling itself  infinitely • There is one (or more) trivial case or base case – We know the answer of the trivial case so we don’t have to make  another recursive call – Here, the trivial case is factorial(0)=1 64 32
  33. 33. 5/20/2013 int factorial(int n) { if (n<1) // By definition 0!=1 return 1; else return (n*factorial(n‐1)); // Recursive call } • We call this function with n=3 – – – – – – – It will return 3 * factorial(2) There will be another call with n=2 It will return 2 * factorial(1) There will be another call with n=1 It will return 1 * factorial(0) There will be another call with n=0 It will return 1 • Now we know factorial(0)=1,  we substitute in  [1*factorial(0)]=1 • Now we know factorial(1)=1,  we substitute in  [2*factorial(1)]=2 • Now we know factorial(2)=2,  we substitute in  [3*(factorial(2)]=6. This is the  answer. When the recursive algorithm is running, the computations will stack up  (left side). Once we reach to the trivial case, we go up the stacked things  and combine the solutions to get the final answer (right side). 108: 112: 116: 120: … ... 300: 304: 308: 312: 316: … jal sw … Procedure1 $v0, 0($s1) It saves $ra=116 Procedure1: add $t0, $a0, $a1 … jal Procedure1 … jr $ra # Jump to procedure # Store the result 65 How do we support  recursive procedures in  MIPS? $ra becomes equal to 312 (the old value=116 is lost) # Recursive call What’s wrong with the code above? The main function calls Procedure1 using the ‘jal’ instruction Therefore, the return address is saved; $ra=116 Procedure1 is a recursive function and calls itself using ‘jal’ Therefore, a new value is saved in the return address register; $ra=312 We’ve lost the original $ra value (116) and we can’t go back to the main function Solution: In recursive functions, before ‘jal’ is used, the value of $ra is saved on the stack This means Procedure1 should have saved $ra on the stack before using ‘jal’ to call itself 66 33
  34. 34. 5/20/2013 Factorial Procedure  (recursive) in MIPS fact: addi sw sw $sp, $sp, ‐8 $ra, 4($sp) $a0, 0($sp) # Make room for 2 words on the stack # Push the return address on the stack # Push the argument value on the stack slti beq $t0, $a0, 1 $t0, $zero, L1 # (If a0<1t0=1), (If a0>=1t0=0) # If it’s not the trivial case, go to label L1 addi addi jr $v0, $zero, 1 $sp, $sp, 8 $ra # If it’s the trivial case, the answer is 1 # Remove the two words we put on the stack # and return to the main code L1: addi jal $a0, $a0, ‐1 fact # We branched to here because it’s not the trivial case # We find the new argument # and we make a recursive call lw lw addi $a0, 0($sp) $ra, 4($sp) $sp, $sp, 8 # We get here only after the trivial case is finished. We load the  # argument and the return address that were saved on the stack # Readjust the stack pointer after removing the two words mul $v0, $a0, $v0 # The trivial case did $v0=1. Now we multiply the next number jr $ra # We return either to the 1st lw instruction; or we finished fact: addi sw sw $sp, $sp, ‐8 $ra, 4($sp) $a0, 0($sp) slti beq $t0, $a0, 1 $t0, $zero, L1 addi addi jr $v0, $zero, 1 $sp, $sp, 8 $ra L1: addi jal $a0, 0($sp) $ra, 4($sp) $sp, $sp, 8 mul $v0, $a0, $v0 jr $ra Factorial Procedure  (recursive) in MIPS $a0, $a0, ‐1 fact lw lw addi 67 These instructions will be repeated while  we are pushing things on the stack and  making the problem smaller: n! = n * (n‐1)! These instructions will be done once when  we reach the trivial case These instructions will be repeated as many time as  we did the above group of instructions. With these  instructions, we will take things off the stack and  combine the results (1*2*3…) until we get the final  answer. 68 34
  35. 35. 5/20/2013 fact: addi sw sw slti beq $t0, $a0, 1 $t0, $zero, L1 addi addi jr $v0, $zero, 1 $sp, $sp, 8 $ra L1: addi jal $a0, $a0, ‐1 fact lw lw addi $a0, 0($sp) $ra, 4($sp) $sp, $sp, 8 mul $v0, $a0, $v0 jr Factorial Procedure  (recursive) in MIPS $sp, $sp, ‐8 $ra, 4($sp) $a0, 0($sp) $ra 69 Frame Pointer During the  procedure Before the  procedure After the  procedure During the  procedure, $sp will  move up and down  but $fp will stay in the  same place. The use of $fp is not  necessary. Some  compilers don’t use  $fp.      When a procedure runs out of registers, it puts variables on the stack If the stack is used during the procedure, $sp will go up and down Therefore, the address of a certain words on the stack will change! This makes it difficult to keep track of this word We use the frame pointer ($fp). It points to the start of the procedure’s  space on the stack and it doesn’t change during the procedure.  A variable that the procedure has put on the stack will have the same  offset with respect to $fp since $fp doesn’t change during the procedure 70 35
  36. 36. 5/20/2013 The Heap vs. The Stack • • • • • The figure shows the total space allocated for a program The lowest addresses are reserved It’s followed by the MIPS machine code, called text segment Above, there is the static variables and constants Above, there is the dynamic data structures, eg: linked lists; this space is called the heap •The stack is at the highest  address and grows down •The stack and the heap grow in  different directions to use the  memory space efficiently •To simplify access to static  data, MIPS uses the global  pointer register ($gp) 71 Allocate and Free Memory • In C, we can use malloc() and free() to allocate and free  memory dynamically • This space is allocated on the heap • If the programmer forgets to free the memory, this might lead  to memory leak and the program might run out of memory • If the programmer frees the memory and tries to access it  later, this is called dangling Example: In C, we are writing a code. We  need an array whose size will be  input by the user. At the time we’re  writing the code, we don’t know  the size of the array. We use  malloc() to allocate memory and  free() to release the memory. 72 36
  37. 37. 5/20/2013 Passing More than 4 Parameters • If we need to pass more than 4 parameters to a procedure,  they won’t fit in the argument register ($a0, $a1, $a2, $a3) • The remaining parameters are passed on the stack right at $fp • Within the procedure, we access them as: 0($fp), 4($fp), …, • Even though is the $sp is changing, the variables’ addresses with respect to $fp stay the same •The use of the frame pointer is not mandatory •If it’s not used, the compiler will access the variables  on the heap with respect to $sp, which will be  changing during the code •The displacement will change: the same variable will  be 8($sp) and later will be 4($sp) 73 74 37
  38. 38. 5/20/2013 Instruction Formats 75 Representing Text • The ASCII (American Standard Code for Information Interchange) code is  used to represent text • A letter is represented by 8 bits • In MIPS, we can use logical and shift operations to extract 8 bits from  the 32‐bit word – A MIPS word has space for 4 ASCII characters • MIPS provides instructions to read/write from memory 1 byte • Load byte (lb) loads a byte from memory and puts it in the rightmost 8  bits of a register – Eg: lb $t0, 0($gp) • Store byte (sb) takes the rightmost byte from a register and writes it to  memory – Eg: sb $t0, 0($gp) 76 38
  39. 39. 5/20/2013 ASCII Code In C, this string represents “UCF”. The value 0 represent the end of the string. 85 67 70 0 01000011 01000110 00000000 This is the MIPS word: 01010101 77 Representing a String • There are 3 popular ways to represent a string in the memory • #1: it’s used in C: – The string has n characters, we reserve n+1 bytes – The last byte=0 represents the end of the string • #2: it’s used in Java – An accompanying variable indicates the size of the string – Therefore, we use two variables to define a string • #3: – The first position in the string indicates the length  78 39
  40. 40. 5/20/2013 String Copy Function (strcpy) • This function in C language allows us to copy one string to another • In C, the string is terminated by the NULL character (value=0) • In the code below, we manually copy the NULL character at the end of  the string void strcpy (char x[], char y[]) { int i; i=0; while(y[i] != ‘0’) { x[i] = y[i]; i = i + 1; } x[i] = y[i]; // Copy the Null=0 character } 79 # Copy y into x; base address of x and y are in $a0 and $a1, respectively strcpy: addi $sp, $sp, ‐4 # Adjust the stack for 1 more word sw $s0, 0($sp) # We will use $s0, so we save it on the stack add $s0, $zero, $zero Start: add $t1, $s0, $a1 lb $t2, 0($t1) # This will hold the index i # $t1 has the address of y[i] add sb $t3, $s0, $a0 $t2, 0($t3) # $t3 has the address of x[i] beq $t2, $zero, End # Is the array done? addi j $s0, $s0, 1 Start # Notice here, we increment the index by 1 End: lw addi jr $s0, 0($sp) $sp, $sp, 4 $ra # Restore the value of $s0 from the stack # Readjust the stack pointer 80 40
  41. 41. 5/20/2013 Unicode Letter Representation • • • • Unicode uses 16 bits to represent a character Therefore, it can represent 216 = 65,536 Unicode represents multiple languages Java uses Unicode to represent letters • MIPS provides the following instructions • Load half (lh): – Load 16 bits from the memory to register • Store half (sh): – Store 16 bits from a register to the memory 81 Word Alignment • MIPS keeps the word addresses aligned to multiples of 4 • The valid word addresses are multiples of 4 • If there is one character variable encoded in ASCII (char c;) – It needs 1 byte but MIPS allocates 4 bytes for it to keep words  aligned, as in figure below (‘A’). Therefore, 3 bytes are wasted. • But if it’s an array of characters (string), then there can be 4  characters in a MIPS word – In this case, the memory is used efficiently 32‐bit number @ address100 10101010 00000000 00001111 11111111 8‐bit character @ address104 ‘A’ unused unused unused 32‐bit number @ address108 00001111 00001111 11110000 10101010 4‐character string @add. 112 ‘A’ ‘B’ ‘C’ ‘D’ 82 41
  42. 42. 5/20/2013 Loading a Number in a Register • We can use the ‘addi’ instruction addi $s0, $zero, <number> • The format of addi is: • With ‘addi’, we can load at most a 16‐bit number in the  register • What if we need to load a 32‐bit number in a register? – Two instructions are used to do this 83 Loading a 32‐bit Number in a Register • Load upper immediate (lui) instruction loads a 16‐bit number in  the left half of a register; the right half is filled with zeros • Our goal is to load in $s0: 0000000011111111 0101010101010101 • Load the leftmost 16 bits: lui $s0, 0000000011111111 • After this: $s0=0000000011111111 0000000000000000 • Now, the lower part of $s0 is loaded • We can do:  ori $s0, $s0, 0101010101010101 16‐bit extended to 32 bits 0000000000000000 0101010101010101 OR $s0 0000000011111111 0000000000000000 • Now: $s0 = 0000000011111111 0101010101010101 84 42
  43. 43. 5/20/2013 Example = 61 in base 10 = 2304 in base 10 85 Loading a 32‐bit Number into a Register • Load the number: 0000000010101010 1111111100001111 • Is the code below correct? (no) lui$s0, 0000000010101010 addi $s0, $s0, 1111111100001111 • This code is wrong!!! • After the ‘lui’ instruction, we have: – $s0 = 0000000010101010   0000000000000000 • However, when we’re adding 1111111100001111, this 16‐bit number is  sign extended to 32 bits! $s0 0000000010101010 0000000000000000 + 16‐bit number gets sign extended 1111111111111111 1111111100001111 • Instead of ‘addi’, use ‘ori’, because the extension to 32 bits is logical so  the 16‐bit becomes: 0…00000 1111111100001111 ori doesn’t sign extend (it adds 0 on the left side) addi sign extends (the left most bit is repeated to preserve the sign) 86 43
  44. 44. 5/20/2013 Jump Instruction Format • It is the J‐type format, Syntax: j Label • The address is designated by 26 bits • How do we get the actual 32‐bit address of the instruction  we’re jumping to? PC+4[31:28] 26‐bit number in the ‘j’ instruction Leftmost 4 bits of PC+4. We jump to  somewhere that’s somewhat close to the  current instruction. This is because all of a  program’s code is stored in one memory  space. 00 MIPS addresses are multiples of 4. Every  address written in binary ends with ’00’.  So when we encode the ‘j’ instruction, we  remove ’00’ and then we add it later. This  allows us a larger jump range. 87 Example • Find the jump address. Assume that PC=24 00  00000000  00000000  00001011 • PC+4=28=0000000000000000 0000000000011100 – Take the leftmost 4 bits of PC+4  0000 • The jump address is: PC+4[31:28] 26‐bit number in the j instruction 00 0000    00000000000000000000001011     00 88 44
  45. 45. 5/20/2013 Branch Instruction Format • Branch‐on‐equal (beq); Syntax: beq $s0, $s1, Exit 4 • The branch address is: PC + 4 + SignExtendTo32[ShiftLeftBy2(16‐bit number)] • This is the procedure: – Take the 16‐bit number, add ’00’ on the right side (shift left by 2) – The ‘00’ were omitted in the encoding since all instruction addresses  end with ’00’ (omitting the ’00’ gives us a longer range in the branch) • Sign extend the 18‐bit number above to 32 bits • Add this to PC+4 Why do we add to PC+4 not to PC? Because when the CPU is executing  instructions, it automatically updates PC to PC+4. So by the time we  decode the ‘beq’ instruction, PC has been incremented by 4. 89 Branch Instruction Format • Branch‐on‐equal (beq); 4 Syntax: beq $s0, $s1, Exit 00000000  00000111 • The branch is taken when the two registers are equal • Find the branch address • Assume that PC=20 • First, we shift the 16‐bit number left by 2 bits – It becomes: 00000000 0000011100  equal to: 28 • Sign‐extend to 32 bits: 000…0000000011100 (still equal to 28) • PC+4 = 24. We add 28 to it, the branch address is 52 • On 32 bits, it is: 00000000  00000000  00000000  00110100 90 45
  46. 46. 5/20/2013 • Translate the MIPS assembly code below into machine code • Also, fill the branch and jump addresses assuming that the  code is stored in the memory starting at address 80,000 80,000 80,004 80,008 80,012 80,016 80,020 80,024  “bne $t0, $s5, Exit” branches from address 80,012 to address 80,024  Branch address = PC+4+offset  offset = 80,024–80,012–4 = 8  Instead of putting 8 (1000) in the instruction, we drop the ’00’ from the  right side  So we store ’10’(binary) in the instruction over 16 bits  The values of “bne” instruction fields are below in decimal 5 8 21 2 91 80,000 80,004 80,008 80,012 80,016 80,020 80,024  “j Loop” instruction jumps to address 80,000  This is how we find the 26‐bit field in ‘j’ instruction PC+4[31:28] 26‐bit number in the j instruction 00  Jump address is: 80,000  00000000  000000001  00111000  10000000  The right ’00’ are dropped; the upper 4 bits aren’t included  The 26‐bit field in the instruction is: 0000 00000001 00111000 100000,  which is 20,000 in decimal 2 20,000 92 46
  47. 47. 5/20/2013 • This is the machine code for the remaining instructions 80,000 80,004 80,008 80,012 80,016 80,020 80,024 93 Branch and Jump Ranges • Using the branch and jump instructions, we can jump to  higher or lower addresses in the code – In ‘beq’, the 16‐bit field is sign‐extended, since it might be negative • ‘beq’ uses a 16‐bit number for the offset • ‘j’ uses 26 bits for the jump address • Therefore, the jump ‘j’ instruction has a longer range • What if we want to branch to an instruction that’s far away,  so that the 16‐bit field in ‘beq’ is not sufficient? beq $s0, $s1, L1 These two codes are equivalent but the code on  the right side gives a longer branching range. bne j L2: … $s0, $s1, L2 L1 94 47
  48. 48. 5/20/2013 MIPS Addressing Modes Summary • “Addressing mode” is how the instruction gets its operands • Register addressing: – The operand is taken from the register (eg: add $t0, $t1, $t2) • Base or displacement addressing: – We add the base (of an array) to an offset to find the data’s address  in memory (eg: lw $t0, 0($s1)) • Immediate addressing: – The operand is a constant encoded in the instruction (addi $t0,$t1,4) • PC‐relative addressing: – In the branch instructions (beq, bne), the offset is added to the PC • Pseudodirect addressing: – In the jump address, almost all of the address is in the instruction (26  bits out of 32 bits are encoded in the instruction) 95 The Addressing Modes 96 48
  49. 49. 5/20/2013 Register $at is reserved for assembler to handle large constants 97 98 49
  50. 50. 5/20/2013 Translating a Code from C to Executable • Object: contains assembly instructions; the file is not finalized • Linker: library routines don’t need to be compiled every time we compile  our code since they don’t change (they are linked to the object file) 99 Pseudoinstructions • The assembler accepts pseudoinstructions but they are not  implemented by the hardware – They make it easy for the programmer who’s writing assembly  instructions • Example: blt $s0, $s1, Label # If s0<s1, branch to Label This is a pseudo instruction, the assembler replaces it with: slt $t0, $s0, $s1 # (If s0<s1  t0=1), (If s0>=s1  t0=0) bne $t0, $zero, Label # Branch if t0=1; it means s0<s1 50