• BCB直接访问硬件端口和物理内存



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

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

    关于直接访问端口, 有很多网站很多文章都讨论过, 但总找不到非常理想的办法。
    我这里用的是 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 *)(&params[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);
    }
    //---------------------------------------------------------------------------
    BCB直接访问硬件端口和物理内存 - WinIO的应用

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

    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 *)(&params[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);
    }
    //---------------------------------------------------------------------------

  • 相关阅读:
    .NET体系结构
    命名空间和程序集
    网站不加www和.com 也能访问的设置
    如何从本机直接复制粘贴文件到服务器
    无法访问已释放的对象。 对象名:“System.ServiceModel.Channels.HttpChannelFactory+HttpRequestChannel”。
    silverlight 数据库更新,UI控件同步更新
    Apache Solr使用自定义QParser后同义词扩展及Token去重的感悟
    Apache Nutch 1.3 学习笔记十(插件机制分析)
    Apache Nutch 1.3 学习笔记十(Ntuch 插件机制简单介绍)
    Apache Nutch 1.3 学习笔记八(LinkDb)
  • 原文地址:https://www.cnblogs.com/honeynm/p/4096508.html
Copyright © 2020-2023  润新知