【问题标题】:assembly aarch64 get current unix timestamp程序集 aarch64 获取当前的 unix 时间戳
【发布时间】:2022-07-08 10:59:04
【问题描述】:

我希望我可以从系统调用中获取当前的纳秒或微秒 unix 时间戳,然后将其存储到寄存器中,例如寄存器 x0

我读过这个arch64 syscall table,看来我可以在x8 寄存器中将它用于0x99,但我不知道如何使用它。似乎时间戳的返回值将存储在寄存器x0中为struct tms __user *tbuf

我试过这个简单的 asm 代码

_start:
mov x8, 0x99
svc 0

在调试器中,在svc 执行后,它的值1725984227x00x66e06de3 十六进制形式。

这是什么意思?当前时间戳应该是 16xxx...xx 但它以 17xxx..xx 开头

【问题讨论】:

  • 另外,请注意,在大多数现代操作系统上,获取当前时间根本没有作为系统调用实现。它通常是所谓的 VDSO。
  • 我使用 Android/Linux 作为操作系统
  • 另外,你提到的表links to the relevant documentation of times,它描述了你得到了什么。
  • @MarcusMüller:Linux 内核确实处理系统调用的调用号,这些调用也可通过 VDSO 获得,因此您可以只使用svc 来处理像timesclock_gettime 如果您正在用 asm 编写玩具程序并且更关心简单性而不是效率。
  • @PeterCordes 是的,我搞砸了。但是如果你关心简单而不是效率,你就不会使用汇编程序(至少在 aarch64 上,空间可能无关紧要)

标签: linux assembly arm64


【解决方案1】:

正如@PeterCordes 提到的,您可以使用timesclock_gettime

但我更喜欢clock_gettime 与内核约定0x71 在寄存器x8 根据您的参考表。

这是我的代码,注意我使用的是模块化编程汇编,所以需要.include

.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

输出:

1657248826648171250

所以如果你还没有制作打印功能,你必须制作print.s

/* 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

还有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

以下是简要说明: 您只需要关注getting current timestamp 并处理输出。

您将获得返回值,该值将存储在寄存器x1 中存储的内存地址中。例如当前秒是 1657248826[x1] 当前纳秒是 648171250.

然后在processing output 你只需要这样

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

【讨论】:

    猜你喜欢
    • 2012-03-04
    • 1970-01-01
    • 2018-01-05
    • 2021-12-04
    • 2012-09-07
    • 2011-12-26
    • 2011-02-17
    • 2013-07-20
    • 2012-03-21
    相关资源
    最近更新 更多