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

📄 digclock.asm

📁 汇编时钟能实现时钟日历
💻 ASM
字号:
;-----------------------------------------
;   Digclock.asm -- Digital Clock Demo
;   based on Charles Petzold's DIGCLOCK.C
;   Translated into assembly 22/4/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
 DISPLAYTIME  PROTO     STDCALL :DWORD, :BOOL, :BOOL

.DATA

    ID_TIMER  EQU       1

   CLASSNAME  DB        "SIMPLEWINCLASS",0
     APPNAME  DB        "DIGITAL CLOCK",0

hBrushRed	HBRUSH	?
fSuppress	BOOL	?	
f24Hour		BOOL	?

    CXCLIENT  DD        ?
    CYCLIENT  DD        ?
   CXC_OVER2  DD        ?
   CYC_OVER2  DD        ?

    SZBUFFER  DB        2 DUP (?),0 ; Zero terminated buffer

; Bits define which of the 7 LED segments is illuminated (ordered top to bottom & left to right)
; On each byte, bit 6 is for Segment 1, bit 5 for segment 2, to bit 0 for segment 7
  
       SEGMT  DB        01110111B,00010010B,01011101B,01011011B,00111010B
;                           0         1         2         3         4         
              DB        01101011B,01101111B,01010010B,01111111B,01111011B
;                           5         6         7         8         9     ; 10 digit values 

; Set coordinates of a 6 sided polygons used to illuminate segments of the LED display 
		
ptSegment	POINT	{7,6},{11,2},{31,2},{35,6},{31,10},{11,10}	; 1st LED segment Top
		POINT	{6,7},{10,11},{10,31},{6,35},{2,31},{2,11}	; 2nd	          TLeft
		POINT	{36,7},{40,11},{40,31},{36,35},{32,31},{32,11}	; 3rd		  TRight
		POINT	{7,36},{11,32},{31,32},{35,36},{31,40},{11,40}	; 4th		  Middle
		POINT	{6,37},{10,41},{10,61},{6,65},{2,61},{2,41}	; 5th		  BLeft
		POINT	{36,37},{40,41},{40,61},{36,65},{32,61},{32,41}	; 6th		  BRight
		POINT	{7,66},{11,62},{31,62},{35,66},{31,70},{11,70}  ; 7th 		  Bottom

ptColon		POINT	{2,21},{6,17},{10,21},{6,25}	; Coords of 4 sided polygon; 1st colon  
		POINT	{2,51},{6,47},{10,51},{6,55}	; Ditto 2nd colon
	
.DATA?
hInstance HINSTANCE ?
CommandLine LPSTR ?
;---------------------------------------------------------------------------
      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

     WNDPROC  PROC      USES EBX ESI EDI, HWND:HWND, UMSG:UINT, WPARAM:WPARAM, LPARAM:LPARAM

              LOCAL     HDC:HDC
              LOCAL     PS:PAINTSTRUCT
	  		
              MOV       EAX,UMSG

.IF           EAX==WM_CREATE

              RGB       255,0,0     ; Set the colour
              INVOKE    CREATESOLIDBRUSH, EAX
              MOV       HBRUSHRED,EAX
              INVOKE    SETTIMER, HWND, ID_TIMER, 1000, NULL            ;

              JMP       FALLTH      ; Fall through for this message

.ELSEIF       EAX==WM_SETTINGCHANGE

     FALLTH:  INVOKE    GETLOCALEINFO, LOCALE_USER_DEFAULT, LOCALE_ITIME, ADDR SZBUFFER, 2

.IF           SZBUFFER[0]=="1"
              MOV       F24HOUR,TRUE
.ELSE
              MOV       F24HOUR,FALSE
.ENDIF

              INVOKE    GETLOCALEINFO, LOCALE_USER_DEFAULT, LOCALE_ILZERO, ADDR SZBUFFER, 2
	 
.IF           SZBUFFER[0]=="0"
              MOV       FSUPPRESS,TRUE
.ELSE
              MOV       FSUPPRESS,FALSE
.ENDIF

              INVOKE    INVALIDATERECT, HWND, NULL, TRUE


.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    INVALIDATERECT, HWND, NULL, TRUE
 						
.ELSEIF       EAX==WM_PAINT

              INVOKE    BEGINPAINT, HWND, ADDR PS

              MOV       HDC,EAX     ; Get handle to device context before selecting GDI object into it

              INVOKE    SETMAPMODE, HDC, MM_ISOTROPIC
              INVOKE    SETWINDOWEXTEX, HDC, 276, 72, NULL  ;Set horizontal and vertical extents
							;  (6*42 + 2*12), height is 72

              INVOKE    SETVIEWPORTEXTEX, HDC, CXCLIENT, CYCLIENT, NULL ;Set viewport extents

              INVOKE    SETWINDOWORGEX, HDC, 138, 36, NULL  ;Set coordinates of new viewport
							; to the centre of the window extents

              INVOKE    SETVIEWPORTORGEX, HDC, CXC_OVER2, CYC_OVER2, NULL           ;Set viewport origin
              INVOKE    GETSTOCKOBJECT, NULL_PEN
              INVOKE    SELECTOBJECT, HDC, EAX
              INVOKE    SELECTOBJECT, HDC, HBRUSHRED

              INVOKE    DISPLAYTIME, HDC, F24HOUR, FSUPPRESS            ; *** This makes the LED display ***
	   
              INVOKE    ENDPAINT, HWND, ADDR PS

