使用MASM-调用API(2)

3. 函数的声明

 

在调用API函数的时候,函数原型也必须预先声明,否则,编译器会不认这个函数。invoke伪指令也无法检查参数个数。声明函数的格式是:

函数名 proto [距离] [语言] [参数1]:数据类型,[参数2]:数据类型,……

句中的proto是函数声明的伪指令,距离可以是NEARFARNEAR16NEAR32FAR16FAR32Win32中只有一个平坦的段,无所谓距离,所以在定义时是忽略的;语言类型就是 .model那些类型,如果忽略,则使用 .model定义的默认值。

后面就是参数的列表了,对Win32汇编来说只存在dword类型的参数,所以所有参数的数据类型永远是dword,另外对于编译器来说,它只关心参数的数量,参数的名称在这里是无用的,仅是为了可读性而设置的,可以省略掉,所以下面两句消息框函数的定义实际上是一样的:

MessageBox  Proto  hWnd:dword,lpText:dword,lpCaption:dword,uType:dword

MessageBox  Proto  :dword,:dword,:dword,:dword

Win32环境中,和字符串相关的API共有两类,分别对应两个字符集:一类是处理 ANSI 字符集的,另一类是处理 Unicode 字符集的。前一类函数名字的尾部带一个A字符,处理Unicode的则带一个W字符。我们比较熟悉的ANSI字符串是以 NULL 结尾的一串字符数组,每一个ANSI字符占一个字节宽。对于欧洲语言体系,ANSI 字符集已足够了,但对于有成千上万个不同字符的几种东方语言体系来说,Unicode 字符集更有用。每一个Unicode字符占两个字节的宽度,这样一来就可以在一个字符串中使用65 336个不同的字符了。

MessageBox和显示字符串有关,同样它有两个版本,严格地说,系统中有两个定义:

MessageBoxA  Proto  hWnd:dword,lpText:dword,lpCaption:dword,uType:dword

MessageBoxW  Proto  hWnd:dword,lpText:dword,lpCaption:dword,uType:dword

虽然《Microsoft Win32 Programmer's Reference》中只有一个MessageBox定义,但User32.dll中确确实实没有MessageBox,而只有MessageBoxAMessageBoxW,那么为什么还是可以使用MessageBox呢?实际上在程序的头文件user32.inc中有一句:

MessageBox      equ     <MessageBoxA>

它把MessageBox偷梁换柱变成了MessageBoxA。在源程序中继续沿用MessageBox  为了程序的可读性以及保持和手册的一致性,但对于编译器来说,实际是在使用MessageBoxA

由于并不是每个Win32系统都支持W系列的API,在Windows 9x系列中,对Unicode是不支持的,很多的API只有ANSI版本,只有Windows NT系列才对Unicode完全支持。为了编写在几个平台中通用的程序,一般应用程序都使用ANSI版本的API函数集。

为了使程序更有移植性,在源程序中一般不直接指明使用Unicode还是ANSI版本,而是使用宏汇编中的条件汇编功能来统一替换,如在源程序中使用Messagebox,但在头文件中定义:

if      UNICODE

        MessageBox      equ     <MessageBoxW>

else

        MessageBox      equ     <MessageBoxA>

endif

所有涉及版本问题的API都可以按此方法定义,然后在源程序的头部指定UNICODE=1UNICODE=0,重新编译后就能产生不同的版本。

 

4include语句

 

对于所有要用到的API函数,在程序的开始部分都必须预先声明,但这一个步骤显然是比较麻烦的,为了简化操作,可以采用各种语言通用的解决办法,就是把所有的声明预先放在一个文件中,在用到的时候再用include语句包含进来。现在回到Win32 Hello World程序,这个程序用到了两个API函数:MessageBoxExitProcess,它们分别在User32.dllKernel32.dll中,在MASM32工具包中已经包括了所有DLLAPI函数声明列表,每个DLL对应<DLL.inc>文件,在源程序中只要使用include语句包含进来就可以了:

include         user32.inc

include         kernel32.inc

当用到其他的API函数时,只需相应增加对应的include语句。

include语句还用来在源程序中包含别的文件,当多个源程序用到相同的函数定义、常量定义,甚至源代码时,可以把相同的部分写成一个文件,然后在不同的源程序中用include语句包含进来。

