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

📄 clock.asm

📁 该示例实现了一个计算机同步时钟
💻 ASM
📖 第 1 页 / 共 2 页
字号:
;这里是用Win32汇编写的程序
;只是在十几天内看了一些书,
;对具体的API函数的细节还并
;不熟悉,所以后面的窗口程序部分
;就直接套用了一些模板,需要继
;续深入学习。之所以选择Win32Asm
;是因为它的用途,比起DOS下汇编
;要广得多,比如可以利用Windows
;本身提供的API函数等。
;对于本身学的信息安全专业,
;汇编起到很重要的作用,机器底层
;的东西需要汇编去做;病毒,加密
;解密之类的需要用汇编去做
;看了一些加密解密的书,首先提到的
;就是要有汇编基础。这学期汇编学习
;了基础的,要想深入还需要多看书多写
;程序并且和高级语言结合起来,所以我
;们要学习要实践的还有很多。老师常说
;要提出一些问题,解决一些问题,再留
;下一些可以继续研究讨论的余地。学习
;就是这样,老师教给了我们基础的,
;继续向深处的学习就要靠我们自己了,
;每门课都留给了我们继续学习的余地,
;学习无止境。


;这个程序是在窗口中用时钟显示系统时间
;查了很多资料才找到需要的API函数的
;具体用法,写了很多注释
NAME Clock
.386
.model flat,stdcall
option casemap:none

; INCLUDE 文件定义
include\masm32\include\windows.inc
include\masm32\include\user32.inc
includelib\masm32\lib\user32.lib
include\masm32\include\kernel32.inc
includelib\masm32\lib\kernel32.lib
include\masm32\include\Gdi32.inc
includelib\masm32\lib\Gdi32.lib


; 数据段
.data?                 ;未赋初值变量
CentX      dd  ?       ;圆心X
CentY      dd  ?       ;圆心Y
Radius     dd  ?       ;半径
hInstance  dd  ?       ;注册窗口类的应用程序实例句柄
hWinMain   dd  ?

.const                 ;常量数据
szClassName  db 'Clock',0  ;窗口名
_180  dw  180          ;180代表角度

; 代码段
.code

;下面两个子程序用一些FPU指令计算某角度对应坐标

;子程序,已知半径
;计算圆周上某角度对应的X坐标,
;X = CentX + Sin(角度) *半径
_CalcX proc _X,_Degree,_Radius
    local Retr              ;局部变量,用来放弹出的坐标值
    fild  _X                ;圆心X压栈
    fild  _Radius           ;半径压栈
    fild  _Degree           ;角度压栈
    fldpi                   ;常量指令,圆周率压栈
    fild  _180              ;180度压栈
    fdivp  st(1),st         ;Pi/180
    fmul                    ;角度*Pi/180,结果压栈
    fsin                    ;Sin(角度*Pi/180),结果压栈
    fmul                    ;半径*Sin(角度*Pi/180),结果压栈
    fadd                    ;CentX+半径*Sin(角度*Pi/180),结果压栈
    fistp  Retr             ;把X坐标弹出到Retr中
    mov  eax,Retr
    ret
_CalcX  endp

;子程序,已知半径
;计算圆周上某角度对应的Y坐标,
;Y = _Y - Cos(角度) *半径
_CalcY  proc  _Y,_Degree,_Radius
    local Retr              ;局部变量,用来放弹出的坐标值
    fild  _Y                ;圆心Y压栈
    fild  _Radius           ;半径压栈
    fild  _Degree           ;角度压栈
    fldpi                   ;常量指令,圆周率压栈
    fild  _180              ;180度压栈
    fdivp  st(1),st         ;Pi/180
    fmul                    ;角度*Pi/180
    fcos                    ;Cos(角度*Pi/180)
    fmul                    ;半径*Cos(角度*Pi/180)
    fsubp st(1),st          ;CentY-半径*Cos(角度*Pi/180)
    fistp Retr              ;把Y坐标弹出到Retr中
    mov  eax,Retr
    ret
_CalcY  endp

