[toc]

# 追踪调用栈原理

1
2
3
4
5
6
7
8
9
void main() {
int m= 3, n= 4, s= 0;
s= f( m, n);
}

int f( int a, int b) {
int c= 2;
return a+ b+ c;
}

上述代码从 f() 函数开始可以用如下汇编描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
push n
push m
call f
push bp
mov bp sp
//保护寄存器,因为算a+b+c的时候要用到这些寄存器
//并且不能把之前的寄存器的值丢了,所以要先保存起来,等函数结束后,再把当前值还原回去
push bx,cx,dx
mov bx [bp+8]
mov cx [bp+12]
mov dx,2
add dx,bx
add dx,cx
//编译器约定俗成地以ax作为返回值。其实如果dx在函数外面没有用到,
//下面一句完全可以不写,然后直接取出dx的值
mov ax,dx
//弹出一系列寄存器值,还原寄存器中的值
pop dx,cx,bx
pop bp
ret 8

在 C/C++ 中参数从右向左压入参数,每一次压栈 sp 就会增加 栈顶指针 一个小 Tip 由于计算机的寄存器数量有限,所以如果寄存器内有值的话,先把值保存下来,下次出栈后再把原来的值放回去 bp 一般用作栈基指针 (存调用函数的开始地址),bp+4 是进入函数时的地址 bp+8 指向 m 参数的地址 所以我们可以通过取到 bp 的地址,根据 bp 的调用顺序就可以追踪到调用栈

更新于

请我喝[茶]~( ̄▽ ̄)~*

Solvarg 微信支付

微信支付

Solvarg 支付宝

支付宝

Solvarg 贝宝

贝宝