0

I am writing assembly-nasm program and I would like to use current time of a device. In Linux, there is a system call with number 201 which returns amount of seconds from the beginning of 1970. Does anyone know what is the value of a corresponding system call in macOS?

Mateusz Stompór
  • 461
  • 6
  • 15
  • 1
    `116 AUE_GETTIMEOFDAY ALL { int gettimeofday(struct timeval *tp, struct timezone *tzp) NO_SYSCALL_STUB; } ` 116 decimal (0x74 hex) is the system call for 32-bit.64-bit system call numbers have to have 0x2000000 added to them. System call table can be found here: https://opensource.apple.com/source/xnu/xnu-2782.20.48/bsd/kern/syscalls.master – Michael Petch Oct 10 '18 at 22:32

2 Answers2

1

Thank you for your help, I have found the solution. Below you can find how to load time to buffer storage

macOS

load_time:
   mov rax, 0x2000074
   lea rdi, [rel buffer]
   mov rsi, 0
   syscall
   ret

You provide pointer to buffer as an argument to retrieve data in form of a structure

_STRUCT_TIMEVAL {
    __darwin_time_t         tv_sec;         /* seconds */
    __darwin_suseconds_t    tv_usec;        /* and microseconds */
};

In case of Linux only seconds are returned

load_time
    mov rax, 201
    mov rdi, 0
    syscall
    mov [rel buffer], rax
    ret
Mateusz Stompór
  • 461
  • 6
  • 15
  • I am trying to do exactly this but confused by the system call. You are using: 0x2000074 and shouldn't it be 0x2000116? Also how do you access both the seconds and the microsecconds from the buffer? Thanks – Will Apr 21 '20 at 00:38
  • 1
    Look at https://opensource.apple.com/source/xnu/xnu-2782.20.48/bsd/kern/syscalls.master. The function that you need has number `116`. It a decimal number, we need to convert it to hex, which is 0x74 and then add 0x2000000 . That's why I was using 0x2000074 – Mateusz Stompór Apr 21 '20 at 13:51
  • 1
    Once you perform the syscall your buffer will be filled with seconds and microseconds. On my machine size of the struct is 16 bytes. To read the first value to the register call `mov rdi, [rel buffer]`. The value will be in `rdi` (whole register, 64 bits). To read the microseconds `lea rax, [rel buffer]` to obtain the pointer and then `mov rdi, [rax + 64]`. – Mateusz Stompór Apr 21 '20 at 14:17
  • Thank you. That clarified both questions. Will try it now. – Will Apr 21 '20 at 18:30
  • Trying to calculate elapsed time. I get a start_time and end_time and calculate difference. Somehow microseconds always show up as zero. What could I be doing wrong? – Will Apr 22 '20 at 03:32
1

Just to complement your answer I found a very simple way to access seconds and microseconds by declaring:

timeval:
    tv_sec  dq 0
    tv_usec dq 0

timestr db "Secs: %ld and microsecs: %ld", 10, 0

After you do:

    mov         rax, 0x2000074
    lea         rdi, [timeval]
    mov         rsi, 0          
    syscall

You can then access each by their name like for printing:

    lea         rdi, [timestr]     
    mov         rsi, [tv_sec]
    mov         rdx, [tv_usec]
    call        _printf 
Will
  • 303
  • 3
  • 9
  • 1
    For high-precision timing, you might want `clock_gettime` instead of `gettimeofday` (if that's what that is). Or even better, if MacOS has a way in user-space to get the time without a kernel round-trip, that would be lower overhead. (e.g. on GNU/Linux, the `clock_gettime` library function can use code+data exported by the kernel (VDSO) to do `rdtsc` in user-space and scale the result) – Peter Cordes Apr 22 '20 at 23:38
  • You are right but macOS does not have clock_gettime. There seem to be a few other alternatives such as mach_absolute_time() that I need to figure out how to access through nasm. – Will Apr 23 '20 at 04:16
  • 1
    You mean not as a system call, or not at all? [`clock_gettime(2)`](https://pubs.opengroup.org/onlinepubs/009695399/functions/clock_getres.html) is standardized by POSIX 2001, but it could be a library function on top of some other syscall. I was curious so I searched; [clock\_gettime alternative in Mac OS X](https://stackoverflow.com/a/21352348) and yeah, apparently `mach_absolute_time` is the way to go from C. You could of course just call the libc implementation from nasm. – Peter Cordes Apr 23 '20 at 04:23
  • 1
    Thank you. Here goes a very good article that explains use of mach_absolute_time: http://www.jonathanbeard.io/tutorials/Timing.html – Will Apr 23 '20 at 14:51