【问题标题】:Jump to line of code in C using pointers (not goto)?使用指针(不是 goto)跳转到 C 中的代码行?
【发布时间】:2021-03-10 12:32:36
【问题描述】:

我知道这是一个奇怪的问题,但有没有办法使用指针返回代码中的某个点?我想做的是模仿 MIPS 中 jal 指令的行为。

例如,如果我有一个返回 1 的函数 fun1(),另一个返回 2 的函数 fun2(),以及此处定义的 main()

1  main() {
2   int v = fun1(); // v = 1
3   if (v == 2) return 2;
4   v = fun2(); // v = 2
5  }

在第 4 行调用 fun2() 后,我是否可以通过在第 2 行保留指向 fun1 调用返回地址的指针来跳回第 3 行?

【问题讨论】:

  • 使用 setjmp/longjmp
  • 您可能对setjmp()longjmp() 感兴趣,但用例看起来有点矫枉过正。
  • 这可能是 XY 问题。可能你想要一个循环。
  • 使用 GNU C 扩展来获取 goto 标签 (gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html) 的地址,是的,您可以使用 C 变量作为“链接寄存器”来模拟类似 jal 的函数调用.但是不,您不能侵入编译器发出的 asm 并捕获返回地址。 IIRC,标准 MIPS 调用约定不要求函数通过将返回地址恢复到 LR 来返回。理论上,他们可以在将返回地址复制到该寄存器而不是$lr 后返回jr $t9 或其他任何内容。调用者不能假设任何关于 LR 的返回

标签: c pointers assembly mips


【解决方案1】:

使用 GNU C 扩展来获取 goto 标签 (https://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html) 的地址,是的,您可以使用 C 变量作为“链接寄存器”模拟 jal 类函数调用,如 asm $ra .但这与编译器发出的 asm 是分开的——您必须使用 goto 进行“函数调用”才能完全按照您的描述进行。

不,您不能侵入编译器发出的 asm 并捕获返回地址。即使使用 GNU C 内联汇编,您也不能安全地做到这一点。

另外,IIRC,标准 MIPS 调用约定不要求函数通过将返回地址恢复到 RA 来返回。理论上,他们可以在将返回地址复制到该寄存器而不是$ra 后返回jr $t9 或其他任何内容。从jal 返回时,调用者不能假设任何关于 RA 的信息。但在实践中,RA 持有 JAL 放在那里的值。我想不出编译器会做一些不同的事情的任何原因。除了可能 C++ 异常展开?但这将以catch 结尾,而不是正常的返回路径。

当然,如果你在 asm 中编写调用者,你可以根据需要利用 $ra,尽管通常它不会比在底部的普通相对分支 bne $v0, $s0 指令更有效包含 jal fun2 的 while 循环继续调用,直到获得不同的返回值。

【讨论】:

    猜你喜欢
    • 2013-07-04
    • 2013-11-07
    • 2015-04-08
    • 1970-01-01
    • 2016-05-16
    • 1970-01-01
    • 1970-01-01
    • 2021-07-01
    • 2023-02-03
    相关资源
    最近更新 更多