1

I write assembly for a school project and I'm stuck on a point, i need re rewrite Read in asm, so i got it, but i need to set the errno variable, then my read can return -1 in case of an error and set value of errno to 9 for example. And i don't found how to change this famous errno :( this is my actual code :

global my_write

section .text
my_write:
    mov rax, 1  ; sys_write
    syscall     ; call write
    cmp rax, 0
    jl error
    ret
error:
    mov rax, -1
    ret

ps : i found somewhere i need to use __error but i don't find any docs on this :(

thanks a lot :D

edit :

Thanks for you help guys ! __errno_location work i make this :

extern __ernno_location
global my_write

section .text
my_write:
    mov rax, 1  ; sys_write
    syscall     ; call write
    cmp rax, 0
    jl error
    ret
error:
    neg rax    ; get absolute value of syscall return
    mov rdi, rax
    call __ernno_location
    mov [rax], rdi  ; set the value of errno
    mov rax, -1
    ret
Maxime Crespo
  • 199
  • 1
  • 10
  • What operating system are you programming for? – fuz May 27 '20 at 14:57
  • Do it in C and see what code it generates. [Here](https://godbolt.org/z/YTLrtR), for example, there's a function called `__errno_location`, that returns a pointer in `rax` which you can dereference to store into. – Erik Eidt May 27 '20 at 14:58
  • i can't do code in C i'm forced to do all in asm and i'm porgramming for linux (xubuntu) – Maxime Crespo May 27 '20 at 15:04
  • Post answers as answers, not as edits to the question. Also, are you sure `__ernno_location` doesn't clobber RDI? It's call-preserved in the normal calling convention so it's not safe/future-proof unless that function has extra guarantees. You may need to `push rax` / `pop [rax]` around that `call`. – Peter Cordes May 28 '20 at 09:50
  • Your code is wrong, because `rdi` is a caller saved register just like `rax`. There is no guarantee that `__errno_location` does not change it. Push it on the stack instead. Also, `errno` is a 32 bit integer, do not write 64 bits into it. – Jester May 28 '20 at 10:08

1 Answers1

6

That's tricky business. You need to look up the definition of errno in your system. It may be going through a helper function like

/* Function to get address of global `errno' variable.  */
extern int *__errno_location (void) __THROW __attribute__ ((__const__));
/* When using threads, errno is a per-thread value.  */
#   define errno (*__errno_location ())

So you can call that function from your assembly and then set the value through the returned pointer. More portable way would be to write a helper function in C, say:

#include <errno.h>
void set_errno(int value)
{
    errno = value;
}

which would take care of the platform dependent stuff.

Jester
  • 56,577
  • 4
  • 81
  • 125
  • Hmm is see but the problem is i'm forced to do all code in asm i can't use C :(, i code on ubuntu – Maxime Crespo May 27 '20 at 15:04
  • 1
    You can still call the `__errno_location` function from asm. – Jester May 27 '20 at 15:05
  • 2
    @MaximeCrespo Compile the C code to assembly (use the `-S` option to get assembly code) and then do the same thing the C compiler does. – fuz May 27 '20 at 15:21