【问题标题】:How to return errno in Assembly?如何在汇编中返回 errno?
【发布时间】:2013-03-08 23:04:43
【问题描述】:

我在汇编中返回 errno 时遇到问题。我知道如何找到它,但我无法返回 errno 和返回值。如果我的函数失败,我将返回 errno(由系统调用设置)和 -1。 我必须为学校科目做这个。我必须在汇编中创建一个小库,最后一个函数是“写”。我用call system write,但我还要管理errno。

如果我没记错的话,errno 是一个全局变量。所以我想在汇编中恢复它,并改变它的值,但我还没有成功地在我的函数中恢复它......

我是正确的还是完全错误的?

我使用的是 Assembly Intel x86,并使用 NASM 进行编译。

抱歉语言错误,我不是英语。

【问题讨论】:

    标签: assembly x86 errno


    【解决方案1】:

    errno 并不总是全局变量。它只需要是一个左值,并且可能是一个隐藏函数调用的宏。来自the specification

    未指定 errno 是宏还是用外部链接声明的标识符。

    事实上,它通常不是一个全局变量,因为它通常被实现为线程局部的(因此需要一个函数调用来检索一个指向 TLS 块的指针)。

    最好有一个调用汇编函数并设置 errno 的 C 包装器。


    编辑:由于您不能使用 C 函数(这在 IMO 中毫无意义,因为 errno 是一个 C/POSIX 概念),您将不得不自己实现 errno。在errno.h 中找到errno 的定义,并实现汇编中的任何内容。例如,我的errno.herrno 定义为

    extern int * __error(void);
    #define errno (*__error())
    

    因此,我会调用__error 函数(它返回一个int *),然后存储到返回的地址。例如,这是我的系统生成的用于设置 errno 的程序集:

    $ gcc -xc - -o- -S <<EOF
    #include <errno.h>
    main() { errno = 3; return 0; }
    EOF
        .section    __TEXT,__text,regular,pure_instructions
        .globl  _main
        .align  4, 0x90
    _main:
    Leh_func_begin1:
        pushq   %rbp
    Ltmp0:
        movq    %rsp, %rbp
    Ltmp1:
        subq    $16, %rsp
    Ltmp2:
        callq   ___error
        movl    $3, (%rax)
            ...
    

    您的系统可能会有不同的errno 实现。

    【讨论】:

    • 感谢您的回答,我现在更了解 errno 的工作原理了。但我不能在 C 中使用包装器,因为它是一门学校科目,我只能使用汇编代码。我必须在汇编中做一个小库(~10 个函数),最后一个函数需要 errno。
    • Ekh,真的吗?您应该更新您的问题以反映这一点。我会更新答案。
    • 我已经更新了我的问题。我尝试应用您在明天的最后一次编辑中解释的内容。谢谢你:)
    • 另外,编译获取/设置errno 的函数并查看它生成的程序集(例如使用gcc -S)。
    • @tc.:是的,这是个好主意。我添加了我的 errno 的程序集作为示例。
    【解决方案2】:

    如果您只是在汇编中编写代码,那您为什么需要errnoerrno 是 C 库函数使用的 C 语言概念,这些函数进行系统调用以将这些系统调用的错误返回传达回 C 代码。如果你真的需要它,最简单的方法是按照 nneonneo 的描述编写一个 C 函数,获取 errno 的地址并从你的汇编代码中调用它。

    但如果您正在编写汇编代码,则不需要它。系统调用自己在正常返回位置(x86 上的 eax)返回错误代码,并通过一种方式将其与非错误返回区分开来。在 Linux 中,错误总是在 -4095..-1 范围内。该范围内的任何返回值都是错误,超出该范围的任何返回值都是非错误返回。在其他 UNIX 风格(例如 *BSD)中,错误会设置 CARRY 标志。

    【讨论】:

    • 我需要 errno,因为这些函数(用纯汇编代码编写,是的)将被 C 中的函数调用。大多数时候,我会在 C 中使用这个库,而不是在汇编代码中。跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多