Win32 Clock Program Decompile
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;
}