请稍侯

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!