飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 3425|回复: 2

汇编改写《windows程序设计》中的模拟时钟

[复制链接]

该用户从未签到

发表于 2006-8-27 09:42:37 | 显示全部楼层 |阅读模式
;----------------------------------------------------------
;   Clock.asm  一个时钟程序
;   
;   原始作者: Charles Petzold's DIGCLOCK.C
;   汇编改写: surge
;             [email protected]
;                 2006-08-26
;   在\masm32\icztutes\tute03\win.asm一个窗口例子基础上修改
;   该例子作者:icztutes
;----------------------------------------------------------
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\gdi32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\gdi32.lib

ID_TIMER        EQU        1

WinMain         proto         :DWORD,:DWORD,:DWORD,:DWORD
SetIsotropic        proto        :HDC,  :DWORD,:DWORD
DrawClock         proto        :DWORD
RotatePoint        proto        :PTR POINT,:DWORD,:DWORD
DrawHands        proto        :HDC,        :PTR SYSTEMTIME,:BOOL
.data
ClassName db "SimpleWinClass",0
AppName  db "Our First Window",0
pt        POINT        <0, -150>, <100, 0>,< 0, 600>,< -100, 0>, <0, -150>,\
                 <0, -200>,  <50, 0>,< 0, 800>,<  -50, 0>,< 0, -200>,\
                 <0,    0>,   <0, 0>, <0,   0>,    <0, 0>, <0,  800>

.data?
hInstance HINSTANCE ?
CommandLine LPSTR ?

cxClient        dd        ?
cyClient        dd        ?

stPrevious        SYSTEMTIME        <>

.code
start:
        invoke GetModuleHandle, NULL
        mov    hInstance,eax
        invoke GetCommandLine
        mov    CommandLine,eax
        invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
        invoke ExitProcess,eax

WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
        LOCAL wc:WNDCLASSEX
        LOCAL msg:MSG
        LOCAL hwnd:HWND
        mov   wc.cbSize,SIZEOF WNDCLASSEX
        mov   wc.style, CS_HREDRAW or CS_VREDRAW
        mov   wc.lpfnWndProc, OFFSET WndProc
        mov   wc.cbClsExtra,NULL
        mov   wc.cbWndExtra,NULL
        push  hInstance
        pop   wc.hInstance
        mov   wc.hbrBackground,COLOR_WINDOW+1
        mov   wc.lpszMenuName,NULL
        mov   wc.lpszClassName,OFFSET ClassName
        invoke LoadIcon,NULL,IDI_APPLICATION
        mov   wc.hIcon,eax
        mov   wc.hIconSm,eax
        invoke LoadCursor,NULL,IDC_ARROW
        mov   wc.hCursor,eax
        invoke RegisterClassEx, addr wc
        INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
           WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
           CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
           hInst,NULL
        mov   hwnd,eax
        invoke ShowWindow, hwnd,SW_SHOWNORMAL
        invoke UpdateWindow, hwnd
        .WHILE TRUE
                invoke GetMessage, ADDR msg,NULL,0,0
                .BREAK .IF (!eax)
                invoke TranslateMessage, ADDR msg
                invoke DispatchMessage, ADDR msg
        .ENDW
        mov     eax,msg.wParam
        ret
WinMain endp

WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
LOCAL        hdc:HDC
LOCAL        ps:PAINTSTRUCT
LOCAL        fChange:BOOL
LOCAL        syst:SYSTEMTIME
        .IF        uMsg==WM_CREATE
                invoke         SetTimer,hWnd,ID_TIMER,1000,NULL
                invoke         GetLocalTime,ADDR stPrevious
        .ELSEIF uMsg==WM_SIZE
                mov        eax,lParam
                mov        ecx,eax
                and        ecx,0ffffh
                mov        cxClient,ecx
                shr        eax,10h
                mov        cyClient,eax
        .ELSEIF uMsg==WM_PAINT
                invoke        BeginPaint,hWnd,ADDR ps
                mov        hdc,eax
                invoke        SetIsotropic,hdc, cxClient, cyClient
                invoke        DrawClock,hdc
                invoke        DrawHands,hdc,addr stPrevious,TRUE
                invoke        EndPaint,hWnd,ADDR ps
        .ELSEIF uMsg==WM_DESTROY
                invoke         KillTimer,hWnd,ID_TIMER
                invoke         PostQuitMessage,NULL
        .ELSEIF        uMsg==WM_TIMER
                invoke        GetLocalTime,addr syst
                mov        ax,syst.wHour
                mov        bx,syst.wMinute
                .if        ax != stPrevious.wHour || bx != stPrevious.wMinute
                        mov        fChange,TRUE
                .else
                        mov        fChange,FALSE
                .endif
                invoke        GetDC,hWnd
                mov        hdc,eax
                invoke        SetIsotropic,hdc,cxClient,cyClient
                invoke        GetStockObject,WHITE_PEN
                invoke        SelectObject,hdc,eax
                invoke        DrawHands,hdc,addr stPrevious,fChange
                invoke        GetStockObject,BLACK_PEN
                invoke        SelectObject,hdc,eax
                invoke        DrawHands,hdc,addr syst,TRUE
                invoke        ReleaseDC,hWnd,hdc

                mov        ecx,sizeof(SYSTEMTIME)
                lea        esi,syst
                lea        edi,stPrevious
                cld
                rep        movsw

        .ELSE
                invoke         DefWindowProc,hWnd,uMsg,wParam,lParam               
                ret
        .ENDIF
        xor eax,eax
        ret
WndProc endp

;-----------------------------------------------
; SetIsotropic
;-----------------------------------------------
SetIsotropic        proc uses ebx edx        _hdc:HDC, _cxClient:DWORD, _cyClient:DWORD  
        invoke        SetMapMode, _hdc, MM_ISOTROPIC
        invoke        SetWindowExtEx, _hdc, 1000, 1000, NULL
        mov        ebx, _cxClient
        sar        ebx, 1
        mov        edx, _cyClient
        sar        edx, 1
        neg        edx
        invoke        SetViewportExtEx, _hdc, ebx, edx, NULL
        neg        edx
        invoke        SetViewportOrgEx, _hdc, ebx, edx, NULL
        ret
SetIsotropic        endp
;-----------------------------------------------
; DrawClock
;-----------------------------------------------
DrawClock proc _hdc:DWORD
        LOCAL pt0:POINT
        LOCAL pt1:POINT

        xor        esi,esi
        .WHILE        esi<360
                mov        pt0.x,0
                mov        pt0.y,900
                invoke        RotatePoint,addr pt0, 1, esi
                mov        eax,esi
                cdq
                mov        ebx,5
                div        ebx
                .IF edx==0
                        mov        eax,100
                .ELSE
                        mov        eax,33
                .ENDIF
                mov        ebx,eax
                sar        eax,1

                mov        edx,pt0.x
                sub        edx,eax
                mov        pt0.x,edx
                add        edx,ebx
                mov        pt1.x,edx

                mov        edx,pt0.y
                sub        edx,eax
                mov        pt0.y,edx
                add        edx,ebx
                mov        pt1.y,edx

                invoke        GetStockObject,BLACK_BRUSH
                invoke        SelectObject,_hdc,eax
                invoke        Ellipse, _hdc, pt0.x, pt0.y, pt1.x, pt1.y
                add        esi,6
        .ENDW
        ret