编译器对include语句的处理仅是简单地把这一行用指定的文件内容替换掉而已。

include语句的语法是:

         include        文件名

       include        <文件名>

当遇到要包括的文件名和MASM的关键字同名等可能会引起编译器混淆的情况时,可以用<>将文件名括起来。

 

5. includelib语句

DOS汇编中,使用中断调用系统功能是不必声明的,处理器自己知道到中断向量表中去取中断地址。在Win32汇编中使用API函数,程序必须知道调用的API函数存在于哪个DLL中,否则,操作系统必须搜索系统中存在的所有DLL,并且无法处理不同DLL中的同名函数,这显然是不现实的,所以,必须有个文件包括DLL库正确的定位信息,这个任务是由导入库来实现的。

在使用外部函数的时候,DOS下有函数库的概念,那时的函数库实际上是静态库,静态库是一组已经编写好的代码模块,在程序中可以自由引用,在源程序编译成目标文件,最后要链接成可执行文件的时候,由link程序从库中找出相应的函数代码,一起链接到最后的可执行文件中。DOSC语言的函数库就是典型的静态库。库的出现为程序员节省了大量的开发时间,缺点就是每个可执行文件中都包括了要用到的相同函数的代码,占用了大量的磁盘空间,在执行的时候,这些代码同样重复占用了宝贵的内存。

Win32环境中,程序链接的时候仍然要使用函数库来定位函数信息,只不过由于函数代码放在DLL文件中,库文件中只留有函数的定位信息和参数数目等简单信息,这种库文件叫做导入库,一个DLL文件对应一个导入库,如User32.dll文件用于编程的导入库是User32.libMASM32工具包中包含了所有DLL的导入库。

为了告诉链接程序使用哪个导入库,使用的语句是:

      includelib        库文件名

    includelib        <库文件名>

include的用法一样,在要包括让编译器混淆的文件名时加方括号。Win32 Hello world程序用到的两个API函数MessageBoxExitProcess分别在User32.dllKernel32.dll中,那么在源程序使用的相应语句为:

includelib      user32.lib

includelib      kernel32.lib

include语句的处理不同,includelib不会把 .lib文件插入到源程序中,它只是告诉链接器在链接的时候到指定的库文件中去找而已。

3.2.3  API参数中的等值定义

再回过头来看显示消息框的语句:

invoke  MessageBox,NULL,offset szText,offset szCaption,MB_OK

uType这个参数中使用了MB_OK,这个MB_OK是什么意思呢,先来看《Microsoft Win32 Programmer's Reference》中的说明:

uType —— 定义对话框的类型,这个参数可以是以下标志的合集:

要定义消息框上显示按钮,用下面的某一个标志:

MB_ABORTRETRYIGNORE —— 消息框有三个按钮:“终止”,“重试”和“忽略”

MB_HELP —— 消息框上显示一个“帮助”按钮,按下后发送WM_HELP消息

MB_OK —— 消息框上显示一个“确定”按钮,这是默认值

MB_OKCANCEL —— 消息框上显示两个按钮:“确定”和“取消”

MB_RETRYCANCEL —— 消息框上显示两个按钮:“重试”和“忽略”

MB_YESNO —— 消息框上显示两个按钮:“是”和“否”

MB_YESNOCANCEL —— 消息框上显示三个按钮:“是”、“否”和“取消”

 

要在消息框中显示图标,用下面的某一个标志:

MB_ICONWARNING —— 显示惊叹号图标

MB_ICONINFORMATION —— 显示消息图标

MB_ICONASTERISK —— 显示危险图标

MB_ICONQUESTION —— 显示问号图标

MB_ICONSTOP —— 显示停止图标

…… 

这些是uType参数说明中的一小半,可以看出,参数中可以用的值有很多种,让我们换一个值试试看,把语句改为:

invoke MessageBox,NULL,offset szText,offset szCaption, MB_ICONWARNING or MB_YESNO

再编译执行看,屏幕上出现了一个不一样的消息框,如图3.3所示。

 

  <这些在学习VC++时经常用到,所以API到我来说比较透明。正如当初学习汇编的目的,只是更好的理解底层一些原理性的东西>



