罗云彬的Win32汇编教程正文文档格式.docx

上传人:b****6 文档编号:16515017 上传时间:2022-11-24 格式:DOCX 页数:118 大小:90.92KB
下载 相关 举报
罗云彬的Win32汇编教程正文文档格式.docx_第1页
第1页 / 共118页
罗云彬的Win32汇编教程正文文档格式.docx_第2页
第2页 / 共118页
罗云彬的Win32汇编教程正文文档格式.docx_第3页
第3页 / 共118页
罗云彬的Win32汇编教程正文文档格式.docx_第4页
第4页 / 共118页
罗云彬的Win32汇编教程正文文档格式.docx_第5页
第5页 / 共118页
点击查看更多>>
下载资源
资源描述

罗云彬的Win32汇编教程正文文档格式.docx

《罗云彬的Win32汇编教程正文文档格式.docx》由会员分享,可在线阅读,更多相关《罗云彬的Win32汇编教程正文文档格式.docx(118页珍藏版)》请在冰豆网上搜索。

罗云彬的Win32汇编教程正文文档格式.docx

在Win32编程中,由于Windows有很多的数据结构和定义,这些都放在include文件中,还有连接时要用到Import库(通俗的讲就是Windows提供的DLL文件中的函数列表,也就是告诉程序到哪里去调用API函数),这些都放在include和lib目录中。

我们在编译时要指定以下的系统环境:

setinclude=\Masm32v5\Include

setlib=\Masmv5\lib

setpath=\Masmv5\Bin

这样编译器就会到正确的路径中去找include文件和lib文件。

你可以自己在autoexec.bat文件中加上以上语句,为了产生Windows的PE格式的执行文件,在编译和连接中要指定相应的参数:

编译:

Ml/c/coff文件名.asm

连接:

Link/SUBSYSTEM:

WINDOWSOBJ文件名.obj资源文件名.res

为了不在每次编译时都要打这么多的参数,我们可以用nmake文件来代为执行,nmake是代码维护程序,他会检查.asm.obj.exe.res等文件的时间,如果你更新了源程序,他会自动执行编译程序或连接程序产生相应的文件。

你可以在文件名为makefile的文件中指定使用的编译器和连接程序以及相应的参数,下面是一个makefile文件的例子:

NAME=Clock

OBJS=$(NAME).obj

RES=$(NAME).res

$(NAME).exe:

$(OBJS)$(RES)

Link/DEBUG/SUBSYSTEM:

WINDOWS$(OBJS)$(RES)

$(RES):

$(NAME).rc

Rc$(NAME).rc

.asm.obj:

Ml/c/coff$(NAME).asm

文件告诉nmake程序,程序名为clock,产生clock.exe文件需要clock.obj和clock.res文件,而产生clock.res文件需要clock.rc文件,产生clock.obj文件要用到clock.asm文件,至于是否需要执行ml,link和rc,程序会根据文件的时间自动判断。

在我的主页的编程工具中,有Tasm、Masm32V5和nmake程序下载。

Win32汇编教程二

Win32汇编程序的结构和语法

Win32ASM程序的结构和语法

让我们先来看看一个最简单的Win32汇编程序:

.386

.modelflat,stdcall

optioncasemap:

none;

casesensitive

includewindows.inc

includekernel32.inc

includelibkernel32.lib

.data

szCaptiondb'

Win32汇编例子'

0

szTextdb'

Win32汇编,Simpleandpowerful!

'

.code

start:

invokeMessageBox,NULL,addrszText,addrszCaption,MB_OK

invokeExitProcess,NULL

endstart

这就是一个能执行的最简单的Win32汇编程序,下面我简单地介绍一下各部分的作用:

.386

这条语句和Dos下汇编是一样的,是告诉编译器我们要用到80386的指令集,因为32位汇编程序要用到32位的寄存器如eax,ebx等,所以这一句是必须的,当然,你也可以用.486,.586等,当用到特权指令时,还可以用.386p,.486p等等。

.modelflat,stdcall

.model告诉编译器程序的模式,编过Dos汇编的人可能知道在Dos程序的模式有tiny,small,...huge等,它指定了程序内存寻址模式,在huge等模式下,内存寻址和子程序调用将用Far的格式,但在Win32汇编中,你只能使用一个模式即flat模式,因为对Win32程序来说,内存是连续的一个4GB的段,无所谓小或大的模式。

而stdcall告诉编译器参数的传递方式,在调用子程序时,参数是通过堆栈传递的,参数的传递方式有三种,stdcall,c和pascal,stdcall指定了参数是从右到左压入堆栈的,比如说对一个WindowsAPI如MessageBox,在手册中是如此定义的:

intMessageBox(

HWNDhWnd,//handleofownerwindow

LPCTSTRlpText,//addressoftextinmessagebox

LPCTSTRlpCaption,//addressoftitleofmessagebox

UINTuType//styleofmessagebox

);

那么在汇编中我们就可以这样调用它:

pushuType

pushlpCaption

pushlpText

pushhWnd

callMessageBox

