First, through the disassembly language, let's take a look at the relationship between the simplest recursive function and the stack.
In visual studio 2008 and debug environments, you can view the language after disassembly in debug/windows/disassembly. Now let's take a look at factorial n! Implementation
The C language implementation code is as follows:
# Include <stdio. h>
Int factorial (int n );
Int main (void)
{
Int fact;
Fact = factorial (4 );
Printf ("% d \ n", fact );
Return 0;
}
Int factorial (int n)
{
If (1 = n)
Return 1;
Return n * factorial (n-1 );
}
The language after disassembly is as follows:
Main Program
Int main (void)
{
00DB1FD0 push ebp
00DB1FD1 mov ebp, esp
00DB1FD3 sub esp, 0CCh
00DB1FD9 push ebx
00DB1FDA push esi
00DB1FDB push edi
00DB1FDC lea edi, [ebp-0CCh]
00DB1FE2 mov ecx, 33 h
00DB1FE7 mov eax, 0 CCCCCCCCh
00DB1FEC rep stos dword ptr es: [edi]
Int fact;
Fact = factorial (4 );
00DB1FEE push 4
00DB1FF0 call @ ILT + 475 (_ factorial) (0DB11E0h)
00DB1FF5 add esp, 4
00DB1FF8 mov dword ptr [fact], eax
Printf ("% d \ n", fact );
00DB1FFB mov esi, esp
00DB1FFD mov eax, dword ptr [fact]
00DB2000 push eax
00DB2001 push offset string "% d \ n" (0DB5A38h)
00DB2006 call dword ptr [_ imp _ printf (0DB82BCh)]
00DB200C add esp, 8
00DB200F cmp esi, esp
00DB2011 call @ ILT + 320 (_ RTC_CheckEsp) (0DB1145h)
Return 0;
The factorial function is compiled as follows:
Int factorial (int n)
{
00DB1AF0 push ebp
00DB1AF1 mov ebp, esp
00DB1AF3 sub esp, 0C0h
00DB1AF9 push ebx
00DB1AFA push esi
00DB1AFB push edi
00DB1AFC lea edi, [ebp-0C0h]
00DB1B02 mov ecx, 30 h
00DB1B07 mov eax, 0 CCCCCCCCh
00DB1B0C rep stos dword ptr es: [edi]
If (1 = n)
00DB1B0E cmp dword ptr [n], 1
00DB1B12 jne factorial + 2Bh (0DB1B1Bh)
Return 1;
00DB1B14 mov eax, 1
00DB1B19 jmp factorial + 3Eh (0DB1B2Eh)
Return n * factorial (n-1 );
00DB1B1B mov eax, dword ptr [n]
00DB1B1E sub eax, 1
00DB1B21 push eax
00DB1B22 call @ ILT + 475 (_ factorial) (0DB11E0h)
00DB1B27 add esp, 4
00DB1B2A imul eax, dword ptr [n]
}
00DB1B2E pop edi
00DB1B2F pop esi
00DB1B30 pop ebx
00DB1B31 add esp, 0C0h
00DB1B37 cmp ebp, esp
00DB1B39 call @ ILT + 320 (_ RTC_CheckEsp) (0DB1145h)
00DB1B3E mov esp, ebp
00DB1B40 pop ebp
00DB1B41 ret
In the whole assembler
Call @ ILT + 475 (_ factorial) (0DB11E0h)
The previous push is the input stack of the parameter. Here is the key. We can consider other push operations necessary for the system to balance the stack.
In the disassembly of factorial,
00DB1B39 call @ ILT + 320 (_ RTC_CheckEsp) (0DB1145h)
In this case, the function factorial calls itself, that is, recursion.
Push eax; Save the parameters of each incoming stack to the eax register, and then re-enter the stack. In this way, n! = 1, each parameter is included in the stack;
00DB1B2A imul eax, dword ptr [n]
This step is used for multiplication. Store the multiplied value in the eax register.
In fact, in the whole process, involves a series of operations in the function call stack frame, http://www.bkjia.com/kf/201111/110912.html this blog tells in detail a series of operations in the Process of calling the function stack frame.
Make a summary:
Function recursion uses the stack operation in the system to implement recursion by performing a series of operations on Stack frames. This process is completed by the system.
In the factorial, we add the factorial function parameters to the stack, and then use a series of operations on the stack frame to implement the parameter output stack, and then complete the factorial action. The entire process is actually a stack's inbound and outbound problems.
Now we need to define a stack to implement function recursion.
# Include "stack. h"
# Define NumOfStack 10
Int main (void)
{
StackNode * pStackNode = NULL;
Int NOfFact;
Int tmp = 1, Sum = 1;
PStackNode = CreateStack (NumOfStack );
Printf ("the number of Factorial \ n ");
Scanf ("% d", & NOfFact );
While (NOfFact)
{
Push (pStackNode, NOfFact --);
}
While (pStackNode-> top)
{
Pop (pStackNode, & tmp );
Sum * = tmp;
}
Printf ("sum is % d \ n", Sum );
Return 0;
}
Only the main program section is displayed. In the main program, we first stack the parameter, that is, n, n-1,... 1, and then operate on the stack.
In this article, I want to tell you how to view the running process and steps of factorial recursion in disassembly language, it can deepen our understanding of function recursion and stack. Although the Assembly Language is difficult to understand, I believe everyone can understand it by reading the blog recommended above.
From yankai0219