c - 在调用者的返回序列中跳过函数

标签 c function assembly x86

在一系列函数调用中,例如

                main() --> A() --> B()-->C();

当一个被调用的函数完成时,它通常会返回到调用函数,例如C()返回B()B()返回A()

我想知道是否也可以直接返回调用序列中较早的函数 所以 C() 返回到 main() 并跳过 B()A()

如果可以的话我该怎么做?你能解释一下它是如何工作的以及它何时在现实中使用吗?

这是我的代码

#include <stdio.h>
int A(void);
int B(void);
void main(void )
{
    A();
}

int A()
{ 
    printf("enter A()\n");
    B();
    printf("exit A()\n");
}

int B()
{
    printf("enter B()\n");
    printf("exit B()\n");
}

并且我想跳过从 B() 返回函数 A() 以便 printf("exit A()\n"); 不会执行并给我这个结果:

enter A()                                                                                                                  
enter B()                                                                                                                  
exit B() 

最佳答案

在检查所有内容之前,@PeterCordes 以多种方式回答了问题

好的,让我们开始吧:

这种类型的东西可以使用称为long jump的东西来完成,所以你的代码在编辑后看起来像这样:

#include <stdio.h>
#include <setjmp.h>//c standard library header
jmp_buf env; // for saving longjmp environment
main()
{
    int r, a=100;
    printf("call setjmp to save environment\n");
    if ((r=setjmp(env)) == 0){
        A();
        printf("normal return\n");
    }
    else
        printf("back to main() via long jump, r=%d a=%d\n", r, a);
}
int A()
{ 
    printf("enter A()\n");
    B();
    printf("exit A()\n");
}
int B()
{
    printf("enter B()\n");
    printf("long jump? (y|n) ");
    if (getchar()=='y')
    longjmp(env, 1234);
    printf("exit B()\n");
}

让我们了解一下刚刚发生了什么

在上面的程序中,setjmp()将当前执行环境保存在一个jmp_buf中 结构,返回 0

程序继续调用 A(),后者调用 B()

同时 在函数B()中,如果用户选择不通过long jump返回,函数将 显示正常的返回序列。

如果用户选择通过longjmp(env,1234)返回, 执行将返回到上次保存的具有非零值的环境。

在 在这种情况下,它会导致 B() 绕过 A() 直接返回到 main()

原则 跳远非常简单。当一个函数完成时,它返回

(caller_EIP, caller_EBP) 在当前堆栈框架中, 如果我们将 (caller_EIP, caller_EBP) 替换为

(saved_EIP, saved_EBP) 较早的函数 在调用序列中,执行将直接返回到该函数。

此外 到(saved_EIP, saved_EBP)setjmp()也可以保存CPU的通用寄存器和 原始的ESP,让longjmp()可以还原返回的完整环境 功能。

长跳转可用于中止调用序列中的函数,导致 从先前保存的已知环境恢复执行。

虽然很少用 在用户模式程序中,它是系统编程中的常用技术。

例如, 它可以用在信号捕捉器中以绕过导致的用户模式功能 异常或陷阱错误。

可以查看this也不错

关于c - 在调用者的返回序列中跳过函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51914598/

相关文章:

c - celltemp结合数据

c - 类似于 C++ 泛型的 C 函数

c - pthread条件变量只能使用一次吗?

c - ESP8266 硬件定时器,uS to ticks 奇怪的宏

c - 与 glibc 有何关系?

swift - 有没有办法将 NSToolbarButton 与 MainViewController 连接起来?

c - 正在读取文件,但未保存

arrays - 在汇编程序中初始化数组

assembly - 气体 : too many memory reference

c++ - 为什么在Visual Studio x64(MASM)上将gs段寄存器的地址设置为0x0000000000000000?