大家要注意最右面的参数是最后一个进堆栈的,当然,我们不必这样麻烦的调用一个API,因为Masm中的一个宏语句不但帮助我们完成了所有的压栈操作,还帮我们检查参数的个数是否正确,那就是invoke语句,我们可以把上面的语句换成invokeMessageBox,hWnd,lpText,lpCaption,uType就行了。

如本程序中代入实际参数就成了invokeMessageBox,NULL,addrszText,addrszCaption,MB_OK。

include语句

include语句包含了一些系统的定义和API函说明,其中所有的Windows数据结构定义和常量定义包含在windows.inc中,而其他API函数的说明包含在xxx.inc中,如查MicrosoftWin32Programmer'

sReference知道ExitProcess包含在kernel32.dll中,那么我们就要在程序中包括includekernel32.inc和includelibkernel32.lib语句,否则在编译时会出现API函数未定义的错误。

而MessageBox在user32.dll中,那么我们就要在程序中包括includeuser32.inc和includelibuser32.lib语句

.data或.data?

指明了接下来是数据段,.data定义了预定义的变量,.data?

定义了未初始化的变量,两者的不同之处是.data?

定义的变量并不占用.exe文件的大小,而是在程序执行时动态分配,所以开始是不指定初始值的数据可以放在.data?

段中,如一个1K大小的缓冲区,放在.data?

中,程序将不会增加一个字节。

.code

指明了接下来是代码段,我们的所有代码都放在这里。

最后的一句start语句指定了程序开始执行的语句。

程序中的ExitProcess是一个标准的Win32API,对应Dos汇编中的int20h或movah,4ch/int21h,也就是程序退出。

而MessageBox也是一个标准的API,功能是在屏幕上显示一个消息框,具体的参数上面已经解释过了还有要注意的是invokeMessageBox,NULL,addrszText,addrszCaption,MB_OK语句中,MB_OK和NULL已经预定义在Windows.inc中。

Win32汇编教程三

一个简单的对话框---兼谈资源文件的使用

Windows的资源文件

不管在Dos下编程还是在Windows下编程,我们总是要用到除了可执行文件外的很多其他数据,如声音数据,图形数据,文本等等,在Dos下编程,我们可以自己定义这些文件的格式,但这样一来就造成了很多资源共享的问题,大家可能还记的Dos下的很多游戏,它们的图形都是按自己的格式存放的,你无法用标准的看图软件来看。

也无法把它另存为其他格式。

虽然在Win32编程中,我们仍然可以这样做,但Win32编程给了我们一个方案----就是格式统一的资源文件,把字符串、图形、对话框包括上面的按钮,文本等定义到一个资源文件中,就可以方便的在不同的文件中使用它,最重要的是,如果我们用自己的文件格式,使用时就要涉及到这些文件的读写操作,比较复杂,但使用资源文件时,Windows提供了一系列的API来装入资源。

非常方便。

现在,让我们来看一个很简单的资源文件的源文件,它的扩展名是.rc,当它用资源编译器编译以后产生.res文件就可以在link的时候连入.exe文件中:

#include<

Resource.h>

#defineDLG_MAIN1

DLG_MAINDIALOGEX0,0,236,185

STYLEDS_MODALFRAME|WS_POPUP|WS_VISIBLE|WS_CAPTION|WS_SYSMENU

CAPTION"

对话框模板"

FONT9,"

宋体"

BEGIN

DEFPUSHBUTTON"

退出"

IDOK,177,163,50,14

CONTROL"

"

-1,"

Static"

SS_ETCHEDHORZ,7,155,222,1

END

现在我简单解释一下.rc文件的语法:

resource.h>

--resource.h文件包括资源文件的一些常量定义,如下面的WS_POPUP,WS_VISIBLE等窗口的风格等等

#defineDLG_MAIN1--类似于.asm文件的equ语句,和汇编源程序一样,这些定义是为了程序的可读性。

DLG_MAINDIALOGEX0,0,236,185

Windows的.rc文件可以定义BITMAP(位图),CURSOR(光标),ICON(图标),ACCELERATORS(加速键),DIALOG(对话框),MENU(菜单),STRINGTABLE(字符串表),RCDATA(自定义资源)等8种资源,详细的描述可以参考有关MFC的书籍,在Win32ASM中的资源编译器的语法中,一般格式是这些资源的定义方法是:

位图定义:

nameIDBITMAP[load-mem]filename

光标定义:

nameIDCURSOR[load-mem]filename

图标定义:

nameIDICON[load-mem]filename

加速键定义:

acctablenameACCELERATORS[optional-statements]

BEGINevent,idvalue,[type][options]

...

END

等等,具体的定义和参数可以参考Masm32v5中的Rc.hlp帮助文件。

(可以在编程工具中下载),我们可以用资源编辑器来所见即所得地编辑资源,也可以在文本编辑器中用上面这些语句自己定义资源。

在程序中使用资源

在程序中,要使用资源之前必须先装如内存,Windows定义了一系列的API来装入资源,如LoadMenu,LoadString,LoadBitmap等等,如LoadBitmap的定义:

