Системное время, получить минуя вызов GetSystemTimeAsFileTime

Тема в разделе "WASM.WIN32", создана пользователем sasha_s, 13 янв 2009.

  1. sasha_s

    sasha_s New Member

    Публикаций:
    0
    Регистрация:
    21 дек 2005
    Сообщения:
    165
    Адрес:
    Belarus
    Вот тело GetSystemTimeAsFileTime (это под XP SP2):

    7C8017E7 push ebp
    7C8017E8 mov ebp,esp
    7C8017EA mov eax,[7FFE0018]
    7C8017EF mov edx,dword ptr ds:[7FFE0014h]
    7C8017F5 cmp eax,dword ptr ds:[7FFE001Ch]
    7C8017FB jne 7C8017EA
    7C8017FD mov ecx,dword ptr [ebp+8]
    7C801800 mov dword ptr [ecx],edx
    7C801802 mov dword ptr [ecx+4],eax
    7C801805 pop ebp
    7C801806 ret 4

    Так вот как видно ф-ция читает время по адресам [7FFE0018] и [7FFE0014h], потом сравнивает старшее слово с тем что по адресу [7FFE001Ch] и если не равно, то цикл повторяется, иначе время прочитано.

    Вопросса три:
    1) что за сравнения и зачем?
    2) как получить сии адреса под любой операционкой (из ряда NTшных ядер) с минимумом затрат?
    3) можно ли использовать это тело скажем под 2к без изменений, кроме перечисленных адресов?
     
  2. Hellspawn

    Hellspawn New Member

    Публикаций:
    0
    Регистрация:
    4 фев 2006
    Сообщения:
    310
    Адрес:
    Москва
    win 2000 sp4
    Код (Text):
    1. 793A72E5 >/$  A1 1800FE7F     MOV EAX,DWORD PTR DS:[7FFE0018]
    2. 793A72EA  |.  8B15 1400FE7F   MOV EDX,DWORD PTR DS:[7FFE0014]
    3. 793A72F0  |.  3B05 1C00FE7F   CMP EAX,DWORD PTR DS:[7FFE001C]
    4. 793A72F6  |.^ 75 ED           JNZ SHORT kernel32.GetSystemTimeAsFileTime
    5. 793A72F8  |.  8B4C24 04       MOV ECX,DWORD PTR SS:[ESP+4]
    6. 793A72FC  |.  8911            MOV DWORD PTR DS:[ECX],EDX
    7. 793A72FE  |.  8941 04         MOV DWORD PTR DS:[ECX+4],EAX
    8. 793A7301  \.  C2 0400         RETN 4
    даже адреса можно не менять
     
  3. bolkin

    bolkin New Member

    Публикаций:
    0
    Регистрация:
    5 июл 2005
    Сообщения:
    34
    Адрес:
    Israel
    lkd> dt /r1 nt!_KUSER_SHARED_DATA
    +0x000 TickCountLow : Uint4B
    +0x004 TickCountMultiplier : Uint4B
    +0x008 InterruptTime : _KSYSTEM_TIME
    +0x000 LowPart : Uint4B
    +0x004 High1Time : Int4B
    +0x008 High2Time : Int4B
    +0x014 SystemTime : _KSYSTEM_TIME
    +0x000 LowPart : Uint4B
    +0x004 High1Time : Int4B
    +0x008 High2Time : Int4B
    ....

    nt!KeUpdateSystemTime:
    ...
    80544254 89531c mov dword ptr [ebx+1Ch],edx ;High2Time
    80544257 894b14 mov dword ptr [ebx+14h],ecx ;LowPart
    8054425a 895318 mov dword ptr [ebx+18h],edx ;High1Time
    ...

    0:000> u kernel32!GetSystemTimeAsFileTime Lc
    kernel32!GetSystemTimeAsFileTime:
    mov edi,edi
    push ebp
    mov ebp,esp
    mov eax,dword ptr [SharedUserData+0x18] ;High1Time
    mov edx,dword ptr [SharedUserData+0x14] ;LowPart
    cmp eax,dword ptr [SharedUserData+0x1c] ;High1Time==High2Time
    jne kernel32!GetSystemTimeAsFileTime+0x5
    mov ecx,dword ptr [ebp+8]
    mov dword ptr [ecx],edx ;dwLowDateTime
    mov dword ptr [ecx+4],eax ;dwHighDateTime
    pop ebp
    ret 4


    Если по русски, дата хранится в двух числах High и Low, чтение их обоих неатомарная оперция, блокировать дорого.
    Ядерный код который обновляет значения обновляет High2,Low а потом High1.
    GetSystemTimeAsFileTime читает в обратном порядке и при несовпадении перечитывает.

    Адрес SharedUserData вроде постоянен (http://uninformed.org/index.cgi?v=2&a=2&p=16)

    P.S. в реактосе это реализовано видимо неправильно:
    http://www.reactos.org/generated/doxygen/df/d0e/ntoskrnl_2ke_2arm_2time_8c-source.html#l00037
    http://www.reactos.org/generated/doxygen/d1/d5a/dll_2win32_2kernel32_2misc_2time_8c.html#cbdb4ddfd0c4082c95f89a0e6f693c69