Win32汇编 API的调用

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位的整数,所有这些HWNDLPCTSTRUINT实际上就是汇编中的dworddouble 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编译器的伪指令,在编译的时候它把上面的指令展开成我们需要的4push指令和1call指令,同时,进行参数数量的检查工作,如果带的参数数量和声明时的数量不符,编译器会报错

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: 是函数声明的伪指令,

距离: 可以是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个不同的字符了。

 

Win32汇编中的的Unicode与多字节的处理是这样的:

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

if UNICODE

MessageBox equ <MessageBoxW>

else

MessageBox equ <MessageBoxA>

endif

 

然后在源程序的头部指定UNICODE=1UNICODE=0,重新编译后就能产生不同的版本。

 

4include语句

Include一些头文件 这些就可以不说了 C的一样.

当然, Win32中的头文件与C的头文件格式是不一样的.

MASM32工具包中已经包括了所有DLLAPI函数声明列表,每个DLL对应<DLL.inc>文件,

在源程序中只要使用include语句包含进来就可以了:

include user32.inc

include kernel32.inc

 

include语句的语法是:

include 文件名

include <文件名>

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

 

5. includelib语句

使用DLL 连接当然需要lib文件了, 这个和C是一样的.

MASM32工具包中包含了所有DLL的导入库。

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

includelib 库文件名

includelib <库文件名>

 

 

 

 

 

 

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值