xyblack技术地带

为了梦想奋斗...............

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。

阅读更多
个人分类: 汇编/逆向工程....
想对作者说点什么? 我来说一句

学习汇编语言最好的工具

2016年04月27日 173KB 下载

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