FASM--Win32汇编学习6

                          FASM--Win32汇编学习6

本节学习目标:windows时间

 

                     很多人看到“定时器”就会联想到时钟,笔者也曾经也是。但是在上节课程中我们已经说过,定时器是不能用来构造定时器的,定时器用于时钟程序中只能是在定时刷新屏幕这个功能上。因为我们调用SetTimer函数实质windows内核也是截获我们时钟中断的,时钟中断每55ms发生一次,且我们设定间隔时间总是时钟中断频率的倍数。 所以它不是很准确,那么今天就让我们来学习下我们如何来获得windows的时间。

 

                     在win32编程中,常用的获取系统时间的函数有两个:

                    invoke GetLocalTime, lpSystemTime

                    invoke GetSystemTime,lpSystemTime

 

                   它们的区别是GetlocalTime返回的是当前的时间,GetSystemTime返回的是当前的格林威治标准时间,这两阁函数返回的时间数据包括 年、月、日、时、分、秒、毫秒、以及星期。由于数据较多所以无法放在eax寄存器中返回,应用程序必须预先设置一个SYSTEMTIME结构的缓冲区,并将缓冲区地址lpSystemTime当参数传递给函数,函数会把时间数据返回到这个缓冲区中。

 

struct SYSTEMTIME
    WORD wYear;年
    WORD wMonth; 月
    WORD wDayOfWeek ;指定星期几,例如Sunday = 0, Monday = 1
    WORD wDay;日,也就是本月的几号
    WORD wHour;小时
    WORD wMinute; 分
    WORD wSecond; 秒
    WORD wMilliseconds; 毫秒
ends

 

那么我们来看一段代码。这个例子是在消息框上显示当前的年月日以及星期几。


    format PE GUI 4.0
    include 'win32ax.inc'
   
    ;**********************数据*****************************
    systime SYSTEMTIME
    szBuffer db 30 dup ?
   
    entry $
        invoke GetLocalTime, systime
        mov ebx, systime
        movzx eax, word [ebx];年
        movzx esi, word [ebx+2];月
        movzx edx, word [ebx+4];星期
        movzx edi, word [ebx+6];日
        invoke wsprintf,szBuffer, '%d年%d月%d日 星期%d ', eax, esi, edi,edx
        invoke MessageBox,NULL, szBuffer, '提示', MB_OK
        invoke ExitProcess,NULL
   
   
    section '.import' data import readable
        library kernel32, 'kernel32.dll',/
            user32, 'user32.dll'
        include 'api/kernel32.inc'
        include 'api/user32.inc'   

那么此刻大家把这段代码编译运行,看是不是显示出当前的时间以及星期。好我们现在来解剖这段代码。

invoke GetLocalTime, systime

我们调用GetLocalTime函数,这个函数的参数就是刚刚我们声明的SYSTEMTIME结构的缓冲区地址。

然后将systime这个结构的变量的地址传送给ebx寄存器。因为等一下要用它来进行间接寻址。这些基础大家去之前黑防论坛也有相应的板块。

因为下面我们要用wsprintf函数来格式化我们的这个结构中的成员,因为此时我们获得是相应的16进制数值,我们需要转换成10进制,这样显示出来的才是我们真正的时间以及日期。我们可以调用wsprintf函数来格式化,那么我们来看下这个函数的参数。

int wsprintf(

LPTSTR lpOut,    // pointer to buffer fo
LPCTSTR lpFmt,     // pointer to format-control string
...    // optional arguments
);   

首先第一个参数是指定我们输出的缓冲区的地址 。

第二个参数是指定我们输出的格式,这个函数其实和我们的c语言sprintf很相似,没办法谁让windows是C写的呢。所以第二个参数是指向输出格式字符串的地址。

第三个参数则指定需输出的参数(也就是要格式化的参数)。

 

