Algorithm for Writing Efficient Recursive Functions in Assembly
Algorithm for Writing Efficient Recursive Functions in Assembly Language Salam N. Salloum Department of Computer Science California State Polytechnic University, Pomona Cal Poly Pomona Computer Science Department
Importance of Assembly Programming and Recursive Function Ø Assembly programming is required for efficient implementation of some embedded software products. Ø Assembly programming is an important component in teaching Computer Organization & Architecture, Compiler, and Programming Languages. Ø Implementation of recursive function in assembly languages is sometimes needed for embedded system design. Cal Poly Pomona Computer Science Department
Recursive Function in Assembly Language Ø Writing a recursive function in assembly language enhances students’ understanding of recursive function implementation and execution. Ø It also enhances students’ skill of writing recursive function in high-level languages. Ø The next slide outlines the traditional procedure for writing recursive function in assembly language as well as the implementation of such functions by compilers. Cal Poly Pomona Computer Science Department
Recursive Function in Assembly Language (Cont. ) Ø One or more stacks are used to perform the following: Before calling a recursive function by another function or by itself, the contents of the registers which may change are saved by pushing them on a stack; § The computed (or return) values are saved on a stack; § The contents of registers are restored to their previous values by popping the stack. § Ø Ø This procedure may require stacks of a large size and a considerable number of stack operations. The stack reduction problem for recursive function implementation has been addressed by some authors. Cal Poly Pomona Computer Science Department
Recursive Function in MIPS Assembly Language Ø MIPS processor is one of the most commonly used RISC processors in industry and computer science and engineering classrooms. Ø Four of the MIPS registers ($a 0, $a 1, $a 2, $a 3) are used for storing the parameters of a recursive function, and the registers $v 0 and $v 1 are used for storing the return values. Ø The register $sp is a stack pointer which points to the current location of the stack. Cal Poly Pomona Computer Science Department
Algorithm for Writing Efficient Recursive Function Ø Ø Each recursive function definition consists of one or more base cases and one or more recursive cases, where each recursive case may consist of one or more calls of the recursive function. For example: GCD(n, 0) = n GCD(0, m) = m GCD(n, m) = n if n=m GCD(n, m) = GCD(n, m%n) if m>n GCD(n, m) = GCD(n%m, m) if m<n This example has three base cases and two recursive cases, where each recursive case has only one recursive call. Cal Poly Pomona Computer Science Department
Algorithm for Writing Efficient Recursive Function (Cont. ) Ø Ø Ø For each of the following steps, assume that the parameters are in registers $a 0 to $a 3 before any recursive call is made, and that the return values will be saved in registers $v 0 and $v 1. Step 1: Implement each base case separately and save the return values in registers $v 0 and $v 1. Step 2: Implement each recursive case separately. The values that need to be pushed on the stack are as follows: § Every external variable (those that appear outside the function calls) appears in the recursive case. For example, the variable n is an external variable in the factorial function: fact. R(n) = n*fact. R(n-1).
Algorithm for Writing Efficient Recursive Function (Cont. ) Ø Step 2 (Cont. ): § Save the return values of every recursive call, except for the last recursive call, that appear in the recursive case. For example, in the recursive case: f(n) = f(n-1) + f(n-2) + f(n-3) the return values of the first two calls must be saved. § Save the return address which has been saved in register $ra by a call statement. Cal Poly Pomona Computer Science Department
Algorithm for Writing Efficient Recursive Function (Cont. ) Ø Step 2 (Cont. ): Save the values of the changing parameters needed for every recursive call, except for the first call. For example, in the recursive case: Fibonacci(n) = Fibonacci(n-1) + Fibonacci(n-2) the variable n must be saved because it is a parameter for the second call. For the recursive case: f(n, k)=f(n-1, k)+f(n-2, k) there is no need to save the parameter k because it is not changing from one recursive call to another. However, the parameter n must be saved because it is changing. § Cal Poly Pomona Computer Science Department
Algorithm for Writing Efficient Recursive Function (Cont. ) Step 3: After making any recursive call, retrieve (pop) the needed values from the stack and perform the required computation and store the return values in registers $v 0 and $v 1. If there is another recursive call in the recursive case, the return values of the current call as well as the parameters of the next call must be saved in the stack. Ø Step 4: At the end of each recursive case restore the return address ($ra) by loading its value from the stack. Ø Cal Poly Pomona Computer Science Department
Example: Factorial Function . text li $a 0, 4 jal move fact. R $a 0, $v 0 li $v 0, 1 syscall li $v 0, 10 syscall fact. R: bgtz $a 0, recu li jr $v 0, 1 $ra # Load the Register $a 0 with the # value of N # Call the factorial function fact. R # Move the result to the Register # $a 0 to be printed. # Go to the recursive part. # Note, N is in $a 0 # Process the base case
Example: Factorial Function (Cont. ) recu: addiu sw addi jal lw mul lw addiu jr $sp, -8 # Reserve 8 bytes on the stack $a 0, 4($sp) # Push N $ra, 0($sp) # Push the return address $a 0, -1 fact. R # Compute (N-1) ! $t 0, 4($sp) # Load N $v 0, $t 0, $v 0 # Compute N ! $ra, 0($sp) # Load the Register $ra with # the return address $sp, 8 # Release the 8 bytes of the stack $ra
Example: Fibonacci Function fib: bgt $a 0, 1, recu # Note, N is in $a 0 move $v 0, $a 0 # the base case jr $ra recu: addiu $sp, -12 sw $ra, 0($sp) sw $a 0, 4($sp) # store the parameter because # it is needed to call the second # part of the equation, fib(N-2). addi $a 0, -1 jal fib # compute fib(N-1)
Example: Fibonacci Function sw lw addi jal lw addiu jr $v 0, 8($sp) # push the value of fib(N-1) $a 0, 4($sp) # get the value of $a 0, -2 fib # compute fib(N-2) $t 0, 8($sp) # get the value of fib(N-1) $v 0, $t 0, $v 0 # compute fib(N) $ra, 0($sp) $sp, 12 $ra
Example: Binary Search /* int BSR(int []A, int low, int high, in value) { /* if (low<= high) { /* int mid =(low + high)/2; /* if (A[mid]==value) return mid; /* if (A[mid]> value) return BSR(A, low, mid-1, value); /* return BSR(A, mid+1, high, value); } /* return -1; /* }
Example: Binary Search (Cont. ) /* Assume $a 0= &A, $a 1=low, $a 2=high, and /* $a 3=value /*the base case BSR: ble $a 1, $a 2, comp. With. Mid li $v 0, -1 jr $ra /* compare with mid comp. With. Mid: add sra $t 0, $a 1, $a 2 $t 0, 1 /* $t 0 contains the mid
Example: Binary Search (Cont. ) /* Now to compute the address of A[mid] to be compared with /* $a 3= value sll $t 1, $to, 2 add $t 1, $a 0, $t 1 /* $t 1= the address of /* A[mid] lw $t 2, 0($t 1) /* $t 2= A[mid] bne $t 2, $a 3, rec /*$a 3= value move $v 0, $t 0 jr $ra
Example: Binary Search (Cont. ) rec: bgt $t 2, $a 3, smaller /* the following is for the case value > A[mid] greater: addiu $sp, -4 sw $ra, 0($sp) addi $t 0, 1 /* $t 0= mid +1 move $a 1, $t 0 /* now $a 1 = mid+1 as the value of the first index and /* $a 2= high as the value of the second index. jal BSR lw $ra, 0($sp) addiu $sp, 4 jr $ra
Example: Binary Search (Cont. ) /* the following is for the case value < A[mid] smaller: addiu $sp, -4 sw $ra, 0($sp) addi $t 0, -1 /* $t 0= mid -1 move $a 2, $t 0 jal BSR lw $ra, 0($sp) addiu $sp, 4 jr $ra /* It is possible to reduce the code to only one /* recursive call. However, this reduction will not /* reduce the number of stack operations.
Examples of Homework and Test Problems 1 Fun(n, k) = n + k if n < k Fun(n, k) = n+k+Fun(n-1, k) if n < k 2 int largest(int[] A, int size, int i){ if (i == size-1) return A[i]; else { if(A[i] > largest(A, size, i+1)) return A[i]; else return largest(A, size, i+1); } } Cal Poly Pomona Computer Science Department
Examples of Homework and Test Problems (Cont. ) 3 conv. To. Binary(n) = Print(0) if n =0 conv. To. Binary(n) = conv. To. Binary(n/2) Print(n%2) 4 Exp(a, n) = 1 Exp(a, n) = Exp(a*a, n/2)*a Cal Poly Pomona if n=0 if n is even if n is odd Computer Science Department
Conclusions Ø A simple algorithm for writing efficient MIPS assembly programs for recursive functions. Ø The algorithm generates programs with a reduced number of stack operations. Ø It seems that the algorithm can be implemented as a software tool for automatic code generation. Cal Poly Pomona Computer Science Department
- Slides: 22