setjmp的工作原理
01 December 2020
setjmp的工作原理
执行环境 简单说就是CPU中的一些寄存器,这些寄存器保存了程序执行的必要信息,以x86为例:
- esp 保存当前栈顶的地址。
- ebp 保存当前函数栈帧的地址,在函数的进入点处,把esp保存到ebp,这样在函数任何位置,都可以通过ebp加偏移拿到函数的参数。
- eip 保存下一条指令的地址。
函数调用约定 函数的调用约定,对寄存器也有影响,以x86的cdecl(这是C语言函数的调用约定)为例:
- 函数参数通过栈传递,顺序从右到左,并且由调用者负责清理栈中的参数。
- 整型值和内存地址通过eax返回。
- eax, ecx, edx由调用者负责保存,其余的由被调函数负责保存。
汇编中的call指令 call指令由两条语句组成:
- 把下一条指令的地址压栈,然后跳到函数的入口地址;
- 函数调用完之后,从栈中把指令地址恢复,这样就能正常的返回到函数调用的下一条指令处。
setjmp/longjmp 下面实现从一个函数体内向另一个事先登记过的函数体内跳转,setjmp/longjmp的作用是保存执行环境。
- 使用setjmp保存当前执行环境到jmp_buf,然后默认返回0。
- 程序继续执行,到某个地方调用longjmp,传入上面保存的jmp_buf,以及另一个值。
- 此时执行点又回到调用setjmp的返回处,且返回值变成longjmp设置的值。
#include <stdio.h>
#include <setjmp.h>
jmp_buf j_buf;
void f(){
longjmp(j_buf, 1);
}
int main(){
if(setjmp(j_buf)){
printf("World!");
}else {
printf("Hello ");
f();
}
}
输出: Hello World!