DrawClock endp
;-----------------------------------------------
; RotatePoint
; ptTemp.x = (int) (pt[i].x * cos (TWOPI * iAngle / 360) +
;           pt[i].y * sin (TWOPI * iAngle / 360))
; ptTemp.y = (int) (pt[i].y * cos (TWOPI * iAngle / 360) -
;           pt[i].x * sin (TWOPI * iAngle / 360))
;-----------------------------------------------
RotatePoint proc uses ebx eax ecx edx  _pt:PTR POINT,_iNum:DWORD,_iAngle:DWORD
        LOCAL        ptTemp:POINT
        LOCAL        i_180:WORD

        mov        ebx,_pt
        mov        i_180,180
        xor        eax,eax
        xor        ecx,ecx
        .WHILE        ecx<_iNum
                finit
                fldpi
                fimul        _iAngle
                fidiv        word ptr i_180
                fcos
                assume        ebx:PTR POINT
                fimul        [ebx+eax].x                ;--- 第一部分运算完成
                fldpi
                fimul        _iAngle
                fidiv        word ptr i_180
                fsin
                fimul        [ebx+eax].y                ;--- 第二部分运算完成
                fadd                        ;--- 两个部分相加
                fist        ptTemp.x        ;--- 保存计算出的X坐标
                finit
                fldpi
                fimul        _iAngle
                fidiv        word ptr i_180
                fcos
                fimul        [ebx+eax].y
                fldpi
                fimul        _iAngle
                fidiv        word ptr i_180
                fsin
                fimul        [ebx+eax].x
                fsub
                fist        ptTemp.y
                mov        edx,ptTemp.x
                mov        [ebx+eax].x,edx        ;--- 修改传入的引用
                mov        edx,ptTemp.y
                mov        [ebx+eax].y,edx
               
                add         eax,sizeof(POINT)        ;指向下一个结构
                inc        ecx        ;计数器加1
        .ENDW
                assume        ebx:nothing
        ret
RotatePoint endp
DrawHands        proc        _hdc:HDC,_pst:PTR SYSTEMTIME,_fChange:BOOL
        LOCAL        _iAngle[3]:DWORD
        LOCAL        _ptTemp[15]:POINT

        mov        ebx,_pst
        assume        ebx:PTR SYSTEMTIME
        movzx        eax,[ebx].wHour
        mov        ecx,30                ;每小时差30度,所以乘上30,再模360度.
        mul        ecx
        cdq
        mov        ecx,360
        div        ecx        ;edx==(_pst->wHour*30)%360
        movzx        eax,[ebx].wMinute
        shr        eax,1
        add        eax,edx
        mov        _iAngle,eax
        movzx        eax,[ebx].wMinute
        mov        ecx,6                ;每分每秒差6度
        mul        ecx
        mov        _iAngle+sizeof(DWORD),eax
        movzx        eax,[ebx].wSecond
        mul        ecx
        mov        _iAngle+sizeof(DWORD)*2,eax
        assume        ebx:nothing

        mov        ecx,(sizeof(POINT)*15)
        shr        ecx,1
        lea        esi,pt
        lea        edi,_ptTemp
        cld
        rep        movsw

        .IF _fChange==TRUE
                mov        esi,0
        .ELSEIF
                mov        esi,2
        .ENDIF
        .WHILE        esi<3
                mov        eax,esi
                mov        ebx,(sizeof(POINT)*5)
                mul        ebx        ;eax==esi*sizeof(POINT)
                lea        ebx,_ptTemp
                add        eax,ebx
                mov        ecx,eax        ;-----------

                mov        eax,esi
                mov        ebx,sizeof(DWORD)
                mul        ebx               
                lea        ebx,_iAngle
                add        eax,ebx
                mov        eax,[eax]        ;eax旋转的角度
                                        ;ecxPOINT指针
               
                invoke        RotatePoint,ecx,5,eax
                mov        eax,esi
                mov        ebx,(sizeof(POINT)*5)
                mul        ebx        ;eax==esi*sizeof(POINT)
                lea        ebx,_ptTemp
                add        eax,ebx                ;修正eax指向point的指针
                invoke        Polyline,_hdc,eax,5
                inc        esi
        .ENDW
        ret
DrawHands        endp
;===============================================
end start
PYG19周年生日快乐!

该用户从未签到

发表于 2006-8-27 09:50:05 | 显示全部楼层
不错!!值得学习
PYG19周年生日快乐!

该用户从未签到

发表于 2006-8-27 12:38:53 | 显示全部楼层
顶一下。。。。。
PYG19周年生日快乐!
您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

快速回复 返回顶部 返回列表