您的位置:首页 > 其它

Win32汇编 API的调用

2011-04-16 11:04 351 查看
Win32汇编 API的调用

 
1.       在Win32汇编中 调用多参数的函数时 传参是通过push参数到堆栈来实现调用的.
Win32 API是用堆栈来传递参数的,调用者把参数一个个压入堆栈,DLL中的函数程序再从堆栈中取出参数处理,并在返回之前将堆栈中已经无用的参数丢弃。例如:
int MessageBox(
    HWND hWnd,                   // handle to owner window
    LPCTSTR lpText,             // text in message box
    LPCTSTR lpCaption,          // message box title
    UINT uType                 // message box style
);
Library: Use User32.lib.
在C中调用MessageBox 就很简单了传递4个指定类型的参数.
对于汇编语言来说,Win32环境中的参数实际上只有一种类型,那就是一个32位的整数,所有这些HWND,LPCTSTR和UINT实际上就是汇编中的dword(double word),之所以定义为不同的模样,是用来说明用途。
上面的声明用汇编的格式来表达就是:
MessageBox Proto hWnd : dword, lpText : dword, lpCaption:dword, uType : dword
有了函数原型的定义以后,就是调用的问题了,Win32 API调用中要把参数放入堆栈,顺序是最后一个参数最先进栈,在汇编中调用MessageBox函数的方法是:
push    uType
push    lpCaption
push    lpText
push    hWnd
call    MessageBox
 
在源程序编译链接成可执行文件后,call MessageBox语句中的MessageBox会被换成一个地址,指向可执行文件中的导入表,导入表中指向MessageBox函数的实际地址会在程序装入内存的时候,根据User32.dll在内存中的位置由Windows系统动态填入。
 
1. 使用invoke语句
为了调用API的方便, MASM中加入了伪指令invoke
在MASM中提供了一个伪指令实现了这个功能,那就是invoke伪指令,它的格式是:
    invoke  函数名[,参数1][,参数2]……
对MessageBox的调用在MASM中可以写成:
invoke  MessageBox, NULL, offset szText, offset szCaption, MB_OK or MB_ICONWARNING
 
注意,invoke并不是80386处理器的指令,而是一个MASM编译器的伪指令,在编译的时候它把上面的指令展开成我们需要的4个push指令和1个call指令,同时,进行参数数量的检查工作,如果带的参数数量和声明时的数量不符,编译器会报错:
error A2137: too few arguments to INVOKE
对于不带参数的API调用,invoke伪指令的参数检查功能可有可无,所以既可以用call API_Name这样的语法也可以用invoke API_Name这样的语法。
 
2. API函数的返回值
 
有的API函数有返回值,如MessageBox定义的返回值是int类型的数,返回值的类型对汇编程序来说也只有dword一种类型,它永远放在eax中。如果要返回的内容不是一个eax所能容纳的,Win32 API采用的方法一般是返回一个指针,或者在调用参数中提供一个缓冲区地址,干脆把数据直接返回到缓冲区中去。
 
3. 函数的声明
在调用API函数的时候,函数原型也必须预先声明。声明函数的格式是:
函数名 proto [距离] [语言] [参数1]:数据类型,[参数2]:数据类型,……
proto: 是函数声明的伪指令,
距离: 可以是NEAR,FAR,NEAR16,NEAR32,FAR16或FAR32,Win32中只有一个平坦的段,无所谓距离,所以在定义时是忽略的;
语言: 就是 .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个不同的字符了。
 
Win32汇编中的的Unicode与多字节的处理是这样的:
为了使程序更有移植性,在源程序中一般不直接指明使用Unicode还是ANSI版本,而是使用宏汇编中的条件汇编功能来统一替换,如在源程序中使用Messagebox,但在头文件中定义:
if UNICODE
MessageBox equ <MessageBoxW>
else
MessageBox equ <MessageBoxA>
endif
 
然后在源程序的头部指定UNICODE=1或UNICODE=0,重新编译后就能产生不同的版本。
 
4.include语句
Include一些头文件 这些就可以不说了 和C的一样.
当然, Win32中的头文件与C的头文件格式是不一样的.
在MASM32工具包中已经包括了所有DLL的API函数声明列表,每个DLL对应<DLL名.inc>文件,
在源程序中只要使用include语句包含进来就可以了:
include user32.inc
include kernel32.inc
 
include语句的语法是:
include 文件名
或 include <文件名>
当遇到要包括的文件名和MASM的关键字同名等可能会引起编译器混淆的情况时,可以用<>将文件名括起来。
 
5. includelib语句
使用DLL时 连接当然需要lib文件了, 这个和C是一样的.
MASM32工具包中包含了所有DLL的导入库。
为了告诉链接程序使用哪个导入库,使用的语句是:
includelib 库文件名
或 includelib <库文件名>
 
 

 

 

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息