.ELSEIF       EAX==WM_DESTROY

              INVOKE    KILLTIMER, HWND, ID_TIMER
              INVOKE    DELETEOBJECT, HBRUSHRED
              INVOKE    POSTQUITMESSAGE,NULL

.ELSE

              INVOKE    DEFWINDOWPROC, HWND, UMSG, WPARAM, LPARAM
              RET

.ENDIF
              XOR       EAX,EAX
              RET

     WNDPROC  ENDP

            DISPLAYDIGIT  PROC      USES EBX ESI EDI, HDC:DWORD, INUMBER:WORD

              LOCAL     BIT:BYTE
	
              MOV       BIT,01000000B           ; Use to test segment mask
              MOV       EBX,0       ; Index to sets of Segment coordinates
              MOV       SI,0        ; Index to segment
              MOV       EDI,0
              MOV       DI,INUMBER  ; Get the Digit index (0 - 9)

.WHILE        SI < 7

              MOV       CL,BIT      ; Do this as Windows destroys cx
              TEST      SEGMT[DI],CL            ; If mask bit not set, LED segment is OFF
              JZ        SKIP
 	
              INVOKE    POLYGON, HDC, ADDR PTSEGMENT[EBX], 6            ; Draw segment as 6 sided polygon
	  
       SKIP:  SHR       BIT,1       ; Prepare to test next LED segment
              ADD       BX,8*6      ; Bump index to next segment
					; 8 bytes/(coord pair) and six sides/segment 
              INC       SI

.ENDW

              RET
            DISPLAYDIGIT  ENDP

        DISPLAYTWODIGITS  PROC      HDC:DWORD, INUMBER:WORD, FSUPPR:BOOL

              MOV       EAX,0       ; Calculate the 10's decade
              MOV       AX,INUMBER
              MOV       ECX,10
              MOV       EDX,0
              DIV       ECX         ; eax = iNumber/10
	
.IF           (! FSUPPR || AX !=0)
              INVOKE    DISPLAYDIGIT, HDC, AX
.ENDIF

              INVOKE    OFFSETWINDOWORGEX, HDC, -42, 0, NULL            ; Negative as we work from the centre
							; & digits are 42 units wide

              MOV       EAX,0       ; Now get the units
              MOV       AX,INUMBER
              MOV       ECX,10
              MOV       EDX,0
              DIV       ECX         ; edx = modulus of iNumber/10

              INVOKE    DISPLAYDIGIT, HDC, DX
              INVOKE    OFFSETWINDOWORGEX, HDC, -42, 0, NULL
 
              RET
        DISPLAYTWODIGITS  ENDP

            DISPLAYCOLON  PROC      HDC:HDC

              INVOKE    POLYGON, HDC, ADDR PTCOLON[0],4     ; 1st Colon
              INVOKE    POLYGON, HDC, ADDR PTCOLON[8*4],4   ; 2nd Colon

              INVOKE    OFFSETWINDOWORGEX, HDC, -12, 0, NULL            ; Colons are 12 units wide & again
							; we work from the centre
              RET
            DISPLAYCOLON  ENDP

 DISPLAYTIME  PROC      HDC:HDC, F24HR:BOOL, FSUPPR:BOOL

              LOCAL     SYST:SYSTEMTIME

              INVOKE    GETLOCALTIME, ADDR SYST

.IF           F24HR

              INVOKE    DISPLAYTWODIGITS, HDC, SYST.WHOUR, FSUPPRESS

.ELSE

              MOV       AX,SYST.WHOUR
              MOV       ECX,12
              MOV       EDX,0
              DIV       CX          ; Get modulus in dx
	  		
.IF           EDX==12
              MOV       AX, SYST.WHOUR
.ELSE
              MOV       AX,12
.ENDIF
 
              INVOKE    DISPLAYTWODIGITS, HDC, AX, FSUPPR   ; Hour

.ENDIF

              INVOKE    DISPLAYCOLON, HDC
              INVOKE    DISPLAYTWODIGITS, HDC, SYST.WMINUTE, FALSE      ; Minute
              INVOKE    DISPLAYCOLON, HDC
              INVOKE    DISPLAYTWODIGITS, HDC, SYST.WSECOND, FALSE      ; Seconds

              RET
 DISPLAYTIME  ENDP

              END       START

⌨️ 快捷键说明

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