• 白凤凰
    2022-01-10
    setjmp和longjmp的应用场景是什么呢?实际开发过程中什么时候可以用这两个函数,是为了解决什么问题呢?

    作者回复: 除了我们在文章中提到的可以用来实现 try...catch,协程以外,也可以用在信号处理程序中。比如参考这边的例子:https://www.gnu.org/software/libc/manual/html_node/Longjmp-in-Handler.html。除此之外,我好像没有再见到过其他用例。其他同学如果有另外的使用场景也可以补充哈。

    共 2 条评论
    3
  • liu_liu
    2022-01-07
    对 setjmp 和 longjmp 的理解: setjmp 将寄存器的值保存到全局变量中,同时保存 rsp 和返回地址的值,设置 eax = 0。 在上面的例子中,返回地址就是 cmp eax, 73 这句指令的地址。 longjmp 的作用: 1. 将保存的值从全局变量中全部恢复,其中最重要的是返回地址和 rsp。因为之后的 jmp 指令会跳转到返回地址去继续执行,也就是重新回到 cmp eax, 73。 2. 根据第二个参数更新 eax 的值。 那么当回到返回地址继续执行时,数据也都准备好,这样就达到了目的。 ------------------------- 另外有个问题,对于 rsp 的保存,不知理解的对不对? lea rdx, [rsp+0x8] mov QWORD PTR [rdi+0x30], rdx 在 call _setjmp 时,会将返回地址压栈,此时 rsp -= 8。所以需要加上 8 得到之前的 rsp,也就是 rdx = rsp + 8。

    作者回复: 没错的哈。

    
    2
  • 红军
    2022-09-16 来自上海
    请问一下setjump和longjump为什么要保存&恢复ebx呢?其他的ecx、edx等寄存器为啥可以不用保存&恢复呢

    作者回复: 因为 rbx 属于 callee-saved 寄存器,需要由被调用方保存状态,并在结束前重置。

    
    
  • TableBear
    2022-08-05 来自广东
    很好奇老师截图里面的工具是什么开发工具?有小伙伴知道吗?

    作者回复: 是这个:https://godbolt.org/

    
    
  • shk1230
    2022-02-26
    那么if (setimp(jb) < 'J' ),不就是恒等式?setjmp(jb)返回0时

    作者回复: setjmp 初次调用会返回 0,而后续 longjmp 在每次返回到 setjmp 时都会携带更新后的值。

    共 2 条评论
    
  • ZR2021
    2022-01-10
    对了,还有个感觉比较怪异的点,就是setjmp 函数的参数是直接传递的值,而非指针,然后setjmp 函数里还真修改了传入的值到jb 变量中! 按照我之前的理解,值传递的时候调用函数先将变量传给rdi 寄存器,然后被调函数里将rdi 里的内容拷贝至本函数的传参变量所在的栈,再使用这个变量的值。 但是setjmp函数貌似没有新开辟传参变量的栈,而是直接找到调用函数传参的地址,然后对其进行修改,这样,调用函数里的变量就得到了修改,不知道我理解的对不对。还有,这种通过值传递的而不是指针,但最后将传入的变量内容修改的形式,哪些地方用到的比较多呢?

    作者回复: setjmp 调用时传递的 jb 是一个指针哈。jb 对应的类型 jmp_buf 是这样定义的:typedef long jmp_buf[8];

    共 2 条评论
    
  • ZR2021
    2022-01-09
    老师,可变参数里面va_start初始化ap的时候,那个count参数需不需要的?理论上也被存到RSA里面了吧,看起来好像有点多余,但是看到很多可变参数都会用到这个参数,很是奇怪

    作者回复: va_start 在调用时的第二个参数,需要传入函数参数列表中显式定义的最后一个带名字的参数,这个是必须要传的。

    共 2 条评论
    
  • Ping
    2022-01-09
    老师,yield函数是不是用这里的setjmp和longjmp实现的?

    作者回复: setjmp 和 longjmp 是在 C 语言中实现协程这种语言特性的一种方式,但其他语言比如 Python、JavaScript 中的 yield 关键字是怎样实现的,这个就要具体情况具体分析了。当然,在 C 中也可以实现 yield,比如参考这个 Post:https://stackoverflow.com/questions/17478264/implementing-yield-in-c

    
    
  • liu_liu
    2022-01-07
    https://gist.github.com/silan-liu/47cf4d65e5f49b84c7f499a7d4fd24f2 尝试写了一个版本,不知思路对不对?

    作者回复: 思路是对的,不过可以用宏封装一下,让使用方式更自然一些。可以参考这篇文章:http://groups.di.unipi.it/~nids/docs/longjump_try_trow_catch.html

    
    
  • liu_liu
    2022-01-07
    cmp esi, 0x1 adc eax, esi 如果 longjmp 传入的第二个参数为 0,那么此时 esi = 0。 cmp 之后的结果,会让进位 CF = 1。 adc 表示进位加和,eax = eax + esi + CF = 1。 这样就达到了令 eax = 1。
    
    4