Quantcast
Channel: Active questions tagged kernel - Stack Overflow
Viewing all articles
Browse latest Browse all 6334

What is the relation between (carry flag) and syscall in assembly (x64 Intel syntax on Mac Os)?

$
0
0

I am new to the assembly language, and I have to make an implementation of read function using assembly language x64 in MAC.so far this is what I did :

;;;;;;ft_read.s;;;;;;global _ft_read:section .textextern ___error_ft_read:    mov rax, 0x2000003 ; store syscall value of read on rax     syscall            ; call read and pass to it rdi , rsi, rdx  ==> rax read(rdi, rsi, rdx)    cmp rax, 103       ; compare rax with 103 by subtracting 103 from rax ==> rax - 103    jl _ft_read_error  ; if the result of cmp is less than 0 then jump to _ft_read_error    ret                ; else return the rax value which is btw the return value of syscall_ft_read_error:    push rax    call ___error    pop rcx    mov [rax], rcx    mov rax, -1    ret

as you can see above, I call read with syscall, and then I compare the returned value of read syscall that stored in rax with 103, I will explain why I compare it with 103 but before that, let me explain something else, which is errno (man page of mac), this is what is written in the manual page about errno:

When a system call detects an error, it returns an integer value indicat-ing indicatinging failure (usually -1) and sets the variable errno accordingly. <Thisallows interpretation of the failure on receiving a -1 and to take actionaccordingly.> Successful calls never set errno; once set, it remainsuntil another error occurs. It should only be examined after an error.Note that a number of system calls overload the meanings of these errornumbers, and that the meanings must be interpreted according to the typeand circumstances of the call.

The following is a complete list of the errors and their names as givenin <sys/errno.h>.

0 Error 0. Not used.

1 EPERM Operation not permitted. An attempt was made to perform an operation limited to processes with appropriate privileges or to theowner of a file or other resources.

2 ENOENT No such file or directory. A component of a specified pathname did not exist, or the pathname was an empty string.

..................................................I'll skip this part (I wrote this line btw)..................................................

101 ETIME STREAM ioctl() timeout. This error is reserved for future use.

102 EOPNOTSUPP Operation not supported on socket. The attempted operation is not supported for the type of socket referenced; for example, trying to accept a connection on a datagram socket.

and as I understand and after I debugged a lot of time using lldb, I noticed that syscall returns one of those numbers that are shown in the errno man page, for example when I pass a bad file descriptor, in my ft_read function using the below main.c code like this :

int bad_file_des = -1337;// a file descriptor which it doesn't exist of course, you can change it with -42 as you likeft_read(bad_file_des, buff, 300);

our syscall returns 9 which is stored in rax so I compare if rax< 103 (because errno values are from 0 to 102) then jump to ft_read_error because that's what it should do.

Well everything works as I planned but there is a problem which came from nowhere, when I open an existing file and I pass it's file descriptor to my ft_read function as shown in the below main.c, our read syscall returns "the number of bytes read is returned", this is what read syscall returns as described on the manual:

On success, the number of bytes read is returned (zero indicates endof file), and the file position is advanced by this number. It isnot an error if this number is smaller than the number of bytesrequested; this may happen for example because fewer bytes areactually available right now (maybe because we were close to end-of-file, or because we are reading from a pipe, or from a terminal), orbecause read() was interrupted by a signal. See also NOTES.

On error, -1 is returned, and errno is set appropriately. In thiscase, it is left unspecified whether the file position (if any)changes.

and in my main that it works pretty fine, I pass to my ft_read function a good file descriptor, a buffer to store the data, and 50 bytes to read, so syscall will return 50 that stored in rax, then the comparison makes it's job >> rax = 50< 103 then it will jump to ft_read_error even that there is no error, just because 50 is one of those errno error numbers which is not in this case.

someone suggests to use jc (jump if carry flag is set) rather than jl (jump if less) as shown in the code below :

;;;;;;ft_read.s;;;;;;global _ft_read:section .textextern ___error_ft_read:    mov rax, 0x2000003 ; store syscall value of read on rax     syscall            ; call read and pass to it rdi , rsi, rdx  ==> rax read(rdi, rsi, rdx)                       ; deleted the cmp    jc _ft_read_error  ; if carry flag is set then jump to _ft_read_error    ret                ; else return the rax value which is btw the return value of syscall_ft_read_error:    push rax    call ___error    pop rcx    mov [rax], rcx    mov rax, -1    ret

and guess what, it works perfectly and errno returns 0 using my ft_read when there is no error, and it returns the appropriate error number when there is an error.

but the problem is that I don't know why the carry flag got set, when there is no cmp, does syscall set the carry flag when there is an error during the call, or there is another thing happening in the background? I want a detailed explanation about the relation between the syscall and carry flag, I am still new to assembly and I want to learn it so badly, and thanks in advance.

what is the relation between the syscall and carry flag and how syscall sets it?

this is my main.c function that I use to compile the assembly code above :

#include <stdio.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#include <sys/types.h>#include <fcntl.h>#include <errno.h>ssize_t ft_read(int fildes, void *buf, size_t nbyte);int     main(){    /*-----------------------------------------------------------------------*/    ///////////////////////////////////////////////////////////////////////////    /********************************ft_read**********************************/    int     fd = open("./main.c", O_RDONLY);    char    *buff = calloc(sizeof(char), 50 + 1);    int     ret = ft_read(fd, buff, 50);    printf("ret value = %d,  error value = %d : %s\n", ret, errno, strerror(errno));    //don't forget to free ur buffer bro, this is just a test main don't be like me.    return (0);}

Viewing all articles
Browse latest Browse all 6334

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>