⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 clock.asm

📁 用汇编语言编写时钟程序
💻 ASM
字号:
;-----------------------------------------
;   Clock.asm -- Analogue Clock Demo
;   based on Charles Petzold's DIGCLOCK.C
;   Translated into assembly 20/9/99 by
;   Ron Thomas Ron_Thom@Compuserve.com	
;-----------------------------------------

.386				; 32 bit when .386 appears before .MODEL
.MODEL FLAT,STDCALL

include windows.inc

include user32.inc
include kernel32.inc
include gdi32.inc

includelib user32.lib
includelib kernel32.lib
includelib gdi32.lib

WinMain		PROTO :DWORD, :DWORD, :DWORD, :SDWORD

.data

ID_TIMER EQU 1

ClassName db "SimpleWinClass",0
AppName   db "Analogue Clock",0

fChange		BOOL	?	


cxClient	dd 	?
cyClient	dd 	?
cxC_over2	dd	?
cyC_over2	dd	?

theta		real4	?	; Required rotation in degrees
math_X_Coord	real4	?	; Math space coords
math_Y_Coord	real4	?	; 
New_X1		real4	?
New_Y1		real4	?

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 ?

stPrevious	SYSTEMTIME <>	; Previous time data
stCurrent	SYSTEMTIME <>	; Current 	" 

;---------------------------------------------------------------------------
LOWORD	MACRO bigword		;; Retrieves the low word from double word argument

	mov	eax,bigword
	and	eax,0FFFFh	;; Get low word 
	ENDM

HIWORD	MACRO bigword  		;; Retrieves the high word from double word 

	mov	ebx,bigword
	shr	ebx,16		;; Shift 16 for high word to set to high word
				
	ENDM

RGB	MACRO red, green, blue	;; Get composite number from red green and blue bytes 

	mov	al,blue			;; ,,,blue	
	shl	eax,8			;; ,,blue,

	add	al,green		;; ,,blue,green
	shl	eax,8			;; ,blue,green,
	add	al,red			;; ,blue,green,red
	and	eax,0FFFFFFh		;; Mask out top byte to complete COLORREF dword 

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

WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:SDWORD

	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,0
        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

SetIsotropic proc hdc:HDC 

	invoke SetMapMode, hdc, MM_ISOTROPIC	; Select isotropic mapping 

;  Set window extents to 1000 and the viewport extents to 1/2 width of client area,
;  and the negative of 1/2 height of client area

	invoke SetWindowExtEx, hdc, 1000, 1000, NULL
	mov	eax,cyC_over2
	neg	eax			; Get -cyClient/2
	invoke SetViewportExtEx, hdc, cxC_over2, eax ,NULL
	invoke SetViewportOrgEx, hdc, cxC_over2, cyC_over2, NULL
	
	ret
SetIsotropic endp


DrawClock proc hdc:HDC

LOCAL   iAngle:DWORD, pt4[3]:POINT

	mov	iAngle,0

	.WHILE	iAngle < 360

	mov	pt4[0].x,0
	mov	pt4[0].y,900

	fild	pt4[0*8].x
	fstp	math_X_Coord
	
	fild	pt4[0*8].y
	fstp	math_Y_Coord

	fild	iAngle
	fstp	theta

	mov	esi,offset theta	; Point at parameter block

	call	rotate			; Rotate the 5-minute or minute marks

	fld	New_X1			; Get new X coord
	fistp	pt4[0*8].x		; Store in structure

	fld	New_Y1			; Ditto for Y coord
	fistp	pt4[0*8].y		; 

	mov	eax,iAngle
	mov	ecx,5
	mov	edx,0
	div	ecx			; Get the remainder in dx

	.IF edx
	    mov pt4[2*8].x,33		; if edx is true its a minute mark (small circle)
	    mov pt4[2*8].y,33
	.ELSEIF
	    mov pt4[2*8].x,100		; if its false its a 5-minute mark (larger circle)
	    mov pt4[2*8].y,100	
	.ENDIF

	mov	eax,pt4[2*8].x
	shr	eax,1			; (pt[2].x)/2
	sub	pt4[0].x,eax
	
	mov	eax,pt4[2*8].y
	shr	eax,1			; (pt[2].y)/2
	sub	pt4[0].y,eax

	mov	eax,pt4[0].x
	add	eax,pt4[2*8].x
	mov	pt4[1*8].x,eax

	mov	eax,pt4[0].y
	add	eax,pt4[2*8].y
	mov	pt4[1*8].y,eax

	invoke	GetStockObject, BLACK_BRUSH
	invoke  SelectObject, hdc, eax

	invoke Ellipse, hdc, pt4[0].x, pt4[0].y, pt4[1*8].x, pt4[1*8].y	

	add	iAngle,6

	.ENDW	

	ret
DrawClock endp  

			
DrawHands proc	hdc:HDC, pst:DWORD, Change:BOOL	; pst points @ current or previous TIME data

LOCAL iAngle[3]:DWORD, ptTemp[15]:POINT	; Provide space for copy of polyline points 

;	This routine is entered twice, once to erase the old hand position and then
;	a second time it uses the new time data to update the hand positions.   
 
;	Convert time data (hour, min and sec) into angles for the three hands
 		
	mov	ebx,pst			; Get address of current or previous SYSTEMTIME

	mov	ax,[ebx+8]		; Get hours
	mov	edx,0
	mov	cx,30			; Scaling factor for 360 degrees
	mul	cx
	mov	cx,360
	div	cx			; mod 360 divide; get hours-remainder in edx
	mov	cx,[ebx+10]		; Get minute value
	shr	cx,1			;
	add	dx,cx			; Add on angle for fractional part of the hour
	mov	iAngle[0],edx		; Now have hour-hand angle

	mov	ax,[ebx+10]		; Get minutes again
	mov	edx,0
	mov	cx,6			; Scale factor for minute-hand angle
	mul	cx
	mov	iAngle[4],eax		; Got minute-hand angle

	mov	ax,[ebx+12]		; Get seconds
	mov	edx,0
	mov	cx,6			; Scale factor for second-hand angle
	mul	cx
	mov	iAngle[8],eax		; Got second-hand angle	

;	Copy polyline data to temp storage

	mov	esi,offset pt		; es and ds point to same segment 
	lea	edi,ptTemp
	mov	ecx,sizeof pt
	cld
	rep	movsb			; Copy polyline points to ptTemp

	.IF Change
	mov     esi,0			; If hour or minute hands have changed position
	mov	ebx,0
	.ELSE
	mov     esi,2*4			; If second hand only has changed 
	mov	ebx,2*40 
	.ENDIF

.WHILE  ebx < 3*40

	mov	edi,0			; Index to point

    .WHILE      edi < 40		; Loop for all points in the structure

	push	edi
	add	edi,ebx			; Add offset for the appropriate hand			

	fild	iAngle[esi]		; Load data into the rotate parameter block				
	fstp	theta			;
	fild	ptTemp[edi].x		;
	fstp	math_X_Coord		;
	fild	ptTemp[edi].y		;
	fstp	math_Y_Coord		;

	push	esi
	mov	esi,offset theta	; Point at parameter block

	call   rotate			; Rotate the point
	pop	esi

	fld	New_X1			; Get new X coord
	fistp	ptTemp[edi].x		; Store in hands structure

	fld	New_Y1			; Ditto for Y coord
	fistp	ptTemp[edi].y		;
 
	pop	edi
	add	edi,8

    .ENDW

	invoke Polyline, hdc,ADDR ptTemp[ebx],5 ; Draw the hand
 
	add	ebx,40				; Inc to next hand
	add	esi,4				; Inc index for angle of next hand

.ENDW
	
	ret
DrawHands endp