HBITMAPLoadBitmap(

HINSTANCEhInstance,//handleofapplicationinstance

LPCTSTRlpBitmapName//addressofbitmapresourcename

);

这些Load函数的返回值是一个句柄,调用参数中一般至少为两项:

hInstance和ResouceName,这个ResouceName(如BitmapName,MenuName)就是在资源文件中的#define指定的值,如果你用#defineMY_ICON10/MY_ICONICON"

Main.ico"

定义了一个图标,那么在程序中要使用Main.ico图标就可以用LoadIcon(hInstance,10)来装入已经定义为10号的图标文件。

另一个参数hInstance是执行文件的句柄,它对应资源所在的文件名,你可以在程序开始执行时用invokeGetModuleHandle,NULL获得hInstance。

另外一些资源并不是显式地装入的,如对话框资源,它是在建立对话框的函数中由Windows自己装入的,如下面例子中的invokeDialogBoxParam,hInstance,DLG_MAIN,NULL,offset_ProcDlgMain,0,是在屏幕上显示一个资源文件中已经定义好了的对话框,就并不存在LoadDialogBox之类的API来先装入对话框。

Win32ASM-显示一个对话框

介绍了这么多相关的东西,现在让我们来看看如何显示一个对话框,源程序如下:

;

>

Programmedby罗云彬,bigluo@

Website:

LuoYunBin'

sWin32ASMpage(罗云彬的编程乐园)

includeuser32.inc

includecomctl32.inc

includecomdlg32.inc

includelibuser32.lib

includelibcomctl32.lib

includelibcomdlg32.lib

DLG_MAINequ1

.data?

hInstancedd?

szBufferdb256dup(?

_ProcDlgMainPROTO:

DWORD,:

DWORD

********************************************************************

_ProcDlgMainprocusesebxediesi,\

hWnd:

DWORD,wMsg:

DWORD,wParam:

DWORD,lParam:

moveax,wMsg

.ifeax==WM_CLOSE

invokeEndDialog,hWnd,NULL

.elseifeax==WM_INITDIALOG

.elseifeax==WM_COMMAND

moveax,wParam

.ifeax==IDOK

invokeEndDialog,hWnd,NULL

.elseifeax==IDCANCEL

.endif

.else

moveax,FALSE

ret

.endif

moveax,TRUE

ret

_ProcDlgMainendp

invokeInitCommonControls

invokeGetModuleHandle,NULL

movhInstance,eax

invokeDialogBoxParam,hInstance,DLG_MAIN,NULL,offset_ProcDlgMain,0

看了前面几篇文章以后,这儿的大部分语句应该是很熟悉了,我来讲解几句新的语句:

PROTO语句类似于C语言中的函数定义,在Win32汇编中,如果子程序的定义在引用以后,你就必须先定义,当然,这个定义是针对invoke语句和其他带参数的调用的,如果你的子程序没有参数,你就可以用call指令去调用它而不是用宏指令invoke,这时候你就不必声明这个函数。

hWnd:

这个定义proc的语句应该是不陌生的,要重复讲解一下的是uses和下面的参数,uses下的寄存器表示要编译器自动插入保存及恢复这些寄存器的指令,\是在Masm32中接下一行的符号,表示下一行是本行的继续内容,以避免一行中的内容过长。

下面的hWnd:

DWORD等语句定义了调用这个子程序的参数,如果有以下定义MyProcprocdwPara1:

DWORD,dwPara2:

DWORD,dwPara3:

DWORD,然后你用invokeMyProc1,2,3来调用它,那么,1,2,3将分别被赋值给dwPara1,dwPara2,dwPara3,你可以在子程序中使用这些传递过来的参数。

如果参数的类型是双字,那么:

DWORD可以省略。

.if/.else/.elseif/.endif

这些语句是宏指令,实际上不说你也知道它们的意思,有了这些宏指令,我们就可以把汇编编得象C一样结构清晰,而不必老是看到jmp指令了,当然,这只不过编译器帮你做了这些事情而已,如果你去反汇编一下,你开始会看到一大堆jmp指令,.if的格式如下

.ifeax==1如果eax等于1

.ifeax!

=1如果eax不等于1

=1&

&

ebx!

=2如果eax不等于1且ebx不等于2

.ifeax==1||ebx==2如果eax等于1或者ebx等于2

其他的宏指令还有.while/.endw.break等等,可以参考Masm32V5的帮助文件Masm32.hlp

最后要讲到的就是DialogBoxParam这个API了,在Windows中,所有的窗口都要指定一个子程序,当Windows检测到鼠标、定时器等和这个窗口有关的动作时,它回调用这个子程序,这就是Windows基于消息的体系的最基本的概念,换句话说,在Dos下,我们通过INT指令调用系统,而在Windows下,有很多时候是你指定子程序地址让Windows来调用你。

invokeDialogBoxParam,hInstance,DLG_MAIN,NULL,offset_ProcDl

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 经管营销 > 企业管理

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1