Changjiang的专栏

孤帆远影碧空尽,唯见长江天际流。

赵世平ID:Changjiang
[修改头像]
17666次访问,排名5663(1)好友0人,关注者0
Changjiang的文章
原创 8 篇
翻译 2 篇
转载 0 篇
评论 6 篇
最近评论
wangqinghua1:很有收获,文风简洁
fantasyzzz:老师好,我是今天和您联系请教学习汇编方法的您的学生,我以前一直学习的是8086的汇编语言,不过也可以理解您上面的Win32ASM程序示例的大意,我已经对8086的汇编程序编写有一定的掌握,熟悉汇编的编写方法了,而且我现在还在看8086的教材巩固,我想问的是这个过程是否可以跳过,放下8086的学习,直接学习Win32的汇编。不知道这里请教合适么?谢谢老师。。
royelee:当年也是玩crack的啊?
还是原来用trw2k的时代爽啊。
Changjiang:呵呵,这个BLOG是去年开的,一直没有用,这几天正好有空,放上了一点文章。最近还好么,支持你。
flier:正是应了微软 3.0 那个说法,CLI 一直出到第三版,才算是基本上完成了预先的设想,把从一开始就规划进去的那些坑都填上,也腾出了精力去折腾相对来说更实际一些的 WinFX。等 Enterprise Library 那套东东再成熟一点,针对 Java 阵营的进攻号角才算真正吹向。
软件项目交易
订阅我的博客
XML聚合  FeedSky
订阅到鲜果
订阅到Google
订阅到抓虾
订阅到BlogLines
订阅到Yahoo
订阅到GouGou
订阅到飞鸽
订阅到Rojo
订阅到newsgator
订阅到netvibes
文章分类
收藏
    相册
    好友的BLOG
    孟岩的BLOG
    自己的其他BLOG
    Changjiang的另一个BLOG:TBsoft工作室的BLOG
    存档

    原创 Windows汇编语言简明教程——基础篇(2007新版)

    新一篇: Windows汇编语言简明教程——资源篇(2007新版)

    Windows汇编语言简明教程——基础篇
     
    2007新版)
     

    (V0.01

     

    作者:TBsoft Software Studio2007

     

    作者前言

     

    本教程是笔者199912月草作《Win32汇编语言教程》的新版,目前国内关于Win32汇编语言的优秀书籍是罗云彬所著,电子工业出版社出版的《Windows环境下32位汇编语言程序设计》,本教程较为简单,仅作为初学者的参考资料使用。

     

    目前Windows已经从Win32发展到了Win64,因此本教程名称改为《Windows汇编语言简明教程》,但本教程的基础篇仍然只涉及Win32汇编语言。

     

    1 引言

     

    WindowsWin32)应用程序一般使用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.LIBUSER32.LIBGDI32.LIB等)。

     

    目前进行Win32汇编语言编程,准备开发环境较为简单的方法是使用MASM32软件包,可以使用MASM32 V7或者MASM32 V8版本。

     

    MASM32软件包中已经包括了进行Win32汇编语言编程所需的各种软件,包括MASM 6.1x、资源编译器、链接器、包含文件、引入库等,还包括一个可以作为简单的汇编语言集成环境(IDE)的编辑器Quick EditorQEDITOR.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.DLLUSER32.DLLGDI32.DLL等,还需要包含对应的包含文件,例如kernel32.incuser32.incgdi32.inc等。

     

    Win32 API中,凡是与字符或者字符串有关的API都有两种不同的类型:ANSI字符集APIUnicode字符集API,分别对应ANSI字符和Unicode字符,相应与字符或者字符串相关的数据结构也有两种不同的类型。Windows NT(包括Windows 2000XP及其以后版本)支持两种类型的APIWindows 9x通常只支持ANSI字符集APIANSI字符集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 GetModuleHandle  GetModuleHandleW

    #else

    #define GetModuleHandle  GetModuleHandleA

    #endif // !UNICODE

     

    但是在MASM32提供的包含文件中,API或者数据结构名称标识符通常只对应ANSI字符集API或者数据结构,例如GetModuleHandle函数只对应GetModuleHandleA函数,这样可以保证在Windows 9xWindows NT下的兼容性,如果读者需要改用Unicode字符集API或者数据结构,则需明确使用Unicode字符集API或者数据结构,例如调用GetModuleHandleW函数,初学者可以暂时不去管它。

     

    4 非结构化的汇编语言和结构化的汇编语言

     

    读者可能一听到“汇编语言”四个字就觉得十分头疼!汇编语言给人的第一印象就是一大堆难以看懂又不直观的指令,而且不结构化,大量的标号、无条件跳转指令(JMP)和条件跳转指令让你难以看懂程序;过程(或者函数)的调用参数传递又不直观,要么直接使用寄存器传递参数,不符合结构化程序设计原则;要么使用堆栈传递参数,又不能有效地检验参数类型……想必Win32汇编语言更麻烦吧!

     

    汇编语言不是结构化编程语言,但不等于汇编语言不能进行结构化编程,MASM 6.0以上版本的汇编器对汇编语言进行了扩展,提供了很多结构化汇编语言伪指令,可以方便地实现汇编语言结构化程序设计,当你看完本教程以后,你可能会感觉到:Win32汇编语言并不比C语言麻烦多少。(如果读者看不懂本教程中的汇编语言源程序,可以对照MASM32中有关结构化汇编语言语法的帮助看)

     

    下面是一个使用非结构化的汇编语言编写的Win32汇编语言程序,本程序没有使用结构化汇编语言伪指令。本程序的功能很简单:在屏幕上显示一个消息框。本程序只调用了两个Win32 APIMessageBoxExitProcess,源程序如下(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

        MsgText         BYTE        'This is a simple Win32 application!',0

        MsgTitle        BYTE        'Information',0

      

    .CODE

     

    _start:

        mov     eax,MB_ICONINFORMATION

        or      eax,MB_OK

        push    eax

        lea     eax,MsgTitle

        push    eax

        lea     eax,MsgText

        push    eax

        xor     eax,eax

        push    eax

        call    MessageBox

        xor     eax,eax

        push    eax

        call    ExitProcess

     

    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

        MsgText         BYTE        'This is a simple Win32 application!',0

        MsgTitle        BYTE        'Information',0

      

    .CODE

     

    _start:

        INVOKE  MessageBoxA,0,ADDR MsgText,ADDR MsgTitle,MB_ICONINFORMATION or MB_OK

        INVOKE  ExitProcess,0