那么我们来看下由于我们是通过%d参数来格式化,%d是整数类型,占4个字节。。我们的SYSTEMTIME结构每个成员是word类型,两个字节。所以我们在进行格式化之前,我们一定要想办法把它扩展成4个字节的。这时候我们就要用到我们的mozx指令。movzx指令是扩展指令,是将源操作数扩展成4阁字节并存放到目的操作数种,其余扩展的数值位用0填充。。那么很明确,我们可以利用movzx将我们的SYSTEMTIME结构的成员一部分扩展到相应的寄存器中,然后后面用寄存器来进行格式化字符串。。

        movzx eax, word [ebx];年
        movzx esi, word [ebx+2];月
        movzx edx, word [ebx+4];星期
        movzx edi, word [ebx+6];日

 

    首先我们取得systime结构变量的缓冲区地址,然后将这个地址赋值给我们的ebx寄存器,然后后面我们利用[ebx+常数]来进行变址寻址。

    我们将格式化的后的字符串保存到之前我们声明的缓冲区中,也就是szBuffer里,这个是我们声明的50个字节的缓冲区。。

 

    最后通过调用MessageBox函数将其显示出来。。

    invoke MessageBox,NULL, szBuffer, '提示', MB_OK

 

   很简单吧。 好的,获取本地时间,我们就讲到这里。接下来我们来学习下如何计算时间间隔。

   Windows提供给我们了一个获取时间戳的函数,GetTickCount。GetTickCount函数返回的是windows本次启动以来的ms数,得到的时间数值直接在eax寄存器返回。这是一个32位的证书,可以表示的范围是1 - ffffffffh ms,所以当windows连续运行49.7天以后,计数器会清0,重新开始,虽然这个函数无法用来判断当前的具体时间,但是计算两个时间点的时间间隔是最合适不过了。。

        invoke GetTickCount
        mov [dwCount], eax
        invoke GetTickCount
        sub eax, [dwCount]

  在win9x系统下,GetTickCount函数的精度为55ms,任何调用两次GetTickCount函数相减后得到的时间间隔幺么是0,要么是55ms的整数倍。在windows NT/2000/xp系统下,这个函数的精度为10ms。

原作者网站http://www.xuyibo.org ,感谢徐艺波辛苦整理写出的该技术手册,为我等FASM学习者提供了良好的参考资料。目前FASM学习资料实在是无比匮乏,网上也鲜见。这个技术手册无疑是雪中送炭,再洗感谢原作者。 1. 简介 1.1 编译器概述 1.1.1 系统需求 1.1.2 编译器使用 1.1.3 编译器选项 1.1.4 在命令行下执行编译器 1.1.5 命令行编译器消息 1.1.6 输出格式 1.2 汇编语法 1.2.1 指令语法 1.2.2 数据定义 1.2.3 常数和标号 1.2.4 数值表达式 1.2.5 跳转和调用 1.2.6 操作数尺寸设置 2. 指令集 2.1 x86 体系指令 2.1.1 数据传送指令 2.1.2 类型转换指令 2.1.3 二进制算术指令 2.1.4 十进制算术指令 2.1.5 逻辑指令 2.1.6 控制转移指令 2.1.7 I/O 指令 2.1.8 字符串操作指令 2.1.9 标志控制指令 2.1.10 条件操作指令 2.1.11 其他指令 2.1.12 系统指令 2.1.13 FPU 指令 2.1.14 MMX 指令 2.1.15 SSE 指令 2.1.16 SSE2 指令 2.1.17 SSE3 指令 2.1.18 AMD 3DNOW!指令 2.1.19 x86-64长模式指令 2.2 控制伪指令 2.2.1 数值常量 2.2.2 条件汇编 2.2.3 重复块指令 2.2.4 地址空间 2.2.5 其他伪指令 2.2.6 多遍扫描 2.3 预处理伪指令 2.3.1 包含源文件 2.3.2 符号常量 2.3.3 宏指令 2.3.4 结构 2.3.5 重复宏指令 2.3.6 条件宏指令 2.3.7 处理顺序 2.4 格式伪指令 2.4.1 MZ 格式 2.4.2 PE 格式 2.4.3 COFF 格式 2.4.4 ELF 格式 3. Windows 编程 3.1 基本头文件 3.1.1 结构 3.1.2 导入表 3.1.3 过程 3.1.4 导出表 3.1.5 COM(组件) 3.1.6 资源 3.1.7 字符编码 3.2 扩展头文件 3.2.1 过程参数 3.2.2 结构化源码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值