WndProc proc uses ebx esi edi, hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM

        LOCAL  hdc:HDC, ps:PAINTSTRUCT 
	  		
	mov    eax,uMsg

	.IF	eax==WM_CREATE

	  finit				; Initialise the coprocessor
	
	  invoke   SetTimer, hWnd, ID_TIMER, 1000, NULL	;
	  invoke   GetLocalTime, ADDR stCurrent

	.ELSEIF eax==WM_SIZE		; lParam gives new window size 

	  LOWORD	lParam		; Get low word from lParam in eax
	  mov	cxClient,eax
	  shr	eax,1
	  mov	cxC_over2,eax		; cxClient/2

	  HIWORD	lParam		; Get high "	"	"     ebx
	  mov	cyClient,ebx
	  shr	ebx,1
	  mov	cyC_over2,ebx		; cyClient/2

	.ELSEIF eax==WM_TIMER

	  invoke GetLocalTime, ADDR stCurrent

	  mov	cx,stCurrent.wHour
	  mov	dx,stCurrent.wMinute

	  .IF     cx != stPrevious.wHour
	     mov  fChange, TRUE
	  .ELSEIF dx != stPrevious.wMinute
	     mov  fChange, TRUE
	  .ELSE
	     mov  fChange, FALSE
	  .ENDIF

	  invoke GetDC, hWnd
	  mov	hdc,eax

	  invoke SetIsotropic, hdc

	  invoke GetStockObject, WHITE_PEN		; Erase hands
	  invoke SelectObject, hdc, eax 
	  invoke DrawHands, hdc, ADDR stPrevious, fChange

	  invoke GetStockObject, BLACK_PEN		; Draw hands at new position
	  invoke SelectObject, hdc, eax 
	  invoke DrawHands, hdc, ADDR stCurrent, TRUE

	  invoke ReleaseDC, hWnd, hdc

	  mov	ax,stCurrent.wHour		; Save the current time
	  mov	stPrevious.wHour,ax		;
	  mov	ax,stCurrent.wMinute		;
	  mov	stPrevious.wMinute,ax		;
	  mov	ax,stCurrent.wSecond		;
	  mov	stPrevious.wSecond,ax		;

        .ELSEIF eax==WM_PAINT

          invoke  BeginPaint, hWnd, ADDR ps

          mov	hdc,eax	 			; Get handle to device context
 
	  invoke  SetIsotropic, hdc

	  invoke  DrawClock, hdc		; Draw the dial

          invoke  EndPaint, hWnd, ADDR ps

	.ELSEIF eax==WM_DESTROY

          invoke  KillTimer, hWnd, ID_TIMER
          invoke  PostQuitMessage,NULL

        .ELSE

            invoke  DefWindowProc, hWnd, uMsg, wParam, lParam
            ret

	.ENDIF
        xor    eax,eax
	ret

WndProc endp

;---------------------------------------------------------------;
; This routine finds new values for cartesian coordinates X & Y	;
; when the point is rotated by theta degrees			;
;								;
; Enter: DS:SI points at a data block in the calling routine	;
;								;
;	  [si] (real4) contains the rotation angle in degrees	;
;	[si+4] (real4) contains the math X coordinate		;
;	[si+8] (real4) contains the math Y coordinate		;     	   
;	[si+12](real4) will contain the new X coordinate	;
;	[si+16](real4) will contain the new Y coordinate	;
;								;
; Note: I keep the orignal coords (as opposed to updating	;
;	so that a program can reuse the same values if required	;
;								; 		  														;
;	X1 =  X * cos(theta)  +  Y * sin(theta) 		;
;	Y1 = -X * sin(theta)  +  Y * cos(theta)			;
; 								;
; Return:  New coords are updated in callers parameter block.	;  
;---------------------------------------------------------------;

.DATA
deg2rad		real4	1.7453292E-2	; 2 * pi / 360 (conversion factor for radians)

.CODE

angle	equ	dword ptr [esi]
X_Coord	equ 	dword ptr [esi+4]
Y_Coord	equ	dword ptr [esi+8]
New_X	equ	dword ptr [esi+12]
New_Y	equ	dword ptr [esi+16]  

rotate	PROC	 

	fld	angle			; Put the rotation in degrees into st(0)

	fmul	deg2rad			; st=radians
	fsincos				; st=cos,   st(1)=sin

	fld	st			; st=cos,   st(1)=cos, st(2)=sin

	fmul	X_Coord			; st=X*cos, st(1)=cos, st(2)=sin

	fxch				; st=cos,   st(1)=X*cos, st(2)=sin
	fmul	Y_Coord			; st=Y*cos, st(1)=X*cos, st(2)=sin

	fxch	st(2)			; st=sin,   st(1)=X*cos, st(2)=Y*cos

	fld	st			; st=sin, st1=sin, st2=X*cos, st3=Y*cos					;now X, X, Y*sin, Y*cos, cos, sin	

	fmul	X_Coord			; X*sin, sin,   X*cos, Y*cos

	fxch				; sin,   X*sin, X*cos, Y*cos
	fmul	Y_Coord			; Y*sin, X*sin, X*cos, Y*cos
	fadd	st,st(2)		; Y*sin + X*cos, X*sin, X*cos, Y*cos

	fstp	New_X			; X*sin, X*cos, Y*cos ; Stored new X coord
 
	fxch	st(1)			; X*cos, X*sin, Y*cos
	fstp	st			; X*sin, Y*cos  
	fsub				; -X*sin +Y*cos

	fstp	New_Y			; Stored new Y coord
	
	RET

rotate	ENDP

        end start

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -