首页 > 汇编语言 > 汇编语言MS-Windows编程
阅读:1,826
汇编语言Win32时间与日期函数
Win32 API 有相当多的时间和日期函数可供选择。最常见的是,用户想要用这些函数来获得和设置当前日期与时间。这里只能讨论这些函数的一小部分,不过在 Platform SDK 文档中可以查阅到下表列出的 Win32 函数。
下面的程序 Timer.asm 计算两次调用 GetTickCount 之间的时间间隔。程序尝试确定计时器没有回绕(超过 49.7 天)。相似的代码可以用于各种程序:
Win32 函数 Sleep 按照指定毫秒数暂停当前执行的线程:
如果想要为日期计算准备系统日期/时间值,Win32 SDK 建议采用如下步骤:
FILETIME 结构把 64 位四字分割为两个双字:
函数 | 说明 |
---|---|
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
GetLocalTime 和 SetLocalTime
函数 GetLocalTime 根据系统时钟返回日期和当前时间。时间要调整为本地时区。调用该函数时,需向其传递一个指针指向 SYSTEMTIME 结构:
GetLocalTime PROTO,
lpSystemTime:PTR SYSTEMTIME
.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 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