• 汇编语言Win32时间与日期函数

    Win32 API 有相当多的时间和日期函数可供选择。最常见的是,用户想要用这些函数来获得和设置当前日期与时间。这里只能讨论这些函数的一小部分,不过在 Platform SDK 文档中可以查阅到下表列出的 Win32 函数。

    函数 说明
    CompareFileTime 比较两个 64 位的文件时间
    DosDateTimeToFileTime 把 MS-DOS 日期和时间值转换为一个 64 位的文件时间
    FileTimeToDosDateTime 把 64 位文件时间转换为 MS-DOS 日期和时间值
    FileTimeToLocalFileTime 把 UTC(通用协调时间)文件时间转换为本地文件时间
    FileTimeToSystemTime  把 64 位文件时间转换为系统时间格式
    GetFileTime 检索文件创建、最后访问和最后修改的日期与时间
    GetLocalTime 检索当前本地日期和时间
    GetSystemTime 以 UTC 格式检索当前系统日期和时间
    GetSystemTimeAdjustment  决定系统是否对其日历钟进行周期性时间调整
    GetSystemTimeAsFileTime 以 UTC 格式检索当前系统日期和时间
    GetTickCount 检索自系统启动后经过的毫秒数
    GetTimeZoneInformation 检索当前时区参数
    LocalFileTimeToFileTime 把本地文件时间转换为基于 UTC 的文件时间
    SetFileTime 设置文件创建、最后访问和最后修改的日期与时间
    SetLocalTime 设置当前本地时间与日期
    SetSystemTime 设置当前系统时间与日期
    SetSystemTimeAdjustment 启用或禁用对系统日历钟进行周期性时间调整
    SetTimeZoneInformation 设置当前时区参数
    SystemTimeToFileTime 把系统时间转换为文件时间
    SystemTimeToTzSpecificLocalTime 把 UTC 时间转换为指定时区对应的本地时间

    SYSTEMTIME 结构

    SYSTEMTIME 结构由 Windows API 的日期和时间函数使用:

    SYSTEMTIME STRUCT
        wYear WORD ?                   ;年(4 个数子)
        wMonth WORD ?               ;月(1 ~ 12)
        wDayOfWeek WORD ?      ;星期(0 ~ 6)
        wDay WORD ?                   ;日(1 ~ 31)
        wHour WORD ?                 ;小时(0 ~ 23)
        wMinute WORD ?             ;分钟(0 ~ 59)
        wSecond WORD ?             ;秒(0 ~ 59)
        wMilliseconds WORD ?     ;毫秒(0 ~ 999)
    SYSTEMTIME ENDS

    字段 wDayOfWeek 的值依序为星期天 = 0,星期一 = 1,以此类推。wMilliseconds 中的值不确定,因为系统可以与时钟源同步周期性地刷新时间。

    GetLocalTime 和 SetLocalTime

    函数 GetLocalTime 根据系统时钟返回日期和当前时间。时间要调整为本地时区。调用该函数时,需向其传递一个指针指向 SYSTEMTIME 结构:

    GetLocalTime PROTO,
        lpSystemTime:PTR SYSTEMTIME

    函数 GetLocalTime 调用示例如下:

    .data
    sysTime SYSTEMTIME <>
    .code
    INVOKE GetLocalTime, ADDR sysTime

    函数 SetLocalTime 设置系统的本地日期和时间。调用时,需向其传递一个指针指向包含了期望日期和时间的 SYSTEMTIME 结构:

    SetLocalTime PROTO,
        lpSystemTime:PTR SYSTEMTIME

    如果函数执行成功,则返回非零整数;如果失败,则返回零。

    GetTickCount 函数

    函数 GetTickCount 返回从系统启动起经过的毫秒数:

    GetTickCount PROTO               ; EAX 为返回值

    由于返回值为一个双字,因此当系统连续运行 49.7 天后,时间将会回绕归零。可以使用这个函数监视循环经过的时间,并在达到时间限制时终止循环。

    下面的程序 Timer.asm 计算两次调用 GetTickCount 之间的时间间隔。程序尝试确定计时器没有回绕(超过 49.7 天)。相似的代码可以用于各种程序:

    ;计算经过的时间    (Timer.asm)
    ;用Win32函数GetTickCount演示一个简单的秒表计时器。
    INCLUDE Irvine32.inc
    INCLUDE macros.inc
    
    .data
    startTime DWORD ?
    
    .code
    main PROC
        INVOKE GetTickCount         ; 获取开始时间计数
        mov    startTime,eax        ; 保存开始时间计数
    
    ; Create a useless calculation loop.
        mov    ecx,10000100h
    L1:    imul    ebx
        imul    ebx
        imul    ebx
        loop    L1
    
        INVOKE GetTickCount         ; 获得新的时间计数
        cmp    eax,startTime        ; 比开始时间计数小
        jb    error                 ; 时间回绕
       
        sub    eax,startTime        ; 计算时间间隔
        call    WriteDec            ; 显示时间间隔
        mWrite <" milliseconds have elapsed",0dh,0ah>
        jmp    quit
    
    error:
        mWrite "Error: GetTickCount invalid--system has "
        mWrite <"been active for more than 49.7 days",0dh,0ah>
    quit:
        exit
    main ENDP
    
    END main

    Sleep 函数

    有些时候程序需要暂停或延迟一小段时间。虽然可以通过构造一个计算循环或忙循环来保持处理器工作,但是不同的处理器会使得执行时间不同。另外,忙循环还不必要地占用了处理器,这会降低在同一时间执行程序的速度。

    Win32 函数 Sleep 按照指定毫秒数暂停当前执行的线程:

    Sleep PROTO,
        dwMilliseconds:DWORD

    由于本教程中汇编语言程序是单线程的,因此假设一个线程就等同于一个程序。当线程休眠时,它不会消耗处理器时间。

    GetDateTime 过程

    Irvine32 链接库中的过程 GetDateTime 以 100 纳秒为间隔,返回从 1601 年 1 月 1 日起经过的时间间隔数。这看起来有点奇怪,因为那个时候计算机还是未知的。对任何事件,Microsoft 都用这个值来跟踪文件日期和时间。

    如果想要为日期计算准备系统日期/时间值,Win32 SDK 建议采用如下步骤:

    • 调用函数,如 GetLocalTime,填充 SYSTEMTIME 结构。
    • 调用函数 SystemTimeToFileTime,将 SYSTEMTIME 结构转换为 FILETIME 结构。
    • 将得到的 FILETIME 结构复制到 64 位的四字。

    FILETIME 结构把 64 位四字分割为两个双字:

    FILETIME STRUCT
        loDateTime DWORD ?
        hiDateTime DWORD ?
    FILETIME ENDS

    下面的 GetDateTime 过程接收一个指针,指向 64 位四字变量。它用 Win32 FILETIME 格式将当前日期和时间保存到变量中:

    ;--------------------------------------------------
    GetDateTime PROC,
        pDateTime:PTR QWORD
        LOCAL sysTime:SYSTEMTIME, flTime:FILETIME
    ;
    ; 以64位整数形式 ( 按 Win32 FILETIME 格式 ) 获得并保存当前本地时间/日期
    ;--------------------------------------------------
    ; 获得系统本地时间
        INVOKE GetLocalTime,
          ADDR sysTime
    
    ; SYSTEMTIME 转换为 FILETIME.
        INVOKE SystemTimeToFileTime,
          ADDR sysTime,
          ADDR flTime
    
    ; 把 FILETIME 复制到一个64位整数
        mov esi,pDateTime
        mov eax,flTime.loDateTime
        mov DWORD PTR [esi],eax
        mov eax,flTime.hiDateTime
        mov DWORD PTR [esi+4],eax
        ret
    GetDateTime ENDP

更多...

加载中...