// 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 //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