让我们先来看看一个最简单的Win32汇编程序:
.386
.model flat, stdcall
option casemap :none case sensitive
include windows.incinclude kernel32.incinclude user32.inc
includelib kernel32.libincludelib user32.lib
.data
szCaption db 'Win32汇编例子',0
szText db 'Win32汇编,Simple and powerful!',0
.code
start:
invoke MessageBox,NULL,addr szText,addr szCaption,MB_OK
invoke ExitProcess,NULL
end start
这就是一个能执行的最简单的Win32汇编程序,下面我简单地介绍一下各笑搜部分的作用: .model告诉编译器程序的模式,编过Dos汇编的人可能知道在Dos程序的模式有tiny,small,...huge 等,它指定了程序内存寻址模式,在huge等模式下,内存寻址和子程序调用将用Far的格式,但在Win32汇编中,你只能使用一个模式即 flat 模式,因为对Win32程序来说,内存是连续的一个4GB的段,无所谓小或大的模式。而stdcall 告诉编译器参数的传递方式,在调用子程序时,参数是通过堆栈传递的,参数的传递方式有三种,stdcall,c 和 pascal,stdcall 指定了参数是从右到左压入堆栈的,比如说对一个Windows API 如 MessageBox,在手册中是如此定义的:
int MessageBox(
HWND hWnd, // handle of owner window
LPCTSTR lpText, // address of text in message box
LPCTSTR lpCaption, // address of title of message box
UINT uType // style of message box
)
那么在汇编中我们就可以这样调用它:
push uType
push lpCaption
push lpText
push hWnd
call MessageBox
大家要注意最右面的参数是最后一个进堆栈的,当然,我们不必这样麻烦的调用一个 API,因为Masm中的一个宏语句不但帮助我们完成了所有的压栈 *** 作,还帮我们检查参数的个数是否正确,那就是 invoke 语句,我们可以把上面的语句换成 invoke MessageBox,hWnd,lpText,lpCaption,uType 就行了。如本程序中代入实际参数就成了 invoke MessageBox,NULL,addr szText,addr szCaption,MB_OK。 不管在Dos下编程还是在Windows下编程,我们总是要用到除了可执行文件外的很多其他数据,如声音数据,图形数据,文本等等,在Dos下编程,我们可以自己定义这些文件的格式,但这样一来碰凳历就造成了很多资源共享的问题,大家可能还记的Dos下的很多游戏,它们的图形都是按自己的格式存放的,你无法用标准的看图软件来看。也无法把它另存为其他格式。虽然在Win32编程中,我们仍然可以这样做,但Win32编程给了我们一个方案 ---- 就是格式统一的资源文件,把字符串、图形、对话粗拿框包括上面的按钮,文本等定义到一个资源文件中,就可以方便的在不同的文件中使用它,最重要的是,如果我们用自己的文件格式,使用时就要涉及到这些文件的读写 *** 作,比较复杂,但使用资源文件时,Windows提供了一系列的API来装入资源。非常方便。.rc,当它用资源编译器编译以后产生 .res 文件就可以在 link的时候连入.exe 文件中:
#include <Resource.h>
#define DLG_MAIN 1
DLG_MAIN DIALOGEX 0, 0, 236, 185
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION 对话框模板
FONT 9, 宋体
BEGIN
DEFPUSHBUTTON 退出,IDOK,177,163,50,14
CONTROL ,-1,Static,SS_ETCHEDHORZ,7,155,222,1
END
.rc文件的语法:
#include <resource.h>-- resource.h文件包括资源文件的一些常量定义,如下面的 WS_POPUP,WS_VISIBLE 等窗口的风格等等
#define DLG_MAIN 1 -- 类似于 .asm 文件的 equ 语句,和汇编源程序一样,这些定义是为了程序的可读性。
DLG_MAIN DIALOGEX 0,0,236,185
Windows的.rc文件可以定义 BITMAP(位图),CURSOR(光标),ICON(图标),ACCELERATORS(加速键),DIALOG(对话框),MENU(菜单),STRINGTABLE(字符串表),RCDATA(自定义资源)等8种资源,详细的描述可以参考有关MFC的书籍,在Win32ASM中的资源编译器的语法中,一般格式是这些资源的定义方法是:
位图定义: nameID BITMAP [load-mem] filename
光标定义: nameID CURSOR [load-mem] filename
图标定义: nameID ICON [load-mem] filename
加速键定义:
acctablename ACCELERATORS [optional-statements]
BEGIN event, idvalue, [type] [options]
. . .
END
等等,具体的定义和参数可以参考 Masm32v5 中的 Rc.hlp 帮助文件。(可以在编程工具中下载),我们可以用资源编辑器来所见即所得地编辑资源,也可以在文本编辑器中用上面这些语句自己定义资源。 在程序中,要使用资源之前必须先装如内存,Windows定义了一系列的API来装入资源,如 LoadMenu,LoadString,LoadBitmap 等等,如 LoadBitmap 的定义:
HBITMAP LoadBitmap(
HINSTANCE hInstance, // handle of application instance
LPCTSTR lpBitmapName // address of bitmap resource name
)
这些Load函数的返回值是一个句柄,调用参数中一般至少为两项: hInstance 和 ResouceName,这个 ResouceName(如BitmapName,MenuName)就是在资源文件中的 #define 指定的值,如果你用 #define MY_ICON 10/ MY_ICON ICON Main.ico 定义了一个图标,那么在程序中要使用 Main.ico 图标就可以用 LoadIcon(hInstance,10) 来装入已经定义为10号的图标文件。另一个参数 hInstance 是执行文件的句柄,它对应资源所在的文件名,你可以在程序开始执行时用 invoke GetModuleHandle,NULL 获得 hInstance。另外一些资源并不是显式地装入的,如对话框资源,它是在建立对话框的函数中由Windows自己装入的,如下面例子中的 invoke DialogBoxParam,hInstance,DLG_MAIN,NULL,offset _ProcDlgMain,0 ,是在屏幕上显示一个资源文件中已经定义好了的对话框,就并不存在 LoadDialogBox 之类的API来先装入对话框。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)