计算-开发-设计-人文
www.52myshare.com

Windows中直接对I/O端口和物理内存存取操作的方法

很多从事硬件开发的工程师,经常会碰到对I/O端口和物理地址直接进行存取操作的场合,对于在Windows应用程序中直接对I/O端口和物理地址进行读写操作,不借助特殊的工具是难以完成的。这里介绍一个可以直接在Windows程序中读写端口和物理地址的工具,供各位读者借鉴。

WinIO是一个函数链接库Winio.dll,利用它加载一个内核模式的设备驱动程序,利用几种底层编程技巧,使得Windows应用程序可以直接对I/O端口和物理内存进行存取,从而绕过了Windows系统的保护机制。

WinIO可以直接到官方网站:http://www.internals.com/去下载,里面包含了帮助文档和源码。

WinNT/2000/XP下,WinIO函数库只允许被具有管理者权限的应用程序调用。如果使用者不是以管理者的身份进入的,则WinIO.DLL不能够被安装,也不能激活WinIO驱动器。

64位WIN系统下,还需要对WinIo64.sys做交叉签名才能正常加载。也可以省去动态加载DLL,用官方的DLL源码,编译生成WinIo.lib,添加一行#pragmacomment(lib,”WinIo.lib”),修改一下winio.h,然后include就可以了。

WionIO函数库提供常用函数是:

(1)bool _stdcall InitializeWinIo();
本函数初始化WioIO函数库。必须在调用所有其它功能函数之前调用本函数。如果函数调用成功,返回值为非零值,如果调用失败,则返回值为0。

(2)void _stdcall ShutdownWinIo();
本函数在内存中清除WinIO库,必须在中止应用函数之前或者不再需要WinIO库时调用。
bool _stdcall GetPortVal(WORD wPortAddr, PDWORD pdwPortVal, BYTE bSize);
使用此函数从一个输入或输出端口读取一个字节/字/双字数据。
参数:
wPortAddr – 输入输出端口地址
pdwPortVal – 指向双字变量的指针,接收从端口得到的数据。
bSize – 需要读的字节数,可以是1 (BYTE), 2 (WORD) or 4 (DWORD).
如果调用成功,则返回非零值,如果函数调用失败,则函数返回值为零。

(3)bool _stdcall GetPortVal(WORD wPortAddr, PDWORD pdwPortVal, BYTE bSize);
使用此函数从一个输入或输出端口读取一个字节/字/双字数据。
参数:
wPortAddr – 输入输出端口地址
pdwPortVal – 指向双字变量的指针,接收从端口得到的数据。
bSize – 需要读的字节数,可以是1 (BYTE), 2 (WORD) or 4 (DWORD).
如果调用成功,则返回非零值。如果函数调用失败,则函数返回值为零。

(4)bool _stdcall SetPortVal(WORD wPortAddr, DWORD dwPortVal, BYTE bSize);
使用本函数将一个字节/字/双字的数据写入输入或输出接口。
参数:
wPortAddr – 输入输出口地址
dwPortVal – 要写入口的数据
bSize – 要写的数据个数,可以是 1 (BYTE), 2 (WORD) or 4 (DWORD).
如果调用成功,则返回非零值。

(5)PBYTE _stdcall MapPhysToLin(PBYTE pbPhysAddr, DWORD dwPhysSize, HANDLE *pPhysicalMemoryHandle)
使用此函数将物理内存的一部分映射到一个32位应用程序的线性地址空间。
下面是一个例子:
PBYTE pbLinAddr;
HANDLE PhysicalMemoryHandle;
pbLinAddr = MapPhysToLin(0xA0000, 65536, &PhysicalMemoryHandle);
该函数将把物理地址范围为0xA0000 – 0xAFFFF的地址空间映射到与应用程序对应的线性地址空间。 返回值为一个与物理地址0xA0000相关的线性地址。如         果出现错误,则返回值为NULL。
参数:
pbPhysAddr – 指向物理地址的指针
dwPhysSize – 需要映射的字节数
pPhysicalMemoryHandle – 变量指针,如果调用成功,负责接收物理内存句柄。随后本句柄在调用UnmapPhysicalMemory函数时作为其第一个参数。

(6)bool _stdcall UnmapPhysicalMemory(HANDLE PhysicalMemoryHandle, PBYTEpbLinAddr)
使用本函数解除原先使用MapPhysToLin函数映射的一段线性物理内存区域,该区域被映射到应用程序所属的线性地址空间。Windows 9x 应用程序不需要调用此函数。
参数:
PhysicalMemoryHandle – 物理内存区域所属的句柄,此参数由对MapPhysToLin函数的调用返回。
pbLinAddr – MapPhysToLin函数调用返回的线性地址。
bool _stdcall GetPhysLong(PBYTE pbPhysAddr, PDWORD pdwPhysVal);
从指定的物理地址读取一个双字数据。
参数:
pbPhysAddr – 指向物理地址的指针。
pdwPhysVal – 指向一个双字变量的指针,接收从物理内存中传来的数据。
如果此函数调用成功,返回一个非零值。
如果函数调用失败,则返回一个零值。
bool _stdcall SetPhysLong(PBYTE pbPhysAddr, DWORD dwPhysVal);
将一个双字型数据写入指定的物理地址。
参数:
pbPhysAddr – 指向物理地址的指针。
pdwPhysVal – 指定待写入物理内存地址出的双字型数据。
如果此函数调用成功,返回一个非零值。
如果函数调用失败,则返回一个零值。

调用WinIo.dll中的函数时,无需安装,你只需要把这3个文件复制到与你的程序相同的文件夹下就可以使用了。用法很简单,先用里面的InitializeWinIo函数安装驱动程序,然后就可以用GetPortVal来读取端口或者用SetPortVal来写入端口了。

谢谢阅读。

分享到:更多 ()
上一篇: 下一篇:

发表评论 抢沙发

评论前必须登录!

 

传播知识 分享技术

了解麦虾合作机会