汇编教程之win32消息框
2008-04-28 09:33:12 来源:WEB开发网在本课中,我们将用汇编语言写一个 Windows 程序,程序运行时将弹出一个消息框并显示"Win32 assembly is great!"。
理论:
Windows 为编写应用程序提供了大量的资源。其中最重要的是Windows API (Application Programming Interface)。 Windows API是一大组功能强大的函数,它们本身驻扎在 Windows 中供人们随时调用。这些函数的大部分被包含在几个动态链接库(DLL)中,譬如:kernel32.dll、 user32.dll 和 gdi32.dll。 Kernel32.dll中的函数主要处理内存管理和进程调度;user32.dll中的函数主要控制用户界面;gdi32.dll中的函数则负责图形方面的操作。除了上面主要的三个动态链接库,您还可以调用包含在其他动态链接库中的函数,当然您必须要有关于这些函数的足够的资料。
动态链接库,顾名思义,这些 API 的代码本身并不包含在 Windows 可执行文件中,而是当要使用时才被加载。为了让应用程序在运行时能找到这些函数,就必须事先把有关的重定位信息嵌入到应用程序的可执行文件中。这些信息存在于引入库中,由链接器把相关信息从引入库中找出插入到可执行文件中。您必须指定正确的引入库,因为只有正确的引入库才会有正确的重定位信息。
当应用程序被加载时 Windows 会检查这些信息,这些信息包括动态链接库的名字和其中被调用的函数的名字。若检查到这样的信息,Windows 就会加载相应的动态链接库,并且重定位调用的函数语句的入口地址,以便在调用函数时控制权能转移到函数内部。
如果从和字符集的相关性来分,API 共有两类:一类是处理 ANSI 字符集的,另一类是处理 UNICODE 字符集的。前一类函数名字的尾部带一个"A"字符,处理UNICODE的则带一个"W"字符(我想"W"也许是代表宽字符的意思吧)。我们比较熟悉的ANSI字符串是以 NULL 结尾的一串字符数组,每一个ANSI字符是一个 BYTE 宽。对于欧洲语言体系,ANSI 字符集已足够了,但对于有成千上万个唯一字符的几种东方语言体系来说就只有用 UNICODE 字符集了。每一个 UNICODE 字符占有两个 BYTE 宽,这样一来就可以在一个字符串中使用 65336 个不同字符了。
这也是为什么引进 UNICODE 的原因。在大多数情况下我们都可以用一个包含头文件,在其中定义一个宏,然后在实际调用函数时,函数名后不需要加后缀"A"或"W"。
<译者注:如在头文件中定义函数foo();
#ifdef UNICODE
#define foo() fooW()
#else
#define foo() fooA()
#endif
>
例子:
我先把框架程序放在下面,然后我们再向里面加东西。
.386
.model flat, stdcall
.data
.code
start:
end start
应用程序的执行是从 END 定义的标识符后的第一条语句开始的。在上面的框架程序中就是从 START 开始。程序逐条语句执行一直到遇到 JMP,JNE,JE,RET 等跳转指令。这些跳转指令将把执行权转移到其他语句上,若程序要退出 Windows,则必须调用函数 ExitProcess。
ExitProcess proto uExitCode:DWORD
上面一行是函数原型。函数原型会告诉编译器和链接器该函数的属性,这样在编译和链接时,编译器和链接器就会作相关的类型检查。 函数的原型定义如下:
FunctionName PROTO [ParameterName]:DataType,[ParameterName]:DataType,...
简言之,就是在函数名后加伪指令PROTO,再跟一串由逗号相隔的数据类型链表。在前面的 ExitProcess 定义中,该函数有一个 DWORD 类型的参数。当您使用高层调用语句 INVOKE 时,使用函数原型定义特别有用,您可以简单地认为 INVOKE 是一个有参数类型检查的调用语句。譬如,假设您这样写:
call ExitProcess
若您事先没把一个DWORD类型参数压入堆栈,编译器和链接器都不会报错,但毫无疑问,在您的程序运行时将引起崩溃。但是,当您这样写:
invoke ExitProcess
连接器将报错提醒您忘记压入一个 DWORD 类型参数。所以我建议您用 INVOKE 指令而不是CALL去调用一个函数。INVOKE 的语法如下:
INVOKE expression [,arguments]
expression 既可以是一个函数名也可以是一个函数指针。参数由逗号隔开。大多数API函数的原型放在头文件中。 如果您用的是 hutch 的 MASM32,这些头文件在文件夹MASM32/include 下, 这些头文件的扩展名为 INC,函数名和 DLL 中的函数名相同,譬如:KERNEL32.LIB 引出的函数 ExitProcess 的函数原形声明于kernel.inc中。您也可以自己声明函数原型。 在我的教学课程中都使用 hutch 的windows。inc,这些头文件您可以从http://win32asm.cjb.net下载。
更多精彩
赞助商链接