来源:电子工业出版社 作者:罗云彬

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: MASM for Windows是一种汇编语言开发工具,用于在Windows操作系统上编写和调试汇编语言程序。它可以生成可执行文件和动态链接库,支持多种指令集和调试器。使用MASM for Windows需要掌握汇编语言的基本知识,了解Windows操作系统的API和数据结构,以及熟悉MASM的语法和命令。在编写程序时,需要使用文本编辑器编写源代码,然后使用MASM编译器将源代码转换为可执行文件或动态链接库。在调试程序时,可以使用MASM提供的调试器进行单步调试、断点调试等操作,以便找出程序中的错误和问题。 ### 回答2: MASM for Windows是一款专门用来编写汇编语言程序的开发工具,它应用广泛,可以用于开发Windows系统的驱动程序、系统服务、动态链接库等系统级别的软件和程序。下面将介绍 MASム for Windows 的使用操作。 首先需要安装MASM for Windows,可以在Microsoft官方网站上下载此软件。下载完后,需要运行安装程序进行安装。安装程序很简单,只需按照提示完成即可。 安装完成后,打开MASM for Windows,可以看到程序的主界面。主界面上有菜单栏、工具栏和源代码窗口等部分。在源代码窗口中,可以输入汇编语言的源代码。在工具栏上,有编译、运行等工具按钮,可以进行编译和运行程序的操作。 编写汇编程序时,需要按照汇编指令的语法规则进行编写。在MAM for Windows中,编写的程序可以使用文本编辑器输入,也可以使用集成开发环境(IDE)编写,例如Visual Studio。 编写完毕后,可以点击编译按钮进行编译。编译完成后,可以点击运行按钮运行程序。如果程序中有错误,编译器会给出错误提示,需要修改源代码并重新编译。 除了编译和运行程序,MASM for Windows还提供了调试和优化程序的功能。可以设置断点、查看变量的值等。这些功能可以帮助程序员更好地调试和优化程序。 总之,MASM for Windows是一款很方便的汇编语言开发工具,它具有简单易用的特点,可以帮助程序员更方便地编写系统级别的程序和软件。 ### 回答3: MASM (Microsoft Macro Assembler)是一种汇编语言工具,可用于Windows平台上的汇编编程。下面是在Windows上使用MASM进行汇编编程的一些操作。 1. 安装MASM 首先,需要下载MASM的安装程序,然后安装到Windows系统中。安装完成后,MASM所在的目录将被添加到系统的PATH环境变量中。需要注意的是,为了使MASM正常工作,还需要安装Visual C++运行库。 2. 编写MASM代码 MASM的代码由一个或多个汇编指令序列组成,这些指令由汇编器读取并将其转换为机器语言。在开始编写代码之前,需要了解MASM的语法和指令。可以从互联网上找到MASM的相关教程和指南。MASM提供了一些常用的指令和宏,可以使代码更加简洁和易于维护。 3. 汇编代码 编译代码的第一步是将其汇编成目标文件。可以使用MASM提供的命令行工具,也可以使用集成开发环境(IDE)中的MASM插件。在命令行中,输入“MASM myprogram.asm”命令将会编译生成目标文件“myprogram.obj”。编译时会输出一些警告或错误信息,需要认真检查并进行修复。 4. 连接目标文件 MASM生成的目标文件需要链接到可执行文件中。链接器负责将各个模块中的代码和数据组合在一起,生成最终的可执行文件。在Windows上,可以使用Microsoft的链接器LINK进行链接操作。在命令行中,输入“LINK myprogram.obj”命令将会生成可执行文件“myprogram.exe”。 5. 运行程序 最后,可以运行生成的可执行文件。在命令行中,输入“myprogram.exe”命令即可执行程序。可以通过调试器或日志等方式观察程序的运行情况,检查程序是否符合预期。 总体来说,使用MASM进行汇编编程需要一定的基础知识和技能,但其可以产生高效、紧凑的机器代码,是实现底层系统编程、性能优化等领域的重要工具。在学习MASM时,可以参考其他程序员的经验和教程,尽可能多地积累实践经验,以提高编程水平。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

汪宁宇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值