+ -
当前位置:首页 → 问答吧 → 汇编写的一个6KB的小时钟《源码》

汇编写的一个6KB的小时钟《源码》

时间:2011-08-02

来源:互联网

Assembly code


.386
.model    flat,stdcall
option    casemap:none

include        windows.inc
include        gdi32.inc
includelib    gdi32.lib
include        user32.inc
includelib    user32.lib
include        kernel32.inc
includelib    kernel32.lib

IDC_MAIN    equ    1000h
ID_TIMER    equ    1

.data?

hInstance    dd    ?        ;实例句柄
hWinMain    dd    ?        ;窗口句柄

dwCenterX    dd    ?        ;圆心X
dwCenterY    dd    ?        ;圆心Y
dwRadius    dd    ?        ;半径

.const

szClass        db    'Clock',0
szWindow    db    'Clock',0
szText        db    '测试HDC函数',0

dwPara180    dw    180

.code

_GetCenterProc    proc
    LOCAL    @stRect:RECT
    
    invoke    GetClientRect,hWinMain,addr @stRect
    
    mov    eax,@stRect.right
    sub    eax,@stRect.left            ;宽度
    
    mov    ecx,@stRect.bottom
    sub    ecx,@stRect.top                ;高度
    
    .if    ecx > eax
        mov    edx,eax
        sub    ecx,eax
        shr    ecx,1                ;逻辑右移补0
        mov    dwCenterX,0
        mov    dwCenterY,ecx
    .else
        mov    edx,ecx
        sub    eax,ecx
        shr    eax,1
        mov    dwCenterX,eax
        mov    dwCenterY,0
    .endif
    
    shr    edx,1
    add    dwCenterX,edx
    add    dwCenterY,edx
    mov    dwRadius,edx

    ret

_GetCenterProc endp

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>.
;计算时钟圆周上某个角度对应的X坐标
;x = 圆心X + Sin(角度) * 半径
_CalcX    proc    _dwDegree,_dwRadius
    
    LOCAL    @dwReturn
    
    fild    dwCenterX
    fild    _dwDegree
    fldpi
    fmul                        ;角度*pi
    
    fild    dwPara180
    fdivp    st(1),st                ;角度*pi/180
    fsin                        ;Sin(角度*pi/180)
    fild    _dwRadius
    fmul                        ;半径*sin(角度*pi/180)
    fadd                        ;X+半径*sin(角度*pi/180)
    fistp    @dwReturn
    mov    eax,@dwReturn

    ret

_CalcX endp

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>.
;计算时钟圆周上某个角度对应的Y坐标
;Y = 圆心Y + Sin(角度) * 半径
_CalcY    proc    _dwDegree,_dwRadius
    
    LOCAL    @dwReturn
    
    fild    dwCenterY
    fild    _dwDegree
    fldpi
    fmul
    fild    dwPara180
    fdivp    st(1),st
    fcos
    fild    _dwRadius
    fmul
    fsubp    st(1),st
    fistp    @dwReturn
    mov    eax,@dwReturn
    ret

_CalcY endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;按照_dwDegreeInc的步进角度,画_dwRadius为半径的小圆点

_DrawDot    proc    _hDC,_dwDegreeInc,_dwRadius
    LOCAL    @dwNowDegree,@dwR
    LOCAL    @dwX,@dwY
    
    mov    @dwNowDegree,0
    mov    eax,dwRadius
    sub    eax,10
    mov    @dwR,eax
    .while    @dwNowDegree <= 360
        finit
    ;计算圆点的圆心坐标
        invoke    _CalcX,@dwNowDegree,@dwR
        mov    @dwX,eax
        invoke    _CalcY,@dwNowDegree,@dwR
        mov    @dwY,eax
        
        mov    eax,@dwX    ;画点
        mov    ebx,eax
        mov     ecx,@dwY
        mov    edx,ecx
        sub    eax,_dwRadius
        add    ebx,_dwRadius
        sub    ecx,_dwRadius
        add    edx,_dwRadius
        
        invoke    Ellipse,_hDC,eax,ecx,ebx,edx
        
        mov    eax,_dwDegreeInc
        add    @dwNowDegree,eax
    .endw
    
    ret
_DrawDot    endp

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;画_dwDegree角度的线条,半径 = 时钟半径 - 参数 dwRadiusAdjust

_DrawLine    proc    _hDC,_dwDegree,_dwRadiusAdjust
    
        LOCAL    @dwR
        LOCAL    @dwX1,@dwY1,@dwX2,@dwY2
        
        mov    eax,dwRadius
        sub    eax,_dwRadiusAdjust
        mov    @dwR,eax
    ;计算线条两端的坐标
        invoke    _CalcX,_dwDegree,@dwR
        mov    @dwX1,eax
        invoke    _CalcY,_dwDegree,@dwR
        mov    @dwY1,eax
        add    _dwDegree,180
        invoke    _CalcX,_dwDegree,10
        mov    @dwX2,eax
        invoke    _CalcY,_dwDegree,10
        mov    @dwY2,eax
        invoke    MoveToEx,_hDC,@dwX1,@dwY1,NULL
        invoke    LineTo,_hDC,@dwX2,@dwY2
    ret

_DrawLine endp

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>..
_ShowTime    proc    _hWnd,_hDC
    
    LOCAL    @stTime:SYSTEMTIME
    
    pushad
    invoke    GetLocalTime,addr @stTime
    invoke    _GetCenterProc
    
;画时钟圆周上的点
    invoke    GetStockObject,BLACK_BRUSH
    invoke    SelectObject,_hDC,eax
    invoke    _DrawDot,_hDC,360/12,3        ;画12个大圆点
    invoke    _DrawDot,_hDC,360/60,1        ;画60个小圆点
;画时钟指针
    invoke    CreatePen,PS_SOLID,1,0
    invoke    SelectObject,_hDC,eax
    invoke    DeleteObject,eax
    movzx    eax,@stTime.wSecond
    mov    ecx,360/60
    mul    ecx                ;秒针度数 = 秒 * 360/60
    invoke    _DrawLine,_hDC,eax,15
    invoke    CreatePen,PS_SOLID,2,0
    invoke    SelectObject,_hDC,eax
    invoke    DeleteObject,eax
    movzx    eax,@stTime.wMinute
    mov    ecx,360/60
    mul    ecx                ;分针度数 = 分 * 360/60
    invoke    _DrawLine,_hDC,eax,20
    invoke    CreatePen,PS_SOLID,3,0
    invoke    SelectObject,_hDC,eax
    invoke    DeleteObject,eax
    movzx    eax,@stTime.wHour
    .if    eax >= 12
        sub    eax,12
    .endif
    mov    ecx,360/12
    mul    ecx
    movzx    ecx,@stTime.wMinute
    shr    ecx,1
    add    eax,ecx
    invoke    _DrawLine,_hDC,eax,30
    invoke    GetStockObject,NULL_PEN
    invoke    SelectObject,_hDC,eax
    invoke    DeleteObject,eax
    popad
    ret

_ShowTime endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>


_WinProc    proc    USES ebx edi esi,hWnd,uMsg,wParam,lParam
    LOCAL    @stPain:PAINTSTRUCT

    mov    eax,uMsg
    .if    eax == WM_TIMER
        invoke    InvalidateRect,hWnd,NULL,TRUE
    .elseif    eax == WM_PAINT
        invoke    BeginPaint,hWinMain,addr @stPain
        invoke    _ShowTime,hWnd,eax
        ;invoke    GetClientRect,hWinMain,addr @stRect
        ;invoke    DrawText,@hDC,offset szText,-1,addr @stRect,DT_CENTER or DT_SINGLELINE or DT_VCENTER
        
        invoke    EndPaint,hWinMain,addr @stPain
        
    .elseif    eax == WM_CREATE
    
        invoke    SetTimer,hWnd,ID_TIMER,1000,NULL
        
    .elseif    eax == WM_CLOSE
    
        invoke    KillTimer,hWnd,ID_TIMER    
        invoke    PostQuitMessage,NULL
        invoke    DestroyWindow,hWinMain
        
    .else    
        invoke    DefWindowProc,hWnd,uMsg,wParam,lParam
        ret
    .endif
    
    xor    eax,eax
    ret

_WinProc endp

_WinMain    proc
    LOCAL    @stWnd:WNDCLASSEX
    LOCAL    @stMsg:MSG
    
    invoke    GetModuleHandle,NULL                                    ;窗口实例句柄
    mov    hInstance,eax
    
    invoke    RtlZeroMemory,addr @stWnd,sizeof @stWnd                            ;在窗口结构初始填充0
    invoke    LoadIcon,NULL,IDC_MAIN                                    ;加载图标
    mov    @stWnd.hIcon,eax
    invoke    LoadCursor,NULL,IDC_ARROW                                ;加载光标
    mov    @stWnd.hCursor,eax
    mov    @stWnd.cbSize,sizeof WNDCLASSEX                                ;窗口结构大小
    mov    @stWnd.style,CS_HREDRAW or CS_VREDRAW                            ;窗口类型
    mov    @stWnd.lpfnWndProc,offset _WinProc                            ;窗口回调函数
    push    hInstance
    pop    @stWnd.hInstance
    mov    @stWnd.hbrBackground,COLOR_WINDOW + 1                            ;窗口背景色
    mov    @stWnd.lpszClassName,offset szClass                            ;窗口类名
    
    invoke    RegisterClassEx,addr @stWnd                                ;注册窗口
    invoke    CreateWindowEx,WS_EX_CLIENTEDGE,offset szClass,offset szWindow,WS_OVERLAPPEDWINDOW,\    
                100,100,250,270,NULL,NULL,hInstance,NULL                ;创建窗口
    mov    hWinMain,eax
    invoke    ShowWindow,hWinMain,SW_SHOWNORMAL                            ;显示窗口
    invoke    UpdateWindow,hWinMain                                    ;更新窗口
    
    .while    TRUE                                            ;窗口消息循环
        invoke    GetMessage,addr @stMsg,NULL,NULL,NULL
        .break    .if    eax == 0
        
        invoke    TranslateMessage,addr @stMsg
        invoke    DispatchMessage,addr @stMsg
    .endw    
    
    ret

_WinMain endp

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
    call    _WinMain
    invoke    ExitProcess,NULL

end start


作者: MyLiveIsLost   发布时间: 2011-08-02

???

作者: jiangquan384414031   发布时间: 2011-08-02

楼主这个程序是书上的吗?还是自己写的?

作者: haojiahuo50401   发布时间: 2011-08-02