Windows汇编语言简明教程——基础篇
(2007新版)
(V0.01)
作者:TBsoft Software Studio(2007)
作者前言
本教程是笔者1999年12月草作《Win32汇编语言教程》的新版,目前国内关于Win32汇编语言的优秀书籍是罗云彬所著,电子工业出版社出版的《Windows环境下32位汇编语言程序设计》,本教程较为简单,仅作为初学者的参考资料使用。
目前Windows已经从Win32发展到了Win64,因此本教程名称改为《Windows汇编语言简明教程》,但本教程的基础篇仍然只涉及Win32汇编语言。
1引言
Windows(Win32)应用程序一般使用C语言编程,但是在某些需要进行底层编程的情况下,例如Win32应用程序执行机制分析、加密解密、反病毒等底层编程,或者对于某些速度要求较高的程序,需要使用汇编语言(甚至机器语言)直接开发Win32应用程序。Win32应用程序虽然和其他32位应用程序(例如32位保护模式DOS程序)一样可以使用386汇编语言和保护模式编程,但是Win32应用程序的执行机制与其他32位应用程序有一定的差别,例如消息循环、动态链接等,Win32汇编语言也有其特殊的编程方式。
为了使大家能对Win32汇编语言的基本编程方法有一定的了解,笔者草拟了本教程,旨在抛砖引玉,如果本教程能够带领你走进Win32汇编语言世界,笔者心愿足矣。
使用本教程,要求读者具有80386汇编语言和C语言开发Win32应用程序(Win32 SDK编程)的基础。
2进行Win32汇编语言编程的基本软件
进行Win32汇编语言编程,通常需要使用MASM 6.11以上版本的汇编器,以及Win32 SDK中的资源编译器(RC.EXE)和链接器(LINK.EXE),还需要用到Win32 SDK中的引入库文件(KERNEL32.LIB、USER32.LIB、GDI32.LIB等)。
目前进行Win32汇编语言编程,准备开发环境较为简单的方法是使用MASM32软件包,可以使用MASM32 V7或者MASM32 V8版本。
MASM32软件包中已经包括了进行Win32汇编语言编程所需的各种软件,包括MASM 6.1x、资源编译器、链接器、包含文件、引入库等,还包括一个可以作为简单的汇编语言集成环境(IDE)的编辑器Quick Editor(QEDITOR.EXE),这样在汇编链接Win32汇编语言源程序时可以无需使用命令行工具,很适合初学者使用。
安装MASM32很简单,运行安装文件INSTALL.EXE,选择安装目标驱动器然后确认安装即可完成安装,MASM32通常安装在安装目标驱动器根目录下的masm32子目录中。
使用Quick Editor,可以直接使用资源管理器或者在命令提示符(MS-DOS方式)下运行MASM32安装目录下的QEDITOR.EXE文件。
3 Win32汇编语言与Win32 API
使用Win32汇编语言开发Win32应用程序,使用的应用程序框架仍然是Win32 SDK编程的应用程序框架,只不过将通常使用的C语言换成80386汇编语言。
显然,使用Win32汇编语言开发Win32应用程序同样存在调用Win32 API的问题。和使用C语言进行Win32 SDK编程需要WINDOWS.H头文件以及其他头文件定义常量、数据结构和Win32 API一样,Win32汇编语言也需要包含文件(INC文件)定义常量、数据结构和Win32 API。
MASM32中提供了使用Win32汇编语言开发Win32应用程序所需的包含文件,通常位于MASM32安装目录下的INCLUDE子目录中。Win32汇编语言源程序应该包含WINDOWS.INC文件,如果需要调用的Win32 API位于Win32系统DLL中,例如KERNEL32.DLL、USER32.DLL、GDI32.DLL等,还需要包含对应的包含文件,例如kernel32.inc、user32.inc、gdi32.inc等。
Win32 API中,凡是与字符或者字符串有关的API都有两种不同的类型:ANSI字符集API和Unicode字符集API,分别对应ANSI字符和Unicode字符,相应与字符或者字符串相关的数据结构也有两种不同的类型。Windows NT(包括Windows 2000/XP及其以后版本)支持两种类型的API,Windows 9x通常只支持ANSI字符集API。ANSI字符集API或者数据结构的实际名称以API或者数据结构名称末尾加字符“A”表示,Unicode字符集API或者数据结构的实际名称以API或者数据结构名称末尾加字符“W”表示,例如GetModuleHandle函数相应的ANSI字符集函数实际名称为GetModuleHandleA,相应的Unicode字符集函数实际名称为GetModuleHandleW。
在Win32 SDK中的WINDOWS.H头文件和其他头文件中,凡是与字符有关的API或者数据结构都有两种不同的定义,并使用条件编译和宏定义实现自动根据当前字符集使用对应的API或者数据结构定义。例如,下列程序段是WINBASE.H头文件中对GetModuleHandle函数的定义:
WINBASEAPI
HMODULE
WINAPI
GetModuleHandleA(
LPCSTR lpModuleName
);
WINBASEAPI
HMODULE
WINAPI
GetModuleHandleW(
LPCWSTR lpModuleName
);
#ifdef UNICODE
#define GetModuleHandleGetModuleHandleW
#else
#define GetModuleHandleGetModuleHandleA
#endif // !UNICODE
但是在MASM32提供的包含文件中,API或者数据结构名称标识符通常只对应ANSI字符集API或者数据结构,例如GetModuleHandle函数只对应GetModuleHandleA函数,这样可以保证在Windows 9x和Windows NT下的兼容性,如果读者需要改用Unicode字符集API或者数据结构,则需明确使用Unicode字符集API或者数据结构,例如调用GetModuleHandleW函数,初学者可以暂时不去管它。
4非结构化的汇编语言和结构化的汇编语言
读者可能一听到“汇编语言”四个字就觉得十分头疼!汇编语言给人的第一印象就是一大堆难以看懂又不直观的指令,而且不结构化,大量的标号、无条件跳转指令(JMP)和条件跳转指令让你难以看懂程序;过程(或者函数)的调用参数传递又不直观,要么直接使用寄存器传递参数,不符合结构化程序设计原则;要么使用堆栈传递参数,又不能有效地检验参数类型……想必Win32汇编语言更麻烦吧!
汇编语言不是结构化编程语言,但不等于汇编语言不能进行结构化编程,MASM 6.0以上版本的汇编器对汇编语言进行了扩展,提供了很多结构化汇编语言伪指令,可以方便地实现汇编语言结构化程序设计,当你看完本教程以后,你可能会感觉到:Win32汇编语言并不比C语言麻烦多少。(如果读者看不懂本教程中的汇编语言源程序,可以对照MASM32中有关结构化汇编语言语法的帮助看)
下面是一个使用非结构化的汇编语言编写的Win32汇编语言程序,本程序没有使用结构化汇编语言伪指令。本程序的功能很简单:在屏幕上显示一个消息框。本程序只调用了两个Win32 API:MessageBox和ExitProcess,源程序如下(MSGBOX1.asm):
.386
.MODEL flat,stdcall
OPTION CASEMAP:NONE
INCLUDE \masm32\include\windows.inc
INCLUDE \masm32\include\kernel32.inc
INCLUDE \masm32\include\user32.inc
INCLUDELIB \masm32\lib\kernel32.lib
INCLUDELIB \masm32\lib\user32.lib
.STACK 4096
.DATA
MsgTextBYTE'This is a simple Win32 application!',0
MsgTitleBYTE'Information',0
.CODE
_start:
moveax,MB_ICONINFORMATION
oreax,MB_OK
pusheax
leaeax,MsgTitle
pusheax
leaeax,MsgText
pusheax
xoreax,eax
pusheax
callMessageBox
xoreax,eax
pusheax
callExitProcess
END _start
使用Quick Editor汇编链接本程序的基本方法如下(下同):
1、启动MASM32中的Quick Editor,编辑汇编语言源程序,将上述汇编语言源程序全部输入或者粘贴,然后选择“File”—“Save As”菜单项将汇编语言源程序保存到一个目录下,注意该目录必须与MASM32的安装目录位于同一个驱动器上,汇编语言源程序文件的扩展名应该是“asm”。
2、选择Quick Editor中的“Project”—“Build All”菜单项即可汇编链接汇编语言源程序。汇编链接时会显示一个命令提示符窗口,如果没有出现错误或者警告信息,说明汇编链接成功,将会生成相应的OBJ文件和EXE文件。
3、选择Quick Editor中的“Project”—“Run Program”菜单项即可运行汇编链接后生成的EXE文件。
本程序汇编链接后,运行生成的MSGBOX1.exe文件,屏幕上将显示出一个消息框,消息框的标题是“Information”,消息框中显示的字符串是“This is a simple Win32 application!”。
Win32汇编语言源程序开始处通常有3条伪指令:
.386
.MODEL flat,stdcall
OPTION CASEMAP:NONE
指示汇编器汇编80386指令,并使用平坦内存模式(Win32内存模式)和stdcall函数调用方式(Win32标准函数调用方式),标识符区分大小写。源程序中使用.STACK、.DATA和.CODE伪指令分别定义堆栈、数据和代码。
Win32 API通常使用stdcall函数调用方式,stdcall函数调用方式中,函数的参数使用堆栈传递,函数调用之前参数自右向左进栈,函数调用返回时同时将参数出栈,函数返回值通过eax寄存器返回。
因此,程序中调用MessageBox函数和ExitProcess函数之前,都使用push指令将参数自右向左进栈,然后使用call指令直接调用Win32 API的入口点地址。本程序调用MessageBox函数显示消息框以后,调用ExitProcess函数终止程序的执行,ExitProcess函数的作用是终止当前进程。这种直接使用汇编语言指令调用Win32 API开发Win32应用程序的方式直接对应CPU的指令代码,最接近CPU硬件,但并不直观,编写程序一不小心就容易出错。
下面是一个与上述程序等价的Win32汇编语言源程序,使用了结构化汇编语言伪指令,实现了结构化的汇编语言。源程序如下(MSGBOX2.asm):
.386
.MODEL flat,stdcall
OPTION CASEMAP:NONE
INCLUDE \masm32\include\windows.inc
INCLUDE \masm32\include\kernel32.inc
INCLUDE \masm32\include\user32.inc
INCLUDELIB \masm32\lib\kernel32.lib
INCLUDELIB \masm32\lib\user32.lib
.STACK 4096
.DATA
MsgTextBYTE'This is a simple Win32 application!',0
MsgTitleBYTE'Information',0
.CODE
_start:
INVOKEMessageBoxA,0,ADDR MsgText,ADDR MsgTitle,MB_ICONINFORMATION or MB_OK
INVOKEExitProcess,0
END _start
本程序汇编链接后,运行生成的MSGBOX2.exe文件,结果与MSGBOX1.exe文件的运行结果完全相同。
在MASM32提供的包含文件中,使用PROTO伪指令定义函数原型(与C语言中函数原型的定义相似),可以定义函数名、调用方式和参数,例如在user32.inc包含文件中定义MessageBox的函数原型:
MessageBoxA PROTO :DWORD,:DWORD,:DWORD,:DWORD
MessageBox equ <MessageBoxA>
INVOKE伪指令调用由PROTO伪指令定义的函数,可以方便地传递参数和检查参数类型。包含文件中使用PROTO伪指令定义API函数,MSGBOX2.asm文件中使用INVOKE伪指令调用API函数,极其简单,连一条汇编语言指令也没有用到,可见MASM 6.0以上版本的汇编器提供的结构化汇编语言伪指令大大简化了Win32汇编语言编程。
5显示一个窗口的Win32汇编语言程序
学习过Win32SDK编程的读者编写的第一个应用程序可能就是显示一个窗口的C语言程序,笔者也编写了这样一个C语言程序,源程序如下(SDKSIMPL.c):
#include <windows.h>
#include <tchar.h>
static TCHAR szWindowClass[]=_T("SIMPLE");
LRESULT CALLBACK WndProc(HWND hWnd,
UINT message,
WPARAM wParam,
LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nShowCmd)
{
WNDCLASSEX wcex;
HWND hWnd;
MSG msg;
if(!hPrevInstance)
{
wcex.cbSize=sizeof(WNDCLASSEX);
wcex.style=CS_HREDRAW|CS_VREDRAW;
wcex.lpfnWndProc=(WNDPROC)WndProc;
wcex.cbClsExtra=0;
wcex.cbWndExtra=0;
wcex.hInstance=hInstance;
wcex.hIcon=LoadIcon(NULL,IDI_APPLICATION);
wcex.hCursor=LoadCursor(NULL,IDC_ARROW);
wcex.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName=NULL;
wcex.lpszClassName=szWindowClass;
wcex.hIconSm=LoadIcon(NULL,IDI_APPLICATION);
if(!RegisterClassEx(&wcex))
return FALSE;
}
hWnd=CreateWindow(szWindowClass,
_T("Simple"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);
if(hWnd==NULL) return FALSE;
ShowWindow(hWnd,nShowCmd);
UpdateWindow(hWnd);
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
switch(message)
{
case WM_PAINT:
hDC=BeginPaint(hWnd,&ps);
EndPaint(hWnd,&ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd,message,wParam,lParam);
}
return 0;
}
现在笔者用Win32汇编语言程序实现本程序的功能,源程序如下(SDKSIMP1.asm):
.386
.MODEL flat,stdcall
OPTION CASEMAP:NONE
INCLUDE \masm32\include\windows.inc
INCLUDE \masm32\include\user32.inc
INCLUDE \masm32\include\gdi32.inc
INCLUDE \masm32\include\kernel32.inc
INCLUDELIB \masm32\lib\user32.lib
INCLUDELIB \masm32\lib\gdi32.lib
INCLUDELIB \masm32\lib\kernel32.lib
WinMainPROTO stdcall,:HINSTANCE,:HINSTANCE,:LPSTR,:DWORD
.STACK 4096
.DATA
WindowClassBYTE'SIMPLE',0
WindowTitleBYTE'Simple',0
hInst1HINSTANCE0
lpCmdLine1LPSTR0
.CODE
_start:
INVOKEGetModuleHandle,NULL
movhInst1,eax
INVOKEGetCommandLine
movlpCmdLine1,eax
INVOKEWinMain,hInst1,NULL,lpCmdLine1,SW_SHOWDEFAULT
INVOKEExitProcess,eax
WinMainPROChInst:HINSTANCE,hPrevInst:HINSTANCE,lpCmdLine:LPSTR,nShowCmd:DWORD
LOCALwcex:WNDCLASSEX
LOCALhWnd:HWND
LOCALmsg:MSG
.IF!hPrevInst
movwcex.cbSize,SIZEOF WNDCLASSEX
movwcex.style,CS_HREDRAW or CS_VREDRAW
movwcex.cbClsExtra,0
movwcex.cbWndExtra,0
movwcex.lpfnWndProc,OFFSET WndProc
moveax,hInst
movwcex.hInstance,eax
INVOKELoadIcon,0,IDI_APPLICATION
movwcex.hIcon,eax
INVOKELoadCursor,0,IDC_ARROW
movwcex.hCursor,eax
movwcex.hbrBackground,COLOR_WINDOW+1
movwcex.lpszMenuName,NULL
movwcex.lpszClassName,OFFSET WindowClass
INVOKELoadIcon,0,IDI_APPLICATION
movwcex.hIconSm,eax
INVOKERegisterClassEx,ADDR wcex
.IF!eax
moveax,FALSE
ret
.ENDIF
.ENDIF
INVOKECreateWindowEx,0,ADDR WindowClass,ADDR WindowTitle,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,0,0,hInst,NULL
movhWnd,eax
.IF!eax
moveax,FALSE
ret
.ENDIF
INVOKEShowWindow,hWnd,nShowCmd
INVOKEUpdateWindow,hWnd
.WHILETRUE
INVOKEGetMessage,ADDR msg,0,0,0
.BREAK.IF!eax
INVOKETranslateMessage,ADDR msg
INVOKEDispatchMessage,ADDR msg
.ENDW
moveax,msg.wParam
ret
WinMain ENDP
WndProcPROChWnd:HWND,message:UINT,wParam:DWORD,lParam:DWORD
LOCALhDC:HDC
LOCALps:PAINTSTRUCT
.IFmessage==WM_PAINT
INVOKEBeginPaint,hWnd,ADDR ps
movhDC,eax
INVOKEEndPaint,hWnd,ADDR ps
xoreax,eax
ret
.ELSEIF message==WM_DESTROY
INVOKEPostQuitMessage,0
xoreax,eax
ret
.ELSE
INVOKEDefWindowProc,hWnd,message,wParam,lParam
ret
.ENDIF
xoreax,eax
ret
WndProc ENDP
END _start
<spa
分享到:
相关推荐
汇编语言课程设计——————电子时钟的设计汇编语言课程设计——————电子时钟的设计汇编语言课程设计——————电子时钟的设计汇编语言课程设计——————电子时钟的设计汇编语言课程设计——————电子...
汇编语言.pdf————电子版_pdf版
《汇编语言简明教程》 学习汇编语言是一次深入理解计算机底层运作的旅程,它需要胆量、知识、开放的心态、一定的编程经验和逻辑思维。汇编语言是计算机可以直接执行的语言,它与高级语言不同,更为底层,更加接近...
《汇编语言程序设计——从DOS到Windows》是一门深入探讨计算机底层运作原理和编程技术的课程。汇编语言,作为与机器指令最接近的编程语言,是理解计算机硬件和软件交互的基础。本课程旨在带领学习者从DOS(Disk ...
【汇编语言实验报告——汇编程序的汇编及运行】深入解析 汇编语言是一种低级编程语言,它直接对应于计算机硬件的指令集。本实验报告旨在探讨汇编程序从编写到运行的全过程,包括汇编、连接和执行等关键步骤。以下是...
汇编语言程序设计————计算器.doc
总的来说,汇编语言简明教程涵盖了计算机组织基础、80x86处理器的特性、内存组织、分段结构以及地址转换等核心概念。这些知识对于编写高效的汇编代码至关重要,因为它们能帮助程序员更好地理解和利用计算机的底层...
《汇编语言教程——学汇编必备》是一个包含丰富的学习资源的压缩包,旨在帮助初学者和有经验的程序员深入理解和掌握汇编语言。汇编语言是计算机科学的基础,它是直接对应于机器语言的编程语言,对于理解计算机硬件...
汇编语言入门教程[定义].pdf
汇编语言课程设计——学生基本信息管理 学生信息包括学号、姓名、性别和出生年月 功能包括插入、删除和查找
PPT形式,共十二章。选择了当今广为流行的以Intel 80x86...第2部分介绍基于Windows的保护模式程序设计,主要内容包括:32位CPU及Windows基础、Windows汇编语言程序设计基础、深入Windows汇编编程、保护模式及其应用等。
一个不错的汇编语言教程,适用于初学者,里面都是基础知识。
windows汇编语言教程,windows汇编语言教程
汇编语言编程二——Debug的使用 Debug 是一种动态调试程序,主要用于调试汇编语言程序。它可以显示和修改寄存器及内存单元的内容,按指定地址启动并运行程序,设置断点使程序分段运行,以便检查程序运行过程中的...
Intel汇编语言程序设计——Irvine.16/32文件包
《汇编语言程序设计简明教程》是一本深入浅出介绍汇编语言编程的教材,由杨文显编著。汇编语言是计算机科学的基础,它是一种低级编程语言,直接对应于计算机的机器指令,因此对理解计算机硬件工作原理至关重要。本...
汇编语言课程设计——计算器.doc
1、简明x86汇编语言教程(1)-汇编语言简介 2、简明x86汇编语言教程(2)-认识处理器 3、简明x86汇编语言教程(3)-使用寄存器 4、简明x86汇编语言教程(4)-操作内存 5、简明x86汇编语言教程(5)-串操作 6、简明x86汇编...
首先,汇编语言是一种低级编程语言,它与计算机的机器语言非常接近,但是使用了人类可读的符号和单词代替了机器语言中的二进制代码。在汇编语言中,程序员可以直接控制硬件,进行内存地址操作,设置寄存器等,这使得...
Intel汇编语言程序设计——示例代码 .exe