;子程序,计算时钟的位置、大小等
_CalcClock  proc
    local   Lrect:RECT            ;局部结构变量
    invoke  GetClientRect,hWinMain,addr Lrect
            ;此函数返回指定窗口客户区矩形的大小到Lrect中
            ;取局部变量偏移地址要用addr
    mov     eax,Lrect.right
    sub     eax,Lrect.left        ;eax = 宽度
    mov     ecx,Lrect.bottom
    sub     ecx,Lrect.top         ;ecx = 高度

;比较宽度和高度,以小的值用做时钟的直径
    .if  ecx>eax
            mov  edx,eax          ;高度>宽度就以宽度作直径
            sub  ecx,eax
            shr  ecx,1
            mov  CentX,0
            mov  CentY,ecx
    .else
            mov  edx,ecx          ;高度<宽度就以高度作直径
            sub  eax,ecx
            shr  eax,1
            mov  CentX,eax
            mov  CentY,0
    .endif
            shr  edx,1
            mov  Radius,edx
            add  CentX,edx        ;得到圆心X坐标CentX
            add  CentY,edx        ;得到圆心Y坐标CentY
            ret
_CalcClock  endp



;画_Radius为半径的圆点
;本来想用画多边形的函数Polygon画五角形的点的
;但是调试了好多次都不行,
;只好改画椭圆形点(这里实际上就是圆点)
;注释掉的是开始写的五角形点
_DrawDot  proc  hDC,_DegreeInc,_Radius
            ;_DegreeInc为角度增量,_Radius为半径
    local   Dgr,R
;local   iDgr,iDgrInc
    local   X,Y
;local   Pt[5]:POINT             ;用来放五角星五个角坐标
    mov     Dgr,0
;mov     iDgr,0
;mov     iDgrInc,72             ;内重循环角度增量
    mov     eax,Radius
    sub     eax,10
    mov     R,eax
    .while  Dgr<=360               ;循环,直到画了一圈
            finit                  ;初始化FPU寄存器

            invoke  _CalcX,CentX,Dgr,R   ;计算钟面圆周上小圆点的圆心X坐标
            mov     X,eax
            invoke  _CalcY,CentY,Dgr,R   ;计算钟面圆周上小圆点的圆心X坐标
            mov     Y,eax
;mov edi,0
;.while edi<5
;invoke _CalcX,X,iDgr,_Radius
;mov  Pt[edi].x,eax 
;invoke _CalcY,Y,iDgr,_Radius
;mov  Pt[edi].y,eax
;inc  edi
;mov     eax,iDgrInc
;add     iDgr,eax 
;.endw
;invoke  Polygon,hDC,addr Pt,5
            mov     eax,X          
            mov     ecx,X
            mov     ebx,Y
            mov     edx,Y
            sub     eax,_Radius
            add     ecx,_Radius
            sub     ebx,_Radius
            add     edx,_Radius
            invoke  Ellipse,hDC,eax,ebx,ecx,edx
            mov     eax,_DegreeInc
            add     Dgr,eax        ;角度增加_DegreeInc
    .endw
ret
_DrawDot  endp

; 画线条,半径=时钟半径-参数_RAdj
_DrawLine   proc  hDC,_Degree,_RAdj
         ;_Degree用来指定画的线的偏移度数
         ;_RAdj用来调整画的线的长度,
         ;秒针、分针、时针长度应该一次减少
    local   R
    local   X1,Y1,X2,Y2
    mov     eax,Radius
    sub     eax,_RAdj
    mov     R,eax

; 计算线条两端的坐标
    invoke  _CalcX,CentX,_Degree,R   ;调用子程序计算指针尖X坐标
    mov     X1,eax
    invoke  _CalcY,CentY,_Degree,R   ;调用子程序计算针尖Y坐标
    mov     Y1,eax
    add     _Degree,180
    invoke  _CalcX,CentX,_Degree,10  ;调用子程序计算针尾X坐标
    mov     X2,eax
    invoke  _CalcY,CentY,_Degree,10  ;调用子程序计算针尾X坐标
    mov     Y2,eax
    invoke  MoveToEx,hDC,X1,Y1,NULL

⌨️ 快捷键说明

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