invoke Function, Parameters |
Push Parameters Call Function Add eSp, <Number of Parameter bytes> |
Function Proto Near C, Parameters if: Terminating Condition is true then: base case result else: recursive case result Push Parameters invoke Function, Parameters endif: Ret Function Endp |
Function Proc Near Push eBp Mov eBp, eSp if: Terminating Condition is true then: base case result else: recursive case result Push Parameters Call Function Add eSp, <Number of Parameter bytes> endif: Pop eBp Ret Function Endp |
Write a function in C++ using Recursion to print numbers from n to 0.
Write a function in Assembler using Recursion to print numbers from 0 to n.
0! = 1Note that:
n! = n * (n-1)!
(n-1)! = (n-1) * (n-2)!so for:
n = 3 3! = 3*2!
n = 2 2! = 2*1!
n = 1 1! = 1*0!
n = 0 0! = 1 by definition
#include <iostream.h>
int Fact(int N) {
if( N <= 0) return 1; // base case result
else return N*Fact(N-1); // recursive case result
}
void main(void) {
cout << Fact(3);
}
|
|
Title Fact - Recursive function with one parameter, n!
.386
.model flat, stdcall
PutDec proto
.code
Fact Proto Near C, N:dword ;; int Fact(int N) {
@@if: Cmp N , 0 ;; If (N <= 0)
Jle @@then ;; Fact = 1;
Jmp @@else ;; Else Fact = N * Fact(N-1);
@@then: Mov eAx, 1
Jmp @@endIf
@@else: Mov eCx, N ;; Fact( N-1 ) * N
Dec eCx
invoke Fact, eCx
Mul N ;; eAx = eAx * N
@@endIf:
Ret
Fact Endp
Main Proc near
invoke Fact, 3 ;; eAx = Fact( 3 );
Call PutDec ;; cout << eAx;
invoke ExitProcess, 0
Main Endp
End Main
|
;; ___________ ;; | 0003 | <- eBp+8 ;; |___________| ;; 1st |Return Addr| <- eBp+4 ;; Call|___________| ;; | eBp | <- eBp ;; |___________|_________ N=3 ;; | 0002 | <- eBp+8 ;; |___________| ;; 2nd |Return Addr| <- eBp+4 ;; Call|___________| ;; | eBp | <- eBp ;; |___________|_________ N=2 ;; | 0001 | <- eBp+8 ;; 3rd |___________| ;; Call|Return Addr| <- eBp+4 ;; |___________| ;; | eBp | <- eBp ;; |___________|__________N=1 ;; | 0000 | <- eBp+8 ;; 4th |___________| ;; Call|Return Addr| <- eBp+4 ;; |___________| ;; | eBp | <- eBp ;; |___________|__________N=0 |
#include <iostream.h>
int Power(int X, int N) {
if( N == 0 ) return 1;
else return Power( X, N-1) * X;
}
void main(void) {
cout << Power(5,2);
}
|
|
Title Power - Recursive function with two parameters, x^n
PutDec proto
.code
Power Proto Near C, X:dword, N:dword
;; int Power( int X, int N) {
@@if: Cmp N , 0 ;; if (N == 0)
Je @@then ;; return 1;
Jmp @@else ;; else return Power(X,N-1) * X
@@then: Mov eAx, 1
Jmp @@endIf
@@else: Mov eCx, N ;; Power( X,N-1 ) * X
Dec eCx
invoke Power, X, eCx
Mul X ;; eAx = eAx * X
@@endIf:
Ret
Power Endp
Main Proc near
invoke Power, 5, 2 ;; eAx = Power( 5, 2 );
Call PutDec ;; cout << Ax
invoke ExitProcess, 0
Main Endp
End Main
|
;; _____________________ ;; N | 2 | <- eBp+12 ;; |___________| ;; X | 5 | <- eBp+8 ;; |___________| ;; |Return Addr| <- eBp+4 ;; 1st |___________| ;; Call| eBp | <- eBp+0 X=5 ;; ___|___________|___________N=2 ;; N | 1 | <- eBp+12 ;; |___________| ;; X | 5 | <- eBp+8 ;; |___________| ;; |Return Addr| <- eBp+4 ;; 2nd |___________| ;; Call| eBp | <- eBp+0 X=5 ;; ___|___________|___________N=1 ;; N | 0 | <- eBp+12 ;; |___________| ;; X | 5 | <- eBp+8 ;; |___________| ;; |Return Addr| <- eBp+4 ;; 3rd |___________| ;; Call| eBp | <- eBp+0 X=5 ;; ___|___________|___________N=0 |
Write a function in C++ using Recursion to check if a number n is prime. (You have to check whether n is divisible by any number below n)
Write the same function in Assembler.
Fibonacci(1) = 1 Fibonacci(2) = 1 Fibonacci(n) = Fibonacci(n-1) + Fibonacci(n-2)There are two recursive calls with each producing a result. The result of the first call must be combined with the result of the second call using addition. For n=3:
Fibonacci(3) = Fibonacci(2) + Fibonacci(1) = 1 + 1The result of Fibonacci(2) must be temporarily saved, Fibonacci(1) computed, and the results of the two calls combined using addition. In Assembler:
invoke Fibonacci, 2 Push eAx ; Save Fibonacci(2) result invoke Fibonacci, 1 Pop eBx ; Restore Fibonacci(2) result Add eAx, eBx ; Combine Fibonacci(2) + Fibonacci(1) |
#include <iostream.h>
int Fib(int n) {
if (n == 1) return 1;
if (n == 2) return 1;
return Fib(n-1) + Fib(n-2);
}
void main(void) {
cout << Fib(5);
}
![]() |
Title Recursive Fibonacci
.386
.model flat, stdcall
PutDec proto
.code
Fib Proto Near C, N:dword ;; int Fib(int N)
@@if: Cmp N, 2
Jle @@then
Jmp @@else
@@then: Mov eAx, 1 ;; return 1
Jmp @@endif
@@else: Mov eCx, n ;; return Fib(n-1)+Fib(n-2)
Sub eCx,1
invoke Fib, eCx
Push eAx ;; save Fib(n-1)
Mov eCx, n
Sub eCx, 2
invoke Fib, eCx ;; Fib(n-2)
Pop eBx ;; recover Fib(n-1)
Add eAx, eBx
@@endif:
Ret
Fib Endp
Main Proc near
invoke Fib, 5
Call PutDec ;; cout << Fib ( 5 );
invoke ExitProcess, 0
Main Endp
End Main
|
Write a function in C++ using Recursion to compute binomial coefficients C(n, k) using the recursive definition:
C(n,n) = 1
C(n,0) = 1
C(n,k) = C(n-1, k-1) + C(n-1,k) for (0<k<n) and n>1
Write the same function in Assembler.
A(m,n) = n + 1 if m == 0Note functions return a result in the eAx register. The inner nested function result in eAx should be pushed onto the stack as a parameter to the outer nested function. For m=9 and n=7:
A(m,n) = A(m-1, 1) if m > 0 && n == 0
A(m,n) = A(m-1, A(m, n-1)) if m > 0 && n > 0
; A(9,7) = A(8,A(9,6)) invoke A, 9, 6 ;A(9,6) invoke A, 8, eAx ; A(8, A(9,6)) |
It is particularly interesting, for computational reasons, the depth of recursion due to the nested expression:
Ackermann( m-1, Ackermann(m, n-1))For example, the execution of Ackermann(3,2) produces recursion of depth 30.
#include <iostream.h>
int Ackermann(int m, int n) {
if(m==0) return n+1;
else if (m>0 && n==0) return Ackermann(m-1,1);
else if (m>0 && n>0) return Ackermann( m-1, Ackermann(m, n-1));
}
void main(void) {
cout << Ackermann(3,2);
}
|
Title Ackermann's function - Recursive function with multipule recursions
PutDec proto
.code
Ackermann Proto Near C, m:dword, n:dword
; int Ackermann(int m, int n) {
@@if1: Cmp m , 0 ; if (m == 0)
Je @@then1
Jmp @@else1
@@then1: Mov eAx, n ; Ackermann = n+1;
Inc eAx
Jmp @@endIf1
@@else1: ; else
@@if2: Cmp m, 0 ; if (m > 0 && n == 0)
Ja @@and2
Jmp @@else2
@@and2: Cmp n, 0
Je @@then2
Jmp @@else2
@@then2:
Mov eCx, m
Dec eCx
; Ackermann = Ackermann(m-1, 1);
invoke Ackermann, eCx, 1
Jmp @@endif2
@@else2: ; else
@@if3: Cmp m, 0 ; if (m > 0 && n > 0)
Ja @@and3 ; Ackermann =
Jmp @@endif3 ; Ackermann(m-1, Ackermann(m, n-1))
@@and3: Cmp n, 0 ; Endif
Ja @@then3 ; Endif
Jmp @@endif3 ; Endif
@@then3: Mov eCx, n
Dec Cx ; eAx = Ackermann(m, n-1)
invoke Ackermann, m, eCx
Mov eCx, m
Dec eCx
; eAx = Ackermann(m-1, eAx)
invoke Ackermann, eCx, eAx
@@endif3:
@@endif2:
@@endif1:
Ret ; Remove current m, n from stack
Ackermann Endp
Main Proc near
invoke Ackermann, 3, 2 ; eAx := Ackermann( 3, 2 );
Call PutDec ; cout << eAx
invoke ExitProcess, 0
Main Endp
End Main
|
Modify the C++ algorithm to determine the total number of calls.
Do the same for the Assembler algorithm.
Document last modified: