Win32 Clock Program Decompile
Win32 Clock Program Decompile

This is a comprehensive program ,using assembly language is really difficult for this program,But it well demonstrates the message loop mechanism of Windows and the relationship between assembly and C.

IDE: CLion (GCC) && MASMPlus
OS : Windows 7
Lang: ASM x86 EXE && C/CPP

Using ASM:

.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
include             masm32.inc 
includelib      masm32.lib 
includelib msvcrt.lib 
 
include macro.asm
sprintf PROTO C:DWORD, :DWORD, :VARARG
printf proto c:DWORD ,:vararg
 
.data?
hInstance       dd      ?
hWinMain        dd      ?
dwCenterX       dd      ?
dwCenterY       dd      ?
dwRadius        dd      ?
buf                 dd 100 ?
 
.const
szClassName      db      'Clock',0
_dwPara180      dw      180
.code
 
_CalcClockParam 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     eax > ecx
            mov edx,ecx
            sub eax,ecx
            shr eax,1
            mov dwCenterX,0
            mov dwCenterY,eax
        .else   
            mov edx,eax
            sub ecx,eax
            shr ecx,1
            mov dwCenterX,ecx
            mov dwCenterY,0
        .endif
            shr edx,1
            mov dwRadius,edx
            add dwCenterX,edx
            add dwCenterY,edx
                                 
        ret
 
_CalcClockParam endp
 
_CalcX      proc    _dwDegree,_dwRadius
                        LOCAL   @dwReturn
 
        fild    dwCenterX
        fild    _dwDegree
        fldpi   
        fmul
        fild    _dwPara180
        fdivp   st(1),st
        fsin
                        fild    _dwRadius
        fmul
        fadd
        fistp   @dwReturn
        mov     eax,@dwReturn
 
        ret
_CalcX          endp
 
 
_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
 
_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
 
_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    _hDC
  
        LOCAL   @stTime:SYSTEMTIME
         
        pushad
        invoke  GetLocalTime,addr @stTime
        invoke  _CalcClockParam
        invoke  GetStockObject,BLACK_BRUSH
        invoke  SelectObject,_hDC,eax
        invoke  _DrawDot,_hDC,360/12,3
        invoke  _DrawDot,_hDC,360/60,1
        invoke  CreatePen,PS_SOLID,1,0
        invoke  SelectObject,_hDC,eax
        invoke  DeleteObject,eax
        movzx   eax,@stTime.wSecond
        mov     ecx,360/60
        mul     ecx
 
        ;.if _dwDegree >30
            ;invoke sprintf ,addr buf,CTXT("%d"),eax
            ;invoke MessageBox,NULL,addr buf,addr buf,0
        ;.ENDIF
 
        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
        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
        ret
 
_ShowTime       endp
  
  
_ProcWinMain    proc    uses ebx edi esi hWnd,uMsg,wParam,lParam
        LOCAL   @stPS:PAINTSTRUCT
         
        mov     eax,uMsg
        .if     eax == WM_TIMER
            invoke InvalidateRect,hWnd,NULL,TRUE
        .elseif eax == WM_PAINT
            invoke BeginPaint,hWnd,addr @stPS
            invoke _ShowTime,eax
            invoke EndPaint,hWnd,addr @stPS
        .elseif eax == WM_CREATE
                invoke SetTimer,hWnd,1,1000,NULL
        .elseif eax == WM_CLOSE
            invoke KillTimer,hWnd,1
            invoke DestroyWindow,hWinMain
            invoke PostQuitMessage,NULL
        .else   
                invoke DefWindowProc,hWnd,uMsg,wParam,lParam
            ret
        .endif
        xor     eax,eax
        ret
_ProcWinMain    endp
 
_WinMain        proc    
  
        LOCAL   @stWndClass:WNDCLASSEX
        LOCAL   @stMsg:MSG
         
        invoke  GetModuleHandle,NULL
        mov     hInstance,eax
        invoke  RtlZeroMemory,addr @stWndClass,sizeof @stWndClass
        invoke  LoadIcon,hInstance,100
        mov     @stWndClass.hIcon,eax
        mov     @stWndClass.hIconSm,eax
        invoke  LoadCursor,0,IDC_ARROW
        mov     @stWndClass.hCursor,eax
        push    hInstance
        pop     @stWndClass.hInstance
        mov     @stWndClass.cbSize,sizeof WNDCLASSEX
        mov     @stWndClass.style,CS_HREDRAW or CS_VREDRAW
        mov     @stWndClass.lpfnWndProc,offset _ProcWinMain
        mov     @stWndClass.hbrBackground,COLOR_WINDOW +1
        mov     @stWndClass.lpszClassName,offset szClassName
        invoke  RegisterClassEx,addr @stWndClass
        invoke  CreateWindowEx,WS_EX_CLIENTEDGE,\
            offset szClassName,offset szClassName,\
            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,0,0
            .break  .if eax ==0
            invoke  TranslateMessage,addr @stMsg
           invoke  DispatchMessage,addr @stMsg 
        .endw
        ret
_WinMain        endp
 
start:
        call    _WinMain
        invoke  ExitProcess,NULL
        end start

C/CPP 的反编译与实现

#include <bits/stdc++.h>
#include "windows.h"
int dwCenterX,dwCenterY,dwRadius;
HWND hWinMain;
void CalcClockParam (){
    RECT stRect;
    GetClientRect(hWinMain,&stRect);
    int eax,ecx,edx;
    eax = stRect.right;
    eax -= stRect.left;
    ecx = stRect.bottom;
    ecx -= stRect.top;
    if(eax >ecx){
        edx = ecx;
        eax -= ecx;
        eax = eax>>1;
        dwCenterX = 0;
        dwCenterY = eax;
    }else{
        edx = eax;
        ecx -= eax;
        ecx = ecx>>1;
        dwCenterX = ecx;
        dwCenterY = 0;
    }
    edx = edx >> 1;
    dwRadius = edx;
    dwCenterX += edx;
    dwCenterY += edx;
}
int CalcX (int _dwDegree,int _dwRadius){
    double SinNum = (double)_dwDegree * 3.14 /180.0;
    return dwCenterX+(int)(sin(SinNum)*_dwRadius);
}
int CalcY (int _dwDegree,int _dwRadius){
    double CosNum = (double)_dwDegree * 3.14 /180.0;
    return dwCenterY-(int)(cos(CosNum)*_dwRadius);
}
int DrawDot(HDC _hdc,int _dwDegreeInc,int _dwRadius) {
    int dwNowDegree,dwr,dwx,dwy;
    dwNowDegree = 0;
    dwr = dwRadius - 10;
    while(dwNowDegree<=360){
        asm volatile("finit");
        dwx = CalcX(dwNowDegree,dwr);
        dwy = CalcY(dwNowDegree,dwr);
        Ellipse(_hdc,dwx-_dwRadius,dwy-_dwRadius,dwx+_dwRadius,dwy+_dwRadius);
        dwNowDegree += _dwDegreeInc;
    }
    return _dwDegreeInc;
}
int DrawLine(HDC _hdc,int _dwDegree,int _dwRadiusAdjust){
    int dwr;
    int dwx1,dwy1,dwx2,dwy2;
    dwr = dwRadius - _dwRadiusAdjust;
    dwx1 = CalcX(_dwDegree,dwr);
    dwy1 = CalcY(_dwDegree,dwr);
    _dwDegree+=180;
    dwx2 = CalcX(_dwDegree,10);
    dwy2 = CalcY(_dwDegree,10);
    MoveToEx(_hdc,dwx1,dwy1,NULL);
    return LineTo(_hdc,dwx2,dwy2);
}
int ShowTime(HWND hwnd,HDC hdc){
    SYSTEMTIME stTime;
    GetLocalTime(&stTime);
    CalcClockParam();
    SelectObject(hdc,GetStockObject(BLACK_BRUSH));
    DrawDot(hdc,360/12,3);
    DrawDot(hdc,360/60,1);
 
    DeleteObject(SelectObject(hdc,CreatePen(PS_SOLID,1,0)));
    DrawLine(hdc,stTime.wSecond*6,15);
    DeleteObject(SelectObject(hdc,CreatePen(PS_SOLID,2,0)));
    DrawLine(hdc,stTime.wMinute*6,20);
    DeleteObject(SelectObject(hdc,CreatePen(PS_SOLID,3,0)));
    if(stTime.wHour>=12){
        stTime.wHour -=12;
    }
    stTime.wHour *= 360/12;
    return DrawLine(hdc,stTime.wHour+(stTime.wMinute>>1),30);
}
 
LRESULT CALLBACK ProcWinMain(HWND hwnd,UINT umsg,WPARAM wParam,LPARAM lParam){
    PAINTSTRUCT stPS;
    if(umsg == WM_TIMER){
        InvalidateRect(hwnd,NULL,TRUE);
    }else if(umsg == WM_PAINT){
        ShowTime(hwnd,BeginPaint(hwnd,&stPS));
        EndPaint(hwnd,&stPS);
    }else if(umsg == WM_CREATE){
        SetTimer(hwnd,1,1000,NULL);
    }else if(umsg == WM_CLOSE){
        KillTimer(hwnd,1);
        DestroyWindow(hWinMain);
        PostQuitMessage(NULL);
    }else{
        return DefWindowProc(hwnd,umsg,wParam,lParam);
    }
}
 
 
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd ) {
    WNDCLASSEX stWndClass;
    MSG stMsg;
    hInstance = GetModuleHandle(NULL);
    RtlZeroMemory(&stWndClass, sizeof(stWndClass));
    stWndClass.hCursor = LoadCursor(0,IDC_ARROW);
    stWndClass.hInstance = hInstance;
    stWndClass.cbSize = sizeof(WNDCLASSEX);
    stWndClass.style = (CS_HREDRAW or CS_VREDRAW);
    stWndClass.lpfnWndProc = ProcWinMain;
    stWndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    stWndClass.lpszClassName = "Clock";
    RegisterClassEx(&stWndClass);
    hWinMain = CreateWindowEx(WS_EX_CLIENTEDGE,"Clock","Clock",WS_OVERLAPPEDWINDOW,\
    100,100,250,270,NULL,NULL,hInstance,NULL);
    ShowWindow(hWinMain,SW_SHOWNORMAL);
    UpdateWindow(hWinMain);
    while(GetMessage(&stMsg,NULL,0,0)){
        TranslateMessage(&stMsg);
        DispatchMessage(&stMsg);
    }
    return 0;
}