Reputation: 51
I have a problem to return errno in assembly. I know how to find it, but I can't return errno and a return value. If my function fails, I would return errno (sets by a system call) and -1. I have to do this for a school subject. I have to create a little library in assembly, and the last function is "write". I use the call system write, but I have also to manage errno.
If I'm not mistaken, errno is a global variable. So I think to recover it in assembly, and change its value, but I did not suceeds to recover it in my function yet...
Am I in the good way or totally wrong ?
I used Assembly Intel x86 and I compile with NASM.
Sorry for the language mistake, I'm not english.
Upvotes: 2
Views: 6289
Reputation: 179552
errno
is not always a global variable. It is only required to be an lvalue, and may be a macro hiding a function call. From the specification:
It is unspecified whether errno is a macro or an identifier declared with external linkage.
In fact, it is usually not a global variable since it is usually implemented to be thread-local (and so requires a function call to retrieve a pointer to the TLS block).
You are better off having a C wrapper that calls the assembly function and sets errno
.
EDIT: Since you can't use a C function (which, IMO, is senseless, since errno
is firmly a C/POSIX concept), you will have to implement the errno
gathering yourself. Find the definition of errno
in errno.h
, and implement whatever is there in assembly. For example, my errno.h
defines errno
as
extern int * __error(void);
#define errno (*__error())
Therefore, I would make a call to the __error
function (which returns an int *
), then store to the returned address. For example, here's the assembly my system produces for setting 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)
...
Your system will probably have a different implementation of errno
.
Upvotes: 7
Reputation: 126408
If you're writing solely in assembly, why do you need errno
at all? errno
is a C language concept used by the C library functions that make system calls to communicate error returns from those system calls back to C code. If you really need it, the easiest way is to do as nneonneo describe and write a C function that gets the address of errno
and call it from your assembly code.
But if you're writing pure assembly code, you don't need it. System calls themselves return error codes in the normal return location (eax on x86) with a way of distinguishing it from a non-error return. In Linux, errors are always in the range -4095..-1. Any return value in that range is an error and anything outside of that is a non-error return. In other UNIX flavors (*BSD for example), errors set the CARRY flag.
Upvotes: 2