LinuxでNASMを使用してシステム時刻にアクセスするにはどうすればよいですか?
(編集者注:受け入れられた答えは、ハードウェアに直接アクセスできる16ビットDOS用です。DOSBox内で機能します。他の答えは実際にはLinux用です。)
Linuxで32ビットコードを使用する:
mov eax, 13 ; call number = __NR_time
xor ebx, ebx ; tloc = NULL
int 0x80
; 32-bit time_t in EAX
これは(システムコール番号13)へのシステムコールであり、EAXでtime(2)
署名された32ビットを返します。time_t
(他のシステムコールとは異なり、戻り値> = -4095U(MAX_ERRNO)は引き続き成功し、1970年1月1日直前の時間を表す単純な小さな負の数です。NULLポインター引数を使用するとtime(2)
、失敗することはありません。詳細。)
ベアメタル(カスタムOSの場合)または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などの通常のOSでは機能しません。ioperm(2)
そのI/Oポートへのアクセスを許可するシステムコールを使用して、これをrootとして機能させることができます。LinuxはBIOS/ハードウェアRTCをシャットダウン中に現在のシステム時間に一致するように更新するだけで、継続的には更新しないため、特にマザーボードのバッテリーが切れている場合は、完全に同期しているとは思わないでください。
NASMでは、Linux x86-64をターゲットにしている場合、次のことを簡単に実行できます。
mov rax, 201
xor rdi, rdi
syscall
201
(ここsys_time
にリストされている)の64ビットシステムコール番号に対応します。レジスタは0に設定されているため、システムコールを実行した後の戻り値はに格納されますが、選択したメモリ位置を指すようにすることもできます。結果は、エポックからの秒数で表されます。rdi
rax
このシステムコールの詳細については、タイムマンページを参照してください。
上記のPyvesによる回答の補足として(x86-64 / NASM / Linuxを使用)、1秒よりも優れたクロック解像度を取得したい場合は、201ではなく228でsyscallを実行して、1つの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
マニュアルページから、システムコールは
int clock_gettime(clockid_t clock_id, struct timespec *tp);
struct timespec
x86にあります-64は符号なし64ビット整数のペアであり、下位アドレスに秒、上位アドレスにnanosがあります。
使用しているプラットフォームによっては、OS機能を使用する必要があると思います。
Windowsでは、GetSystemTimeを試してください。Linuxでは、gettimeofdayを試してください。関連する質問はこちらをご覧ください。