zoukankan      html  css  js  c++  java
  • 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);
    }
    //---------------------------------------------------------------------------

  • 相关阅读:
    Spring Cloud Hystrix Dashboard的使用 5.1.3
    Spring Cloud Hystrix 服务容错保护 5.1
    Spring Cloud Ribbon 客户端负载均衡 4.3
    Spring Cloud 如何实现服务间的调用 4.2.3
    hadoop3.1集成yarn ha
    hadoop3.1 hdfs的api使用
    hadoop3.1 ha高可用部署
    hadoop3.1 分布式集群部署
    hadoop3.1伪分布式部署
    KVM(八)使用 libvirt 迁移 QEMU/KVM 虚机和 Nova 虚机
  • 原文地址:https://www.cnblogs.com/honeynm/p/4096508.html
Copyright © 2011-2022 走看看