标题:帖子《郁闷了好几天了——关于罗云彬的win32的书的第七章那个时钟的程序》d ...
只看楼主
zklhp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:china
等 级:贵宾
威 望:254
帖 子:11485
专家分:33241
注 册:2007-7-10
结帖率:100%
 问题点数:0 回复次数:7 
帖子《郁闷了好几天了——关于罗云彬的win32的书的第七章那个时钟的程序》debug心得~~~~~~
说下我的思路罢~~~~ 其实这章我没看 跳过去了 因为不会浮点指令(那章我跳了)呵呵~

一看 开始正常 但 过了一秒 即 刷新了之后 错误 先怀疑

.elseif    eax == WM_PAINT
            invoke    BeginPaint,hWnd,addr @stPs
            invoke    _ShowTime,hWnd,eax
            invoke    EndPaint,hWnd,addr @stPs

重绘一定有鬼

再注意:






大了也这样 说明什么?

半径有问题 还有 为什么我能这么快得到结论 因为源程序(指罗大的程序) 注释好!!! 这点很重要

半径 怎么得来

_CalcClockParam    proc
        local    @stRect:RECT

        invoke    GetClientRect,hWinMain,addr @stRect
        mov    eax,@stRect.right
        sub    eax,@stRect.left    ;eax = 宽度
        mov    ecx,@stRect.bottom
        sub    ecx,@stRect.top        ;ecx = 高度
;********************************************************************
; 比较客户区宽度和高度,以小的值作为时钟的直径
;********************************************************************
        .if    ecx > eax
            mov    edx,eax        ;高度 > 宽度
            sub    ecx,eax
            shr    ecx,1
            mov    dwCenterX,0
            mov    dwCenterY,ecx
        .else
            mov    edx,ecx
            sub    eax,ecx
            shr    eax,1
            mov    dwCenterX,eax
            mov    dwCenterY,0
        .endif
        shr    edx,1
        mov    dwRadius,edx
        add    dwCenterX,edx
        add    dwCenterY,edx
        ret

_CalcClockParam    endp

原版 一比 发现错误~~~~~~

对新手的启示:注释非常重要 良好的注释对出错非常有帮助 如果你自信 随便拿出一个你多年前的帖子 你都能准确的知道你当时的思路 那 不注释也可以 不过 如果 你写了下面忘了上面 还是注释好

附录 罗大的原版源码 膜拜ing

程序代码:
 

 

 

 
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
; Sample code for < Win32ASM Programming 2nd Edition> 
; by 罗云彬, http://asm. 
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
; Clock.asm 
; 时钟例子:使用 GDI 函数绘画指针 
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
; 使用 nmake 或下列命令进行编译和链接: 
; ml /c /coff Clock.asm 
; rc Clock.rc 
; Link /subsystem:windows Clock.obj Clock.res 
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
        .386 
        .model flat, stdcall 
        option casemap :none 
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
; Include 文件定义 
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
include        windows.inc 
include        user32.inc 
includelib    user32.lib 
include        kernel32.inc 
includelib    kernel32.lib 
include        Gdi32.inc 
includelib    Gdi32.lib 
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
; Equ 等值定义 
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
ICO_MAIN    equ        1000h 
ID_TIMER    equ        1 
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
; 数据段 
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
        .data? 

 
hInstance    dd        ? 
hWinMain    dd        ? 
dwCenterX    dd        ?    ;圆心X 
dwCenterY    dd        ?    ;圆心Y 
dwRadius    dd        ?    ;半径 
 
        .const 
szClassName    db    'Clock',0 
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
; 代码段 
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
        .code 
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
; 计算时钟的位置、大小等参数 
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
_CalcClockParam    proc 
        local    @stRect:RECT 

 
        invoke    GetClientRect,hWinMain,addr @stRect 
        mov    eax,@stRect.right 
        sub    eax,@stRect.left    ;eax = 宽度 
        mov    ecx,@stRect.bottom 
        sub    ecx,@stRect.top        ;ecx = 高度 
;******************************************************************** 
; 比较客户区宽度和高度,以小的值作为时钟的直径 
;******************************************************************** 
        .if    ecx > eax 
            mov    edx,eax        ;高度 > 宽度 
            sub    ecx,eax 
            shr    ecx,1 
            mov    dwCenterX,0 
            mov    dwCenterY,ecx 
        .else 
            mov    edx,ecx 
            sub    eax,ecx 
            shr    eax,1 
            mov    dwCenterX,eax 
            mov    dwCenterY,0 
        .endif 
        shr    edx,1 
        mov    dwRadius,edx 
        add    dwCenterX,edx 
        add    dwCenterY,edx 
        ret 

 
_CalcClockParam    endp 
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
; 计算时钟圆周上某个角度对应的 X 坐标 
; X = 圆心X + Sin(角度) * 半径 
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
_dwPara180    dw    180 
_CalcX        proc    _dwDegree,_dwRadius 
        local    @dwReturn 

 
        fild    dwCenterX 
        fild    _dwDegree 
        fldpi 
        fmul            ;角度*Pi 
        fild    _dwPara180 
        fdivp    st(1),st    ;角度*Pi/180 
        fsin            ;Sin(角度*Pi/180) 
        fild    _dwRadius 
        fmul            ;半径*Sin(角度*Pi/180) 
        fadd            ;X+半径*Sin(角度*Pi/180) 
        fistp    @dwReturn 
        mov    eax,@dwReturn 
        ret 

 
_CalcX        endp 
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
; 计算时钟圆周上某个角度对应的 Y 坐标 
; Y = 圆心Y - Cos(角度) * 半径 
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
_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 
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
; 按照 _dwDegreeInc 的步进角度,画 _dwRadius 为半径的小圆点 
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
_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 
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
; 画 _dwDegree 角度的线条,半径=时钟半径-参数_dwRadiusAdjust 
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
_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    _hWnd,_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    ;画12个大圆点 
        invoke    _DrawDot,_hDC,360/60,1    ;画60个小圆点 
;******************************************************************** 
; 画时钟指针 
;******************************************************************** 
        invoke    CreatePen,PS_SOLID,1,0 
        invoke    SelectObject,_hDC,eax 
        invoke    DeleteObject,eax 
        movzx    eax,@stTime.wSecond 
        mov    ecx,360/60 
        mul    ecx            ;秒针度数 = 秒 * 360/60 
        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            ;分针度数 = 分 * 360/60 
        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 
;******************************************************************** 
        invoke    GetStockObject,NULL_PEN 
        invoke    SelectObject,_hDC,eax 
        invoke    DeleteObject,eax 
        popad 
        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,hWnd,eax 
            invoke    EndPaint,hWnd,addr @stPS 
        .elseif    eax ==    WM_CREATE 
            invoke    SetTimer,hWnd,ID_TIMER,1000,NULL 
;******************************************************************** 
        .elseif    eax ==    WM_CLOSE 
            invoke    KillTimer,hWnd,ID_TIMER 
            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,ICO_MAIN 
        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 

 

 


对这帖楼主还有几句:自己思考 学会问问题 学会使用论坛功能~

附件:原版源码+程序

Clock.rar (7.75 KB)


打完收工~


[ 本帖最后由 zklhp 于 2010-2-17 01:15 编辑 ]
搜索更多相关主题的帖子: 心得 debug 时钟 罗云彬 
2010-02-17 00:49
zklhp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:china
等 级:贵宾
威 望:254
帖 子:11485
专家分:33241
注 册:2007-7-10
得分:0 
自己顶~~~~~~~~~~~~~~~~~~~~~~~

还算疑惑tab的问题~~~~~~
2010-02-17 01:14
zklhp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:china
等 级:贵宾
威 望:254
帖 子:11485
专家分:33241
注 册:2007-7-10
得分:0 
貌似标题前加 “对” 不符合语法~
2010-02-17 01:15
新手小生
Rank: 1
等 级:新手上路
帖 子:7
专家分:0
注 册:2010-2-16
得分:0 
谢谢斑竹的指点
2010-02-17 10:23
ShadowHandle
Rank: 1
等 级:新手上路
帖 子:2
专家分:0
注 册:2015-1-17
得分:0 
以下是引用zklhp在2010-2-17 01:15:53的发言:

貌似标题前加 “对” 不符合语法~

时间真是一个巧妙的东西,与楼主发帖时隔四年;学会编的人前仆后继,作为还在探索中的一员,此时只能用痛哭流涕来感谢先哲们的无私奉献!
请问楼主:
    我今天看到这章,但遇到函数_CalcClockParam就卡住了。因为我不理解这两条指令:
sub    ecx,eax
shr    ecx,1

较长的边减去较短的边,然后向右位移一位...
总之我是没得出什么逻辑上的意义,所以语言钝涩...
您能解释一下x,y中心点是怎么的出来的吗?

[ 本帖最后由 ShadowHandle 于 2015-1-17 20:42 编辑 ]
2015-01-17 20:36
zklhp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:china
等 级:贵宾
威 望:254
帖 子:11485
专家分:33241
注 册:2007-7-10
得分:0 
以下是引用ShadowHandle在2015-1-17 20:36:50的发言:

 
时间真是一个巧妙的东西,与楼主发帖时隔四年;学会编的人前仆后继,作为还在探索中的一员,此时只能用痛哭流涕来感谢先哲们的无私奉献!
请问楼主:
    我今天看到这章,但遇到函数_CalcClockParam就卡住了。因为我不理解这两条指令:
sub    ecx,eax
shr    ecx,1
 
较长的边减去较短的边,然后向右位移一位

你好 我现在已经不玩这玩意了 祝你玩的愉快
2015-01-17 20:41
ShadowHandle
Rank: 1
等 级:新手上路
帖 子:2
专家分:0
注 册:2015-1-17
得分:0 
以下是引用zklhp在2015-1-17 20:41:21的发言:


你好 我现在已经不玩这玩意了 祝你玩的愉快

好吧,谢谢。
2015-01-17 20:48



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-297731-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.386450 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved