@
PTLin 答案是各级函数调用的所有寄存器值切片都被保存并恢复了。具体展开来说,有通用寄存器的指令集架构一般会在调用约定中将寄存器分为 Caller-saved 和 Callee-saved 两类,在多级函数调用中每一级函数都可能会修改寄存器的值形成新的上下文状态。在函数中对于 Caller-saved 寄存器可以直接修改,因为 Caller 需要的寄存器旧值它自己保存了,而 Callee-saved 必须在修改前将旧值存入栈中。因此整个调用链绝大部分帧的寄存器值都已保存在栈中,只有最末级的 Callee 存在还未入栈的寄存器值。如果此时以这级作为 Caller 再调用 setjmp ,我们来考虑一下 setjmp 应该怎么实现,会发现它根本不需要保存 Caller-saved 寄存器,只需要保存 Callee-saved 寄存器以及一些并不属于以上分类且有可能被改变且影响上下文的寄存器,比如 sp 、pc 、各种 flags 等等。而后续 longjmp 回来恢复这个调用链的上下文时,也只需要再恢复 setjmp 中保存的那部分寄存器值,这样随着这个调用链再逐级弹出,所有寄存器值的完整切片均能被恢复出来。