Home > Blockchain >  assembly aarch64 get current unix timestamp
assembly aarch64 get current unix timestamp

Time:07-09

I expect I can get current nanosecond or microsecond unix timestamp from syscall then stored into a register for example register x0.

I read this arch64 syscall table, it seems I can use it for 0x99 in x8 register but I'm not sure how to use it. It seems the return value of timestamp will be stored in register x0 as struct tms __user *tbuf

I tried this simple asm code

_start:
mov x8, 0x99
svc 0

In debugger, after svc executed, it had value 1725984227 in x0 or 0x66e06de3 in hexadecimal form.

What does it mean? The current timestamp should be 16xxx...xx but it started with 17xxx..xx

CodePudding user response:

As @PeterCordes mention, you can use times or clock_gettime.

But I prefer clock_gettime with kernel convention 0x71 in register x8 according your refference table.

Here is my code, note that I'm using modular programming assembly so .include is needed.

.data
//reseve 8 bytes for second and 8 bytes for nanosecond
TIME_OUTPUT: .zero 16

//line feed alloc for print newline
LF: .ascii "\n"

.text
.global _start
.include "exit.s" // import exit
.include "print.s" // import print library

_start:

 // getting current timestamp
 mov x0, 0 // x0=0 means CLOCK_REALTIME
 ldr x1, =TIME_OUTPUT // store output in specified addres
 mov x8, 0x71 // kernel convention
 svc 0 //execute

 // processing output
 ldr x2, [x1] // load second
 ldr x3, [x1, 8] // load nanosecond
 ldr x4, =1000000000 //nanosecond unit for multiplier
 mul x2, x2, x4 // multiply second
 add x0, x2, x3 // add second   nanosecond store in x0

 // print Unsigned Integer 64bit
 bl _print_u64 // the argument is in x0 which unsigned integer in bin>

 // print Line Feed (newline)
 ldr x0, =LF
 mov x1, 1
 bl _print

_exit:
 exit 0 // just exit gracefully with exit code 0

Output:

1657248826648171250

So you must make print.s if you didn't make print function yet.

/* Function Usage
_print <x0: start address> <x1: length>
 "Print string based on address offset and length."
eg: mov x0, 0x12345; mov x1, 5; bl _print

_print_uint64 <x0: uint64 in binary form>
 "Print string char format from uint64."
eg: mov x0, #12345; bl _print_uint64 // 12345
*/

/* Macro Usage
print_str <string>
 "Print string to the standard output."
eg: print_str "Hello world!\n"

print_uint64 <uint64>
 "Print string char format from uint64 to the stdout."
eg: print_uint64 123456
*/

// Register Dependencies: x0 until x8


.type _print, @function
.global _print
_print: //args: x0 start_address, x1 length
  mov x2, x1; mov x1, x0 //moving arguments x0, x1
  mov x0, 1; mov x8, 0x40; svc 0 //system call
  ret //void

.type _print_u64, @function
_print_u64: //args: x0 uint64 in binary form
 mov x1, 10 //divisor
 mov x5, 0 //total digit
 _dividing:
  udiv x2, x0, x1; msub x3, x2, x1, x0 //x2 quotient, x3 remainder
  add x4, x3, 0x30 //convert remainder to ascii char
  sub x5, x5, 1; strb w4, [sp,x5] //store ascii char
  mov x0, x2; cmp x0, 0; b.ne _dividing //jump if quotient not zero
 mov x0, sp; add x0, x0, x5 //x0 args
 neg x1, x5 //x1 args
 mov x6, lr //backup lr
 bl _print
 mov lr, x6 //restore lr
 ret //void

.macro print_str string
 .pushsection .data
 str\@: .ascii "\string"
 len\@= .-str\@
 .popsection
 ldr x0, =str\@
 mov x1, len\@
 bl _print
.endm

.macro print_u64 unsigned_int64
 .pushsection .data
 uint64\@: .8byte \unsigned_int64
 .popsection
 ldr x0, uint64\@
 bl _print_uint64
.endm

And exit.s

/*
exit <code>
  "Exit the program with code, 0 means success."
eg: exit 0
*/

.macro exit code
 mov x0, #\code
 mov x8, #0x5d
 svc #0
.endm

Here is summary explanation: You just need focus to getting current timestamp and processing output (optional).

You will get return value which will be stored in memory address that stored in register x1. For example current second is 1657248826 in [x1]. Current nanosecond is 648171250 in [x1,8]

Then in processing output You just need make like this

ts = 1657248826
ts = ts * 1000000000 // because there are 9 zeros for nano unit
ts = ts   648171250
/So the final is
ts = 1657248826648171250
  • Related