这是我的第一个Win32汇编程序,实现的效果就是画线,并能拖出橡皮线,刷新后不丢失数据。虽然功能很简单,若用VC++说不定一个小时就over,但是这个整整用了三天。现在我将程序贴出来恭大家批评指正。
我用的开发工具是:编辑器:EditPlus+asm语法文件,编译连接器Masm32v8,调试器:Ollydbg,make工具:VC++的nmake
.386
.model flat,stdcall
option casemap:none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; include
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include windows.inc
include gdi32.inc
includelib gdi32.lib
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; data
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data?
hInstance dd ?
hWinMain dd ?
m_isLine dd ?
m_X dd ?
m_Y dd ?
m_dragX dd ?
m_dragY dd ?
m_f dd ? ;the flag
m_data dd 1024 dup (0) ;the points buffer
m_pdata dd ? ;the number of the points in the buffer
.const
szClassName db 'MyClass',0
szCaptionMain db '画线',0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; code
; WinProc
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
_ProcWinMain proc uses ebx edi esi,hWnd,uMsg,wParam,lParam
local @stPs:PAINTSTRUCT
local @stRect:RECT
local @hDc
local @a1,@a2,@a3,@a4
mov eax,uMsg
;********************************************************************
.if eax == WM_LBUTTONDOWN
invoke SetCapture,hWnd
or m_isLine,1 ;the left button is pressed
mov ebx,lParam ;store mouse position
and ebx,0000FFFFH
mov m_X,ebx
mov ebx,lParam
shr ebx,00000010H
mov m_Y,ebx
mov m_f,0 ;0 means first time mouse move when drawing a line
;**************************************************************************************
.elseif eax == WM_MOUSEMOVE
mov ebx,m_isLine ;the left button is pressed
.if ebx == 1
invoke GetDC,hWnd
mov @hDc,eax
invoke SetROP2,@hDc,R2_NOTXORPEN
mov ebx,m_f
;the next block means NOT the first time mouse move when drawing a line
.if ebx == 1
invoke MoveToEx,@hDc,m_X,m_Y,0 ;move to recorded position
invoke LineTo,@hDc,m_dragX,m_dragY ;earase last line
.endif
invoke MoveToEx,@hDc,m_X,m_Y,0 ;move to recorded position
mov ebx,lParam ;draw line to mouse current position
and ebx,0000FFFFH
mov m_dragX,ebx
mov ebx,lParam
shr ebx,00000010H
mov m_dragY,ebx
invoke LineTo,@hDc,m_dragX,m_dragY
mov m_f,1 ;the first mouse down happened
invoke SetROP2,@hDc,R2_NOP
invoke ReleaseDC,hWnd,@hDc
.endif
;**************************************************************************************
.elseif eax == WM_LBUTTONUP
invoke GetDC,hWnd
mov @hDc,eax
invoke MoveToEx,@hDc,m_X,m_Y,0 ;move to recorded position
mov esi,offset m_data ;record the start point to m_data
mov eax,m_pdata
sal eax,2
add esi,eax
mov ebx,m_X
mov [esi],ebx
inc m_pdata
mov esi,offset m_data
mov eax,m_pdata
sal eax,2
add esi,eax
mov ecx,m_Y
mov [esi],ecx
inc m_pdata
mov ebx,lParam ;get mouse current position
and ebx,0000FFFFH
mov m_X,ebx
mov ebx,lParam
shr ebx,00000010H
mov m_Y,ebx
invoke LineTo,@hDc,m_X,m_Y
mov esi,offset m_data ;record the end point to m_data
mov eax,m_pdata
sal eax,2
add esi,eax
mov ebx,m_X
mov [esi],ebx
inc m_pdata
mov esi,offset m_data
mov eax,m_pdata
sal eax,2
add esi,eax
mov ecx,m_Y
mov [esi],ecx
inc m_pdata
invoke ReleaseDC,hWnd,@hDc
xor m_isLine,1 ;left button up
invoke ReleaseCapture
;**************************************************************************************
.elseif eax == WM_PAINT
invoke BeginPaint,hWnd,addr @stPs
mov @hDc,eax
mov edi,0
mov esi,0
mov ebx,offset m_data
.while edi < 1024
mov esi,edi
mov ecx,[ebx+esi]
mov @a1,ecx
mov ecx,[ebx+esi+4]
mov @a2,ecx
mov ecx,[ebx+esi+8]
mov @a3,ecx
mov ecx,[ebx+esi+12]
mov @a4,ecx
invoke MoveToEx,@hDc,@a1,@a2,0 ;move to recorded position
invoke LineTo,@hDc,@a3,@a4
add edi,16
.endw
invoke EndPaint,hWnd,addr @stPs
;**************************************************************************************
.elseif eax == WM_CLOSE
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
mov m_isLine,0
mov m_X,0
mov m_Y,0
mov m_dragX,0
mov m_dragY,0
mov m_f,0
invoke RtlZeroMemory,offset m_data,sizeof m_data
mov m_pdata,0
;**************************************************************************************
; Reg Window Class
;**************************************************************************************
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
;**************************************************************************************
; Create and Show Window
;**************************************************************************************
invoke CreateWindowEx,WS_EX_CLIENTEDGE,offset szClassName,/
offset szCaptionMain,WS_OVERLAPPEDWINDOW,100,100,600,400,/
NULL,NULL,hInstance,NULL
mov hWinMain,eax
invoke ShowWindow,hWinMain,SW_SHOWNORMAL
invoke UpdateWindow,hWinMain
;**************************************************************************************
; Message Loop
;**************************************************************************************
.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
最后补充一点,Win32汇编编程跟其他语言最大的不同就是:什么都要自己调用系统API,而且各API对各个标志位和寄存器的影响一定要注意,我一开始在刷新时候用的edx做循环判断,但程序只能刷出第一条线,白思不得其解,后来用调试器发现MoveToEx,LineTo返回后会影响edx,晕,而edi是一直空闲的,所以改用edi。所以调试工具一定不能少,不然的话,那编程就象在碰运气了。