帖子《郁闷了好几天了——关于罗云彬的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 编辑 ]