系统栈和栈
自己实现个栈很简单,但是用栈的思想在有时候比较抽象,尤其是在使用系统栈的时候(递归)。栈的主要特点就像是你放很多大木板子在你的收纳盒里,模板放入后,每次只能取走最后放入的模板,是“先入后出”,或者“后入先出”。
稍微谈一下递归:本质上来讲能用数学归纳法证明的数学问题都可以用递归解决,用栈能解决的问题也都能递归解决(废话都是栈)。递归的核心思想在于:在这一阶段,只考虑目前这一小阶段的情况,以及和前/后阶段的联系,随后考虑一个最基础的跳出条件。感觉放这里不太合适,还是以后专门说一说递归吧。
系统栈如何保存函数调用信息
所谓系统栈,其实也是和栈比较类似的一种东西,可以用ollydbg或者x32/x64dbg去看一个简单的C语言程序是怎么被压栈的。或者也可以使用VS2019ALT 8反汇编查看
大概情况如下:
比如有一个C语言程序求阶乘,
那么汇编大概就是:
.586
.model flat,stdcall
.stack 4096
includelib libcmt.lib
includelib legacy_stdio_definitions.lib ;stdio.h
includelib libvcruntime.lib
includelib libucrt.lib
extern printf:NEAR
extern scanf:NEAR
ExitProcess PROTO, dwExitCode:DWORD
.data
msg BYTE "%d! = %d", 0Ah, 0
result BYTE "The result is %d", 0Ah, 0
printfact BYTE "%d! = %d",0Ah,0
prompt BYTE "Enter an integer: ",0Ah,0
num dd 0
scan BYTE "%d",0
.code
fact:
push ebp
mov ebp, esp
mov ecx, [ebp+8] ; ecx = n
;mov eax, 1 ; accumulator eax = ecx*fact(ecx-1)
cmp ecx, 1
jle base
push ecx
sub ecx, 1
push ecx
call fact
add esp, 4
pop ecx
mul ecx ;eax = ecx*fact(ecx-1)
push eax
push ecx
push eax
push ecx
push offset msg
call printf
add esp,12
pop ecx
pop eax
pop ebp
ret
base: ; return 1
mov eax, 1
pop e