AArch64汇编调用syscall获取Unix时间戳返回值异常问题
问题原因
- 你选错了系统调用号:AArch64 架构Linux环境下,
0x99(十进制153)对应的是times()系统调用,这个接口的作用是获取进程自身及已回收子进程占用的CPU时间,根本不是用来获取Unix纪元墙上时间的。 - 你对系统调用的返回规则理解有误:所有需要返回多字段结构体的系统调用,都不会把结构体内容直接存在通用寄存器里。系统调用返回时
x0寄存器仅存储整数类型的返回值:成功时通常是0或者正整数结果,失败时是负的错误码;结构体类型的返回数据,需要你提前向内核传入一块自己拥有写权限的内存地址,内核会把数据拷贝到这块内存中。 - 你调试时拿到的
1725984227本身是2024年9月前后的秒级Unix时间戳,但这不是times()系统调用的标准返回结果——标准实现中times()返回的是从系统启动等固定参考点开始计算的时钟滴答数,和Unix纪元时间无关,你拿到这个值属于运行环境(如用户态模拟器、定制内核)的非标准行为,不能作为正确调用的参考。
正确实现方法
要获取纳秒/微秒级Unix时间戳,你需要调用clock_gettime接口,AArch64 Linux下对应的系统调用号是0x71(十进制113),参数规则如下:
x0:时钟类型ID,传0即CLOCK_REALTIME,代表获取从1970-01-01 00:00:00 UTC开始计算的真实Unix时间x1:指向struct timespec结构的内存指针,结构总长度16字节,前8字节存储秒级时间戳,后8字节存储纳秒级偏移(取值范围0~999999999)- 系统调用返回后
x0为0代表调用成功,你可以直接从传入的内存地址中读取时间值。
如果你不需要长期保存时间结构,直接用栈空间做临时缓冲区就能把秒级时间戳直接读到x0寄存器,示例代码如下:
_start: mov x8, #0x71 // 加载clock_gettime系统调用号 mov x0, #0 // 指定时钟类型为CLOCK_REALTIME sub sp, sp, #16 // 在栈上分配16字节空间存timespec结构 mov x1, sp // 把缓冲区地址作为第二个参数传入 svc #0 // 触发系统调用 ldp x0, x1, [sp], #16 // 把秒值加载到x0,纳秒值加载到x1,同时回收栈空间 // 此时x0就是你要的秒级Unix时间戳,x1是对应的纳秒偏移,除以1000即可得微秒偏移
注意:如果你运行的不是Linux环境(比如BSD、macOS、专用RTOS),系统调用号和传参规则会有差异,需要对应环境的调用表调整参数。
内容的提问来源于stack exchange,提问作者Citra Dewi
相关产品推荐
相关产品推荐

