注册 登录
编程论坛 汇编论坛

帖子《郁闷了好几天了——关于罗云彬的win32的书的第七章那个时钟的程序》debug心得~~~~~~

zklhp 发布于 2010-02-17 00:49, 3503 次点击
说下我的思路罢~~~~ 其实这章我没看 跳过去了 因为不会浮点指令(那章我跳了)呵呵~

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

.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

 

 


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

附件:原版源码+程序

只有本站会员才能查看附件,请 登录


打完收工~


[ 本帖最后由 zklhp 于 2010-2-17 01:15 编辑 ]
7 回复
#2
zklhp2010-02-17 01:14
自己顶~~~~~~~~~~~~~~~~~~~~~~~

还算疑惑tab的问题~~~~~~
#3
zklhp2010-02-17 01:15
貌似标题前加 “对” 不符合语法~
#4
新手小生2010-02-17 10:23
谢谢斑竹的指点
#5
ShadowHandle2015-01-17 20:36
以下是引用zklhp在2010-2-17 01:15:53的发言:

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

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

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

[ 本帖最后由 ShadowHandle 于 2015-1-17 20:42 编辑 ]
#6
zklhp2015-01-17 20:41
以下是引用ShadowHandle在2015-1-17 20:36:50的发言:

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

你好 我现在已经不玩这玩意了 祝你玩的愉快
#7
ShadowHandle2015-01-17 20:48
以下是引用zklhp在2015-1-17 20:41:21的发言:


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

好吧,谢谢。
1