# Program Translation --- CS 130 // 2021-10-20 ## Administrivia - Quiz 2 and 3 graded and returned on Gradescope - Assignment 3 and Midterm Exam 2 are pushed back + Monday will be primarily for practice problems for the exam and for working on assignment 3 # Questions ## ...about anything? # Procedures ## Calling a Procedure 1. Put parameters in appropriate registers + `$a0`, `$a1`, `$a2`, `$a3` 2. Transfer control to the procedure + `jal ProcedureLabel` 3. Perform task 4. Place result in a location the callee can find + `$v0`, `$v1` 5. Return control to the caller + `jr $ra` ## Leaf Procedures - A **leaf procedure** is a function that makes no other function calls ```c int func(int x, int y) { return x + y; } ``` --- ```mips func: add $v0, $a0, $a1 jr $ra ``` ## Non-Leaf Procedures - Non-leaf procedures are the interesting cases ```c int termial(int n) { if (n == 0) { return 0; } else{ return n + termial(n - 1); } } ``` - Before a procedure calls another procedure, it needs to **save** any data that might be overwritten by the procedure call **in memory** ## Non-Leaf Procedures ```mips[1|13,14|5-6,10-11|2-4,7-9|1-14] termial: beq $a0, $zero, ret_zero # Checks base case addi $sp, $sp, -8 # Allocates space sw $ra, 0($sp) # for $ra and n sw $a0, 4($sp) # on the stack addi $a0, $a0, -1 # Loads n-1 as arg jal termial # Calls termial(n-1) lw $a0, 4($sp) # Restores n lw $ra, 0($sp) # Restores $ra addi $sp, $sp, 8 # Deallocates memory add $v0, $v0, $a0 # Adds n to result jr $ra # Returns result ret_zero: li $v0, 0 # Returns 0 jr $ra ``` # Tail Calls ## Tail Calls - A **tail call** is when a procedure immediately returns the result of another procedure ```c int foo(int x) { return x + x; } int bar(int x) { int y = x + x; return foo(y); // this is a tail call } ``` - A tail call can be implemented **without** creating a new procedure frame ## Tail Calls ```c int foo(int x) { return x + x; } int bar(int x) { int y = x + x; return foo(y); } ``` ```mips foo: add $v0, $a0, $a0 jr $ra bar: add $a0, $a0, $a0 j foo ``` ## Tail Recursion - If a function makes tail calls to itself, it is called **tail recursive** - Is our implementation of `termial` tail recursive? ```c int termial(int n) { if (n == 0) { return 0; } else { return n + termial(n - 1); } } ``` - No! It has to add `n` before returning ## Tail Recursion - Can we implement it tail recursively? ```c int termial(int n) { return termial_helper(n, 0); } int termial_helper(int n, int so_far) { if (n == 0) { return so_far; } else { return termial_helper(n - 1, n + so_far); } } ``` ## Tail Recursion - What does this look like in MIPS? ```mips termial: li $a1, 0 j termial_helper ``` ```mips termial_helper: beq $a0, $zero, ret_so_far add $a1, $a1, $a0 addi $a0, $a0, -1 j termial_helper ret_so_far: move $v0, $a1 jr $ra ``` # Summing an Array ## Summing an Array - Let's compile the following function to MIPS: ```c int sum(int *arr, int size) { int total = 0; for (int i = 0; i < size; i++) { total = total + arr[i]; } return total; } ``` ## Summing an Array ```mips sum: li $v0, 0 li $t1, 0 while: bge $t1, $a1, done sll $t2, $t1, 2 add $t2, $a0, $t2 lw $t3, 0($t3) add $v0, $v0, $t3 j while done: jr $ra ``` # Fibonacci ## Fibonacci - Recall that the Fibonacci sequence that starts with 1, 1, and then each successive number is the sum of the previous two - We can calculate the $n$th Fibonacci number recursively: ```c int fib(int n) { if (n == 0 || n == 1) { return 1; } else { return fib(n-1) + fib(n-2); } } ``` ## Fibonacci in MIPS ```mips fib: beq $a0, $zero, return # Handles base case addi $t0, $zero, 1 # of n == 0 and n == 1 beq $a0, $t0, return addi $sp, $sp, -12 # Allows space on the stack sw $ra, 0($sp) # for $ra, $a0, and $v0 sw $a0, 4($sp) addi $a0, $a0, -1 # Computes fib(n-1), puts jal fib # it on the stack sw $v0, 8($sp) lw $a0, 4($sp) # Computes fib(n-2) addi $a0, $a0, -2 jal fib lw $t0, 8($sp) # Takes sum of two results add $v0, $v0, $t0 lw $ra, 0($sp) # Deallocates stack memory addi $sp, $sp, 12 # and returns jr $ra return: addi $v0, $zero, 1 jr $ra ``` ## Alternative Fibonacci Implementation ```c int fib(int n) { int prev1 = 1, prev2 = 1; for (int i = 0; i < n; i++) { int next = prev1 + prev2; prev2 = prev1; prev1 = next; } return prev1; } ``` ## Fibonacci (Loop) ```mips fib: addi $t0, $zero, 0 # i addi $v0, $zero, 1 # prev1 addi $v1, $zero, 0 # prev2 loop: bge $t0, $a0, return add $t1, $v0, $v1 li $v1, $v0 li $v0, $t1 addi $t0, $t0, 1 j loop return: jr $ra ``` # Regions of MIPS Code ## Regions of MIPS Code - There can be multiple regions of a MIPS program + **.text**: Contains *program instructions* + **.data**: Contains *initial memory* ## Interaction with the OS - We are used to **printing** characters and **reading** characters within our programs which requires interaction with the operating system - In MIPS, we need to use the **syscall** instruction to send or receive information from the OS - To request a service, you must: + Put an **instruction code** in `$v0` + Put any arguments into `$a0`--`$a3` + Execute `syscall` ## Input/Output Example ```mips .data S1: .asciiz "Type in an integer: " S2: .asciiz "You entered the following: " .text main: add $v0, $zero, 4 # system code for print_str la $a0, S1 syscall addi $v0, $zero, 5 # system code for read_int syscall addi $t0, $v0, 0 addi $v0, $zero, 4 la $a0, S2 syscall addi $a0, $t0, 0 addi $v0, $zero, 1 # system code for print_int syscall addi $v0, $zero, 10 # system code for terminate syscall ``` # Program Translation ## Program Translation - What exactly happens when you run `gcc` on a C program? - It goes through several stages --- 1. Compiler 2. Assembler 3. Linker 4. Loader ![Program Translation](/teaching/2021f/cs130/assets/images/COD/compiler-diagram.png)