// This program illustrates the use of inline assembly from within C++.
// N - factorial is calculated using a "stack frame" to pass the parameters
// and recursion to find the number.
//
// Written by Joe Toone March 11, 2005
// Modified to work with Visual Studio.Net 2005 November 6, 2007
#include <iostream> //changed iostream.h to iostream to meet VS .Net requirement
using namespace std; //needed for VS 2005 .Net
int factorial(int n);
void main()
{
int number,nfact;
while(1) {
cout << endl << "Enter the number to find the factorial of (0 to exit) -> ";
cin >> number;
if (number<=0)
break;
nfact=factorial(number);
cout << "n factorial of " << number <<" is " << nfact << endl;
};
}; //end of main
/* This function is presented for informational purposes only
however, you could uncomment this function and comment out the
assembly version of the function and it would work.
// A typical C++ function to calculate the factorial of n
// Notice that recursion is used to find the factorial
int factorial(int n)
{
if(n==1) return(1);
else n = factorial(n-1) * n;
};
*/
// The following function uses inline assembly code to calculate the factorial
// of n. Notice that it has a standard C++ function header. Inside the C++
// function, you should notice the "__asm" statement which signals that the
// following statements are normal x86 assembly instructions.
// N - factorial is calculated by recursive calls to the assemble procedure
// "factor". The answer is left in the EAX register and is returned to the
// calling C++ function from that location.
// It should also be noted that each recursive call produces a new "stack frame"
// on which the parameters are passed. It is critical that the "stack" be
// managed properly, since it is the same stack that the C++ program is using
// to pass it's parameters.
// More information on using inline assembly may be found in the MSDN library.
int factorial(int n) //Normal C++ function header with parameter
{
__asm { ;C/C++ reserved word or inline assembly
mov ecx,n ;copy C++ parameter to ECX register
push ecx ;push parameter onto the stack
call factor ;call the local factorial procedure
jmp outtahere ;we have an answer, so jump to exit
factor: ;We are forced to use the simplest form of
;an assembly procedure since inline code does
;not support the PROC assembler directive.
push ebp ;Establish the "stack frame"
mov ebp,esp ;
push ecx ;place a copy of "n" on the stack
;if n = 1 ;if "n" is not equal to 1
cmp dword ptr [ebp+8],1 ; "n" is located on the stack
jne else01 ; jump to the else condition
mov eax,1 ; otherwise n==1, so set EAX to 1
jmp endif01 ; and exit the if
else01: ;
mov ecx,dword ptr [ebp+8] ;else retrieve n from stack
dec ecx ; decrement n
push ecx ; place n back on the stack
call factor ; and call factor again
add esp, 4 ;reduce the stack pointer by one dword
mul dword ptr [ebp+8] ;multiply EAX by n
push ecx ;place n parameter back on the stack
endif01: ;end of if statement
pop ecx ;remove left over paramter from the stack
pop ebp ;restore the original base pointer
ret 4 ;discard the original value of n
outtahere: ;the answer is in EAX register
mov n,eax ; so copy it to the C++ parameter
}; //end of inline assembly code
return n; //return the answer to C++ caller
}; //end of factorial