用汇编编 Windows 程序
概述:
用汇编编制一般的 Windows 程序需要的不是汇编编程的资料,而是 Windows 函数调用的资料,你分析一下下面的源程序就会发现,程序的结构跟用
BC++ 编 Windows 程序几乎一模一样,原来用 C++ 函数的地方,变成了一个 Call 外部子程序,而函数的参数是由 PUSH 指令先压入堆栈,先由最后一个参数压起。同样,用汇编编
Windows 程序也需要 .DEF 文件和 .RES 文件,这是由 Windows 程序的结构决定的。本文是一个最简单的 Windows 程序,仅仅开了一个窗口,说一句话:"Hello,
Windows 95!",这个声音文件是我从别的地方拷来的,你可以把它换成其他声音文件。
用于编译的工具请到软件下载中找,本文要用到的是 Tasm.exe,Tlink.exe,Make.exe 和库文件
Import32.lib。这儿是源程序和编译好的可执行文件的压缩档:Hellowin.zip
源程序:
文件 Makefile 的内容,这个文件是给 Make.exe 用的,告诉它用什么库文件,什么 .RES 文件等等:
NAME = hellowin OBJS = $(NAME).obj DEF = $(NAME).def RES = $(NAME).res
IMPORT=IMPORT32
$(NAME).EXE: $(OBJS) $(DEF) tlink32 /Tpe /aa /c $(LINKDEBUG) $(OBJS),,, $(IMPORT), $(DEF),
.asm.obj: tasm32 /ml /m2 $&.asm,,,
文件 Hellowin.def 的内容,同编 C++ 程序一样,定义了数据段,代码段的属性等内容:
NAME HELLOWIN
DESCRIPTION '(C) Copyright by Lyb'
CODE PRELOAD MOVEABLE DISCARDABLE DATA PRELOAD MOVEABLE MULTIPLE
EXETYPE WINDOWS
HEAPSIZE 8192 STACKSIZE 8192
EXPORTS WndProc
HelloWin 的源程序:
.486p .model flat,STDCALL
include windows.inc ;外部子程序,常量的定义等
;************************************************** .data
msg MSGSTRUCT <?> ;消息 wndclass WNDCLASS <?> ;Windows 类 ptstr PAINTSTRUCT <?> ;用于屏幕刷新的句柄 rect RECT <?> ;
h_dc dd ? ;DC 句柄,用于屏幕刷新的句柄 h_inst dd ? ;handle of module h_win dd ? ;handle of window d_class db "hello win",0
t_title db "Hello, windows 95 !",0 t_copy db 'A copy of program is already running, continue ? ',0
paint_x dd ? paint_y dd ? wav_filename db 'hellowin.wav',0
;************************************************** .code
start: push 0 call GetModuleHandle ;取模块句柄 mov h_inst,eax find_class: push 0 push offset d_class call FindWindow ;查找有无程序副本在运行 or eax,eax jz register_class push MB_YESNO or MB_ICONQUESTION push offset t_title push offset t_copy push 0 call MessageBox ;显示一个对话框 cmp eax,IDNO jz end_loop register_class: push IDC_ARROW push 0 call LoadCursor ;装入光标 mov wndclass.clsHCursor,eax
mov wndclass.clsStyle,CS_HREDRAW or CS_VREDRAW mov wndclass.clsLpfnWndProc,offset WndProc mov wndclass.clsCbClsExtra,0 mov wndclass.clsCbWndExtra,0 mov eax,h_inst mov wndclass.clsHInstance,eax mov wndclass.clsHIcon,0 mov wndclass.clsHbrBackground,COLOR_WINDOW+1 mov wndclass.clsLpszMenuName,0 mov wndclass.clsLpszClassName,offset d_class push offset wndclass call RegisterClass ;注册窗口类
; create new window
push 0 push h_inst push 0 push 0 push CW_USEDEFAULT push CW_USEDEFAULT push CW_USEDEFAULT push CW_USEDEFAULT mov eax,WS_OVERLAPPEDWINDOW or WS_MINIMIZE
push eax push offset t_title push offset d_class push 0 call CreateWindowEx ;创建一个窗口 mov h_win,eax
; show new window
push SW_SHOWNORMAL ; push SW_SHOWMINNOACTIVE ;show in task bar push h_win call ShowWindow ;显示窗口
push h_win call UpdateWindow ;刷新窗口 msg_loop: push 0 push 0 push 0 push offset msg call GetMessage ;取消息循环 cmp ax,0 jz end_loop
push offset msg call TranslateMessage ;把消息传给 WndProc 子程序 push offset msg call DispatchMessage jmp msg_loop end_loop: push msg.msWPARAM call ExitProcess
;******************************************************************** ; WndProc ;消息处理程序 ;******************************************************************** WndProc proc uses ebx edi esi,hwnd:DWORD,wmsg:DWORD,wparam:DWORD,lparam:DWORD LOCAL theDC:DWORD ;注意,以上的结构是固定的,因为 Windows 自己回先把 EBX,EDI,ESI 压入 STACK
mov eax,wmsg cmp eax,WM_CREATE ;判断消息类型并执行响应程序 jz wm_create cmp eax,WM_DESTROY jz wm_destroy cmp eax,WM_PAINT jz wm_paint
push lparam ;return with default windows proc push wparam push wmsg push hwnd call DefWindowProc ret wm_create: push 20000h or 1 ;snd_filename | snd_async push 0 push offset wav_filename call PlaySound xor eax,eax ret wm_paint: push offset ptstr push hwnd call BeginPaint mov h_dc,eax
push offset rect push hwnd call GetClientRect
push 20h or 1 or 4 ;dt_singleline | dt_enter | DT_VCENTEr push offset rect push -1 push offset t_title push h_dc call DrawText
push offset ptstr push hwnd call EndPaint xor eax,eax ret wm_destroy: push 0 call PostQuitMessage xor eax,eax ret
WndProc endp public WndProc
ends end start