您的位置:首页 > 其它

使用MASM04 - Win32汇编语言012

2011-09-21 21:00 453 查看

使用MASM04

让编程改变世界

Change the world by program

调用API函数

习惯工作于DOS汇编的程序员同志都有一个愿望:如果说,能够以功能名称作为子程序名直接调用,他们愿意以生命中的十年寿命作为交换……

随着Win32的到来,他们的愿望实现了!这就是API函数,它事实上就是以一种新的方法代替了DOS下的中断。

与DOS中断相比,Win32的系统功能模块放在Windows的动态链接库(DLL)中。

DLL是一种Windows的可执行文件,采用的是和我们熟悉的.exe文件同样的PE(PortableExecutable)约定格式。

[caption id="attachment_752" align="aligncenter" width="593"]

DLL文件的原理[/caption]

关于DLL

DLL事实上只是一个大大的集装箱,装着各种系统的API函数。

应用程序在使用的时候由Windows自动载入DLL程序并调用相应的函数。

实际上,Win32的基础就是由DLL组成的。

Win32API的核心由3个DLL提供,它们是:

– KERNEL32.DLL——系统服务功能。包括内存管理、任务管理和动态链接等。

– GDI32.DLL——图形设备接口,处理图形绘制。

– USER32.DLL——用户接口服务。建立窗口和传送消息等。

当然,Win32API还包括其他很多函数,这些也是由DLL提供的,不同的DLL提供了不同的系统功能。

如使用TCP/IP协议进行网络通信的DLL是Wsock32.dll,它所提供的API称为SocketAPI;

专用于电话服务方面的API称为TAPI(TelephonyAPI),包含在Tapi32.dll中。

所有的这些DLL提供的函数组成了现在使用的Win32编程环境。

我们也经常自己打包自己的“集装箱”!

API函数的参数

在DOS下,我们演示过无数次,通过中断来调用系统“函数”,其中的“参数”是通过放在寄存器(ah)中。

Win32API是用堆栈来传递参数的,调用者把参数一个个压入堆栈,DLL中的函数程序再从堆栈中取出参数处理,并在返回之前将堆栈中已经无用的参数丢弃。

在Microsoft发布的《MicrosoftWin32Programmer’sReference》中定义了常用API的参数和函数声明。

[codesyntax lang="c"]
intMessageBox(
HWNDhWnd,           //handletoownerwindow
LPCTSTRlpText,      //textinmessagebox
LPCTSTRlpCaption,   //messageboxtitle
UINTuType           //messageboxstyle
);//注意,上边是用C语言表示!

[/codesyntax]

[caption id="attachment_753" align="aligncenter" width="570"]

API函数的参数[/caption]

上述函数声明说明了MessageBox有4个参数,这些数据类型看起来很复杂。

但有一点是很重要的,对于汇编语言来说,Win32环境中的参数实际上只有一种类型,那就是一个32位的整数,所以这些HWND,LPCTSTR和UINT实际上就是汇编中的dword(doubleword,双字型,4个字节,两个字,32位)之所以定义为不同的模样,主要是用来说明了用途。

由于Windows是用C写成的,世界上的程序员好像也是用C语言的最多,所以Windows所有编程资料发布的格式也是C格式。

上面的声明用汇编的格式来表达就是:

[codesyntax lang="asm"]
MessageBoxProtohWnd:dword,lpText:dword,lpCaption:dword,uType:dword

[/codesyntax]

在汇编中调用MessageBox函数的方法是:

[codesyntax lang="asm"]
pushuType
pushlpCaption
pushlpText
pushhWnd
callMessageBox

[/codesyntax]

在源程序编译链接成可执行文件后,callMessageBox语句中的MessageBox会被换成一个地址,指向可执行文件中的导入表的一个索引(函数名或索引号)。

导入表中指向MessageBox函数的实际地址会在程序装入内存的时候,根据User32.dll在内存中的位置由Windows系统动态填入。

使用invoke语句

API是可以调用了,另一个烦人的问题又出现了,Win32的API动辄就是十几个参数,整个源程序一眼看上去基本上都是把参数压堆栈的push指令,参数的个数和顺序很容易搞错,由此引起的莫名其妙的错误源源不断,源程序的可读性看上去也很差。

如果写的时候少写了一句push指令,程序在编译和链接的时候都不会报错,但在执行的时候必定会崩溃,原因是堆栈对不齐了。

有木有解决的办法呢?那是必须得!最好是像C语言一样,能在同一句中打入所有的参数,并在参数使用错误的时候能够提示。

好消息又来了,Microsoft终于做了一件好事,在MASM中提供了一个伪指令实现了这个功能,那就是invoke伪指令,它的格式是:
invoke函数名[,参数1][,参数2]…[,参数n]

[codesyntax lang="asm"]
invokeMessageBox,NULL,offsetszText,offsetszCaption,MB_OK

[/codesyntax]

注意,invoke并不是80386处理器的指令,而是一个MASM编译器的伪指令,在编译的时候它把上面的指令展开成我们需要的4个push指令和一个call指令,同时,进行参数数量的检查工作,如果带的参数数量和声明时的数量不符,编译器报错:errorA2137:toofewargumentstoINVOKE

编译时看到这样的错误报告,首先要检查的是有没有少写一个参数。

对于不带参数的API调用,invoke伪指令的参数检查功能可有可无。

所以既可以用callAPI_Name这样的语法,也可以用invokeAPI_Name这样的语法。

API函数的返回值

有的API函数有返回值,如MessageBox定义的返回值是int类型的数,返回值的类型对汇编程序来说也只有dword一种类型,它永远放在eax中。

如果要返回的内容不是一个eax所能容纳的,Win32API采用的方法一般是返回一个指针,或者在调用参数中提供一个缓冲区地址,干脆把数据直接返回到缓冲区中去。

[buy] 获得所有教学视频、课件、源代码等资源打包 [/buy]
[Downlink href='http://urlxf.qq.com/?mUJJziB']视频下载[/Downlink]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: