您的位置:首页 > 其它

BCB直接访问硬件端口和物理内存 - WinIO的应用

2011-01-11 11:02 316 查看
http://www.cppfans.com/articles/system/portrw_winio.asp

(读硬盘参数和主板BIOS信息, 支持 Win9x/NT/2k/XP/2003)

(浏览
32444
次)

Victor Chen, (C++
爱好者)

附完整的源程序(本页最下面的链接)

关于直接访问端口, 有很多网站很多文章都讨论过, 但总找不到非常理想的办法。

我这里用的是 Yariv Kaplan 的 WinIo 2.0。虽然 WinIO 也有缺陷, 但是是我用过的当中最好的了。

WinIO 是免费的, 并且是开放源代码的, 可以直接到他的主页下载, 也可以在这里下载。

Yariv Kaplan 的主页: http://www.internals.com/

WinIO 的使用非常简单, 在程序的开始调用 InitializeWinIo(); 初始化 WinIO, 在程序的结束使用 ShutdownWinIo();

这样就可以在程序里直接访问端口和物理内存了。

在这里仍然用的是读硬盘参数和主板BIOS信息。

本站在《硬盘参数读取程序》这篇文章里曾经介绍过利用
WinIO 读取硬盘参数, 很多人提出程序太复杂, 并且在程序启动时调用经常无效,

在这里简化了程序, 并且改善了性能, 在程序启动时调用也可读出参数了。

按钮Button1: 硬盘参数:

型 号: MAXTOR 6L040J2

序 列 号: 662202841232

固件版本: AR1.0400

容 量: 38172 Mb

柱 面 数: 16383

磁 头 数: 16

扇 区 数: 63

缓存容量: 1818 kb

ECC 字节: 4 bytes

LBA 支持: 是

DMA 支持: 是
按钮Button2: BIOS信息:

Award Modular BIOS v6.00PG

Copyright (C) 1984-2001, Award Software, Inc.

05/14/02

05/14/2002-i815-ITE87X2-6A69RPQRS-00
有关读写端口函数 inportb 和 outportb 等函数: 在 Win2000 等 NT 内核的 OS 可直接用汇编访问端口,
但 Win9x 反而不可以

#include "WinIO.h"

//---------------------------------------------------------------------------

unsigned char inportbNT(unsigned short p) { asm mov dx, p; asm
in al, dx; return _AL; }

unsigned short inportwNT(unsigned short p) { asm mov dx, p;
asm in ax, dx; return _AX; }

unsigned long inportdNT(unsigned short p) { asm mov dx, p; asm
in eax,dx; return _EAX;}

void outportbNT(unsigned short p, unsigned char v) { asm mov
dx, p; asm mov al, v; asm out dx,al; }

void outportwNT(unsigned short p, unsigned short v) { asm mov
dx, p; asm mov ax, v; asm out dx,ax; }

void outportdNT(unsigned short p, unsigned long v) { asm mov
dx, p; asm mov eax,v; asm out dx,eax;}

//---------------------------------------------------------------------------

unsigned char inportb9x(unsigned short p) { unsigned long v
= 0; GetPortVal(p, &v, 1); return v; }

unsigned short inportw9x(unsigned short p) { unsigned long v
= 0; GetPortVal(p, &v, 2); return v; }

unsigned long inportd9x(unsigned short p) { unsigned long v
= 0; GetPortVal(p, &v, 4); return v; }

void outportb9x(unsigned short p, unsigned char v) { SetPortVal(p,v,1);
}

void outportw9x(unsigned short p, unsigned short v) { SetPortVal(p,v,2);
}

void outportd9x(unsigned short p, unsigned long v) { SetPortVal(p,v,4);
}

//---------------------------------------------------------------------------

unsigned char (*inportb)(unsigned short) = inportbNT;

unsigned short (*inportw)(unsigned short) = inportwNT;

unsigned long (*inportd)(unsigned short) = inportdNT;

void (*outportb)(unsigned short, unsigned char ) = outportbNT;

void (*outportw)(unsigned short, unsigned short) = outportwNT;

void (*outportd)(unsigned short, unsigned long ) = outportdNT;

//---------------------------------------------------------------------------

void InitPortFuncs(void)

{
OSVERSIONINFO osVer = {sizeof(OSVERSIONINFO)};

GetVersionEx(&osVer);

if(osVer.dwPlatformId
== VER_PLATFORM_WIN32_NT)
{

inportb = inportbNT;
outportb = outportbNT;
inportw
= inportwNT; outportw = outportwNT;
inportd
= inportdNT; outportd = outportdNT;
}

else
{

inportb = inportb9x;
outportb = outportb9x;
inportw
= inportw9x; outportw = outportw9x;
inportd
= inportd9x; outportd = outportd9x;
}

}
上面的程序 InitPortFuncs 就是判断操作系统是否为 NT 内核, 并且选择合适的函数来访问端口。

经过这样处理, 在 Win2000 下访问端口的速度就要比 98 的快了, Win2000 的速度比较理想。

具体程序: Button1 是读硬盘参数, Button2 是读主板BIOS信息

#include "WinIO.h"

#pragma link "WinIo_bc.lib"

//---------------------------------------------------------------------------

__fastcall TForm1::TForm1(TComponent* Owner)

: TForm(Owner)

{

bWinIoInitOK = InitializeWinIo();

if(!bWinIoInitOK)

{

Application->MessageBox("不能装载
WinIO 程序!","错误信息",MB_OK|MB_ICONSTOP);

Application->Terminate();

}

InitPortFuncs();

}

//---------------------------------------------------------------------------

__fastcall TForm1::~TForm1()

{

if(bWinIoInitOK)

ShutdownWinIo();

}

//---------------------------------------------------------------------------

bool ReadHddParams(unsigned short *params, int pn, int dn)

{

int i,IdePort[2] = {0x1f0, 0x170};
//primary & secondary IDE Controller

unsigned char HD_Selection[2]={0xa0,0xb0};
// Master Disk: 1010 0000, Slave Disk: 1011 0000

unsigned short BasePort = IdePort[pn];

for(i=0;i<500;i++) //Get HDC Status,
wait until HDC not busy

{

if((inportb(BasePort+7)&0x80)==0)

break;
//hdc is ready

Sleep(1);

}

if(i>=300)return false; //HDC no
response

outportb(BasePort+6, HD_Selection[dn]);
//master or slave hard disk

outportb(BasePort+7, 0x10); //HDD
status

for(i=0;i<300;i++) //Get HDD Status,
wait until HDD not busy

{

if((inportb(BasePort+7)&0x80)==0)

break;

Sleep(1);

}

if(i>=300)return false; //HDC no
response

if(inportb(BasePort+7)!=0x50)return
false; //HDD ready: 0101 0000

outportb(BasePort+6, HD_Selection[dn]);
//master or slave hard disk

outportb(BasePort+7, 0xec); //HDD
parameters

for(i=0;i<300;i++) //wait for parameters
retrieved

{

if(inportb(BasePort+7)==0x58)
//retrieved OK

break;

Sleep(1);

}

if(i>=300)return false; //parameters
retrieved error

for(i=0;i<256;i++)

params[i]=inportw(BasePort);

return true;

}

//---------------------------------------------------------------------------

void WordToStr(unsigned char *s, unsigned short *w, int n)
//硬盘参数转成字符串

{

int i;

for(i=0; i<n; i++)

{

s[i*2] = w[i]>>8;

s[i*2+1] =
w[i]&0x00ff;

}

s[i*2]=0;

}

//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)

{

DWORD dwOldProcessP = GetPriorityClass(GetCurrentProcess());

DWORD dwOldThreadP = GetThreadPriority(GetCurrentThread());

SetPriorityClass(GetCurrentProcess(),
REALTIME_PRIORITY_CLASS);

SetThreadPriority(GetCurrentThread(),
THREAD_PRIORITY_TIME_CRITICAL);

AnsiString idename[2] = {"IDE0","IDE1"},
diskname[2] = {"主盘","从盘"};

unsigned short params[256]; char Str[256];

for(int pn=0; pn<2; pn++) //primary
or secondary

for(int dn=0; dn<2; dn++) //master
or slave

{

Memo1->Lines->Add(idename[pn]+"
"+diskname[dn]+":");

if(ReadHddParams(params,pn,dn))

{

WordToStr(Str,params+27,20);
Memo1->Lines->Add("型 号: "+AnsiString(Str));

WordToStr(Str,params+10,10);
Memo1->Lines->Add("序 列 号: "+AnsiString(Str));

WordToStr(Str,params+23,
4); Memo1->Lines->Add("固件版本: "+AnsiString(Str));

unsigned
long LbaCap = *(unsigned long *)(¶ms[60])/2048;

unsigned
long NomCap = ((unsigned long)(params[1])*(params[3])*(params[6]))/2048;

Memo1->Lines->Add("容
量: " + AnsiString().sprintf("%lu Mb",LbaCap>NomCap?LbaCap:NomCap));

Memo1->Lines->Add(AnsiString().sprintf("柱
面 数: %u", params[1]));

Memo1->Lines->Add(AnsiString().sprintf("磁
头 数: %u", params[3]));

Memo1->Lines->Add(AnsiString().sprintf("扇
区 数: %u", params[6]));

bool
DMA = params[49]&0x0100; //D8:是否支持DMA

bool
LBA = params[49]&0x0200; //D9:是否支持LBA

Memo1->Lines->Add(AnsiString().sprintf("缓存容量:
%u kb", params[21]>>1));

Memo1->Lines->Add(AnsiString().sprintf("ECC
字节: %u bytes", params[22]));

Memo1->Lines->Add(AnsiString().sprintf("LBA
支持: %s", LBA?"是":"否"));

Memo1->Lines->Add(AnsiString().sprintf("DMA
支持: %s", DMA?"是":"否"));

}

else

{

Memo1->Lines->Add("没找到硬盘");

}

Memo1->Lines->Add("");

}

SetThreadPriority(GetCurrentThread(),
dwOldThreadP);

SetPriorityClass(GetCurrentProcess(),
dwOldProcessP);

}

//---------------------------------------------------------------------------

void __fastcall TForm1::Button2Click(TObject *Sender)

{

HANDLE hPhyMem; //char *lpInfo = (char
far *)0xf0000L;

//下面的语句让 0xf0000 地址的 65536 个字节可直接读写

char *lpInfo = MapPhysToLin((char*)0xf0000,65536,&hPhyMem);

Memo1->Lines->Add(lpInfo+0xe061);
//主板BIOS名称 0xFE061

Memo1->Lines->Add(lpInfo+0xe091);
//主板BIOS版权 0xFE091

Memo1->Lines->Add(lpInfo+0xfff5);
//主板BIOS日期 0xFFFF5

Memo1->Lines->Add(lpInfo+0xec71);
//主板BIOS序列号 0xFEC71

UnmapPhysicalMemory(hPhyMem, lpInfo);

}

//---------------------------------------------------------------------------

最后写一下 WinIO 的缺陷:

会让纯DOS版本的程序无法接受键盘和鼠标事件, 可现在用纯DOS程序很少了, 所以影响不大。


直接访问硬件端口和物理内存-下载完整的程序源代码(BCB5,可以在BCB6下编译通过)
25,438 字节 (下载
7927
次)

源代码本址下载网址:winio_源码.rar
http://files.cnblogs.com/chulia20002001/winio_%e6%ba%90%e7%a0%81.rar
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: