如何在 Linux 上使用NASM访问系统时间?
(编者注:接受的答案是针对具有直接硬件访问权限的 16 位 DOS;它可以在 DOSBox 中工作。其他答案实际上是针对 Linux 的。)
Using 32-bit code under Linux:
mov eax, 13 ; call number = __NR_time
xor ebx, ebx ; tloc = NULL
int 0x80
; 32-bit time_t in EAX
This is a system call to time(2)
(system call number 13), and it returns the signed 32-bit time_t
in EAX.
(Unlike other system calls, return values >= -4095U (MAX_ERRNO) are still successes, and simply small negative numbers that represent times just before Jan 1, 1970. With a NULL pointer arg, time(2)
can't fail. See the man page for details.)
在裸机上(在自定义操作系统中)或在 DOS 程序中:
%define RTCaddress 0x70
%define RTCdata 0x71
;Get time and date from RTC
.l1: mov al,10 ;Get RTC register A
out RTCaddress,al
in al,RTCdata
test al,0x80 ;Is update in progress?
jne .l1 ; yes, wait
mov al,0 ;Get seconds (00 to 59)
out RTCaddress,al
in al,RTCdata
mov [RTCtimeSecond],al
mov al,0x02 ;Get minutes (00 to 59)
out RTCaddress,al
in al,RTCdata
mov [RTCtimeMinute],al
mov al,0x04 ;Get hours (see notes)
out RTCaddress,al
in al,RTCdata
mov [RTCtimeHour],al
mov al,0x07 ;Get day of month (01 to 31)
out RTCaddress,al
in al,RTCdata
mov [RTCtimeDay],al
mov al,0x08 ;Get month (01 to 12)
out RTCaddress,al
in al,RTCdata
mov [RTCtimeMonth],al
mov al,0x09 ;Get year (00 to 99)
out RTCaddress,al
in al,RTCdata
mov [RTCtimeYear],al
ret
这使用 NASM,并且来自这里。
这在像 Linux 这样阻止用户空间进程直接访问硬件的普通操作系统下是行不通的。您可以通过ioperm(2)
系统调用以允许访问该 I/O 端口的方式使其以 root 身份工作。Linux 仅在关机期间更新 BIOS/硬件 RTC 以匹配当前系统时间,而不是连续更新,因此不要期望它完全同步,尤其是在主板电池没电的情况下。
作为上述 Pyves 答案的附录(使用 x86-64/NASM/Linux),如果您想获得比一秒更好的时钟分辨率,您可以使用 228 而不是 201 进行系统调用以在一个 64 位变量中获得秒数,并且另一个 64 位变量中的额外纳秒(超过秒)。
default rel
section .bss
time: resq 2 ; 2 qwords for seconds and nanoseconds
section .text
mov rax, 228 ; 228 is system call for sys_clock_gettime
xor edi, edi ; 0 for system clock (preferred over "mov rdi, 0")
lea rsi, [time]
syscall ; [time] contains number of seconds
; [time + 8] contains number of nanoseconds
从手册页来看,x86-64 上的系统调用是
int clock_gettime(clockid_t clock_id, struct timespec *tp);
struct timespec
一对无符号的 64 位整数,低地址为秒,高地址为纳秒。
我想说,根据您使用的平台,您必须使用操作系统功能。
在 Windows 上,尝试GetSystemTime。在 linux 上,尝试 gettimeofday -在此处查看相关问题。