2012-07-01 85 views
6

我正在浏览各种setjmplongjmp实现的源代码,并注意到并非所有CPU寄存器都保存在jmp_buf结构中。在回顾AMD64 ABI后,我注意到只有被保存的寄存器被保存。为什么setjmp(3)不保存AMD64上的所有寄存器?

我不明白当只有一些寄存器被保存时如何完全恢复功能状态。肯定的是,未保存的寄存器必须一遍又一遍地被破坏,直到我稍后致电longjmp

然而,一切都很完美,所以肯定有一些我不明白的东西。我希望有人能够对此有所了解。

谢谢!

+0

有一些setjmp实现只保存指令指针/帧指针(参见'libunwind')。那些setjmp速度非常快,但longjmp时间相对较慢,并基于描述如何从呼叫者保存位置等恢复其他寄存器的帧表。 –

+0

我在哪里可以找到您正在查看的来源? – nullpotent

+0

@AljoshaBre这些是迄今为止我发现的最具可读性:[setjmp](http://git.etalabs.net/cgi-bin/gitweb.cgi?p=musl;a=blob;f=src/setjmp /x86_64/setjmp.s;h=98f58b8d6551e391f426fc53c81678a03ac89074;hb=HEAD)和[longjmp](http://git.etalabs.net/cgi-bin/gitweb.cgi?p=musl;a=blob;f=src/的setjmp/x86_64的/ longjmp.s; H = e175a4b9606bba41eccc8972c22244e533718f0a; HB = HEAD)。 – haste

回答

4

setjmp函数是一个像其他函数一样的函数,因此可以假定为打开任何调用者保存的寄存器。因此,它不需要保存/恢复这些寄存器。

+0

是不是编译器可以自由使用任何可用的寄存器,因为它在我的函数,即我喜欢。即即使是没有被'setjmp'保存的寄存器? – haste

+0

并非完全 - 它不能在函数调用中使用调用者保存的寄存器,因为它们可以/将被更改。例如,考虑'eax'(在x86上):被调用者将向该寄存器写入一个返回值,因此调用者不能在函数调用中存储任何重要的内容。 – duskwuff

+1

@haste我也为此失败了。以更详细的方式来描述它:因为它们是保存的调用者,并且setjmp被认为是一个普通函数,所以setjmp的调用者已经保存了这些寄存器(如果需要的话),所以当setjmp第二次返回给调用者时(通过longjmp) ,调用者将在之前存储各个呼叫者保存的寄存器并且能够恢复它们。 –

相关问题