用汇编编 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		




(C) Copyright by LuoYunBin's Win32 ASM Page,http://asm.yeah.net