Для получения времени непрерывной работы системы обычно используется функция API
GetTickCount. Она возвращает количество миллисекунд, прошедших с момента последнего старта системы. Проблема в том, что счетчик имеет тип dword, и по прошествии примерно 50 дней (49,7 если быть точным) достигает предельного значения и обнуляется. Конечно, продержать систему без перезагрузки почти два месяца трудно, но не значит что невозможно. Поэтому для получения гарантированно точного времени работы системы воспользуемся функцией
NtQuerySystemInformation. Достаточно долго эта функция относилась к разряду недокументированных, теперь же на MSDN по ней имеется описание с примечанием, что ее использование в прикладных программах все равно нежелательно.
; Сегмент данных
section '.data' data readable writeable
; По умолчанию структура в FASM не определена, сделаем это самостоятельно
; Для получения необходимой информации нужны только два первых значения
struct SYSTEM_TIME_INFORMATION
liKeBootTime dq ? ; Время старта системы
liKeSystemTime dq ? ; Текущее время
liExpTimeZoneBias dq ?
uCurrentTimeZoneId dd ?
dwReserved dw ?
ends
SystemTime SYSTEM_TIME_INFORMATION ; Наша структура с данными
; Константа нужного класса информации тоже не определена, сделаем это сами
GET_SYSTEM_TIME_INFORMATION = 3
; Сегмент кода
section '.code' code readable executable
...
invoke NtQuerySystemInformation, GET_SYSTEM_TIME_INFORMATION,\
SystemTime, sizeof.SYSTEM_TIME_INFORMATION, 0
; Записать в регистры EDX:EAX текущее время в миллисекундах
mov eax, dword [SystemTime.liKeSystemTime]
mov edx, dword [SystemTime.liKeSystemTime+4]
; Вычесть время старта системы
sub eax, dword [SystemTime.liKeBootTime]
sbb edx, dword [SystemTime.liKeBootTime+4]
; Теперь в регистры EDX:EAX записано реальное количество миллисекунд,
; прошедшее с момента старта системы
...
Преобразовать миллисекунды в обычный вид даты и времени можно при помощи пары стандартных функций
FileTimeToLocalFileTime и
FileTimeToSystemTime.
; Сегмент данных
section '.data' data readable writeable
; По умолчанию структура в FASM не определена, сделаем это самостоятельно
; Для получения необходимой информации нужны только два первых значения
struct SYSTEM_TIME_INFORMATION
liKeBootTime dq ? ; Время старта системы
liKeSystemTime dq ? ; Текущее время
liExpTimeZoneBias dq ?
uCurrentTimeZoneId dd ?
dwReserved dw ?
ends
SystemTime SYSTEM_TIME_INFORMATION ; Наша структура с данными
; Добавляются две стандартные структуры для работы с датой и временем
ftSystemTime FILETIME
stSystemTime SYSTEMTIME
; Константа нужного класса информации тоже не определена, сделаем это сами
GET_SYSTEM_TIME_INFORMATION = 3
; Сегмент кода
section '.code' code readable executable
...
invoke NtQuerySystemInformation, GET_SYSTEM_TIME_INFORMATION,\
SystemTime, sizeof.SYSTEM_TIME_INFORMATION, 0
; Получить текущее системное время. Для получения времени старта
; системы замените в вызове SystemTime.liKeSystemTime на
; SystemTime.liKeBootTime
invoke FileTimeToLocalFileTime, SystemTime.liKeSystemTime,\
ftSystemTime
; Преобразовать в системный формат даты и времени
invoke FileTimeToSystemTime, ftSystemTime, stSystemTime
; Теперь к элементам структуры stSystemTime можно обращаться
; обычными способами: [stSystemTime.wDay], [stSystemTime.wMonth] и т.д.
...
После выполнения этого кода структура stSystemTime (стандартная структура
SYSTEMTIME) содержит все значения в удобном для доступа и обработки виде.