编程技术、软件应用与系统模拟

(Programming, Applicaiton and Simulation)



本站目录

 

首页
ASP/Access/IIS
DELPHI/PASCAL
PASCAL高级编程
C语言编程实例
WORD
Excel
MATLAB
MINITAB讲座
Windows
DOS
SAS
生物系统模拟
土壤水分剖析器
其他



镜像站点

 

主站
北美镜象站
欧洲镜象站(1)
欧洲镜象站(2)

本站 Google

[搜索]  [站内导航]
座右铭:
只做有益人类的事
不做有害人类的事


CMOS内存的读写和修改

一、CMOS内存信息详解

一般的PC/AT、286、386、486等微机均配有CMOS芯片,CMOS芯片包含了一个实时钟和64个字节的CMOS内存。
在CMOS内存中,0-0DH为实时钟的有关信息,0E-3FH包含计算机的硬件配置信息,如常规内存的大小、扩展
内存的大小、软盘的类型、固定盘的类型及其物理参数、显示器的类型等,这些参数与计算机能否正常工作具
有密切的关系,另外还有计算机的开机口令和其它辅助设置信息。表1列出了CMOS内存各字节的用途。
                    表1  CMOS内存配置信息的含义
┌───┬──────┬──────────────────────┐
│地 址*│  功    能  │     说                              明     │
├───┼──────┼──────────────────────┤
│ 0,1  │秒,秒报警   │                                            │
│ 2,3  │分,分报警   │                                            │
│ 4,5  │时,时报警   │                                            │
│   6  │星期几      │                                            │
│7,8,9 │日,月,年    │                                            │
│   A  │状态寄存器A │                                            │
│   B  │状态寄存器B │                                            │
│   C  │状态寄存器C │                                            │
│   D  │状态寄存器D │0=电池失效,80=电池有效                      │
│   E  │诊断状态    │                                            │
│   F  │关机状态    │由上电诊断定义                              │
│  10  │软驱        │高4位为A驱,低4位为B驱,0=无,1=360KB,         │
│      │            │       2=1.2KB,4=1.44KB,6=720KB             │
│  11  │保留        │                                            │
│  12  │固定盘      │高4位为C驱,低4位为D驱,0=无,F=用户定义盘,    │
│      │            │       其它为系统定义盘                     │
│  13  │保留        │                                            │
│  14  │设备状态    │标志驱动器数、显示器类型、有无数学处理器等  │
│ 15-16│内存        │以KB计的常规内存数,100H=256KB,200H=512KB,   │
│      │            │           280H=640KB                       │
│ 17-18│扩展内存    │以KB计的扩展内存数,200H=512KB,400H=1024KB等 │
│  19  │C盘类型数   │根据具体硬盘类型而定                        │
│  1A  │D盘类型数   │根据具体硬盘类型而定                        │
│ 1B-1C│保留        │                                            │
│ 1D-1E│C盘柱体数   │1D-2CH只有当硬盘为用户自定义类型时起作用    │
│  1F  │C盘面数     │                                            │
│ 20-21│C盘WP       │                                            │
│ 22-23│C盘LZ       │                                            │
│  24  │C盘每柱扇区 │                                            │
│ 25-26│D盘柱体数   │                                            │
│  27  │D盘面数     │                                            │
│ 28-29│D盘WP       │                                            │
│ 2A-2B│D盘LZ       │                                            │
│  2C  │D盘每柱扇区 │                                            │
│  2D  │保留        │                                            │
│ 2E-2F│校验和      │为10-2DH共30个字节的和数,2EH为高位,2FH为低位│
│ 30-31│扩展内存    │                                            │
│  32  │日期的世纪数│BCD码的世纪值,如1995年的世纪数为19          │
│  33  │标志信息    │                                            │
│ 34-3F│保留        │                                            │
└───┴──────┴──────────────────────┘
* 地址栏均为16进制表示

二、读写CMOS内存的方法

CMOS内存的地址口和数据口的口地址分别为70H和71H。在对CMOS内存进行写操作时,首先将要写入的CMOS内
存的地址送到口地址70H,再将要写入的数据送口地址71H。在对CMOS内存进行读操作时,首先将要读出的
CMOS内存的地址送到口地址70H,再从口地址71H读出数据到AL寄存器。

三、程序设计与使用

为了方便系统信息丢失后CMOS信息的恢复,作者用TURBO C 2.0设计了一个CMOS.C的程序,它可以将
CMOS内存中的信息直接写入文件,也可以把文件中的信息写入CMOS内存,同时可以对CMOS内存中的信息进行编
辑修改,并重新写回CMOS内存。它不仅解决了没有SETUP程序的计算机在加电时不能设置CMOS内存的问题,同
时解决了CMOS信息的保存和恢复问题,是广大计算机用户的一个好帮手。
该程序的使用很简单,在DOS提示符下打CMOS,即显示该程序的使用方法,具体使用方法是:
          CMOS [/开关]
开关有3个:
R --- 读取CMOS内存信息,并将其存入CMOS.DAT的文件,共占64个字节。
W --- 从CMOS.DAT中读取信息,并将其写入CMOS内存。注意这样写入的CMOS信息,其时间和日期是不正确的
,写完之后应当用DOS命令DATE和TIME设置正确的日期和时间。
M --- 从CMOS中读取当前信息,进行修改,然后将其写入CMOS内存和CMOS.DAT的文件。

四、源程序清单

/********************************************************/
/*  程序名称: CMOS.C 1.0                                */
/*  作    者: 董占山                                    */
/*  完成日期: 1995-10-17                                */
/*  用    途: 读、写、修改CMOS内存信息                  */
/*  编译方法: 用下列命令编译连接可以得到CMOS.COM:       */
/*  tcc -mt cmos                                        */
/*  tlink c:\tc\lib\c0t+cmos,cmos,,c:\tc\lib\cs\lib /t  */
/********************************************************/

#include <stdio.h>
#include <ctype.h>
#include <string.h>

struct hdinfo {            /* 硬盘物理参数结构体 */
   unsigned int Cylinder;  /* 硬盘柱体数 */
   unsigned char Head;     /* 面数 */
   unsigned int WP;
   unsigned int LZ;
   unsigned char Sector;   /* 扇区数 */
   };

struct TCMOSStruc          /* CMOS RAM信息结构体 */
   {
   unsigned char Seconds;      /* 实时钟秒数 */
   unsigned char SecondAlarm;  /* 秒报警 */
   unsigned char Minutes;      /* 实时钟分数 */
   unsigned char MinuteAlarm;  /* 分报警 */
   unsigned char Hours;        /* 实时钟小时数 */
   unsigned char HourAlarm;    /* 时报警 */
   unsigned char DayOfWeek;    /* 周几 */
   unsigned char DayOfMonth;   /* 号数 */
   unsigned char Month;        /* 月份 */
   unsigned char Year;         /* 年份 */
   unsigned char StatusRegA;   /* 状态寄存器A */
   unsigned char StatusRegB;   /* 状态寄存器B */
   unsigned char StatusRegC;   /* 状态寄存器C */
   unsigned char StatusRegD;   /* 状态寄存器D */
   unsigned char DiagStatus;   /* 诊断状态 */
   unsigned char ShutDownStatus; /* 关机状态 */
   struct {
     unsigned FloppyDrive2 : 4;/* 第二软驱的类型 */
     unsigned FloppyDrive1 : 4;/* 第一软驱的类型 */
   } fd;
   unsigned char Reserved1;    /* 保留 */
   struct {
     unsigned FixedDrive2 : 4; /* 第二硬盘的类型 */
     unsigned FixedDrive1 : 4; /* 第一硬盘的类型 */
   } hd;
   unsigned char Reserved2;    /* 保留 */
   struct {
      unsigned diskdrv : 1;    /* 磁盘驱动器 */
      unsigned mpu : 1;	       /* 数学处理器 */
      unsigned  : 2;           /* 保留 */
      unsigned videotype : 2;  /* 当前显示类型 */
      unsigned numdrive : 2;   /* 磁盘驱动器的数目 */
   } equipment;
   unsigned int RAM;           /* 基本内存KB数 */
   unsigned int XMS;           /* 扩充内存KB数 */
   unsigned char FixedDriveType1; /* 驱动器C扩展字节 */
   unsigned char FixedDriveType2; /* 驱动器D扩展字节 */
   unsigned int Reserved3;     /* 保留 */
   struct hdinfo hd1;          /* 硬盘C的物理参数 */
   struct hdinfo hd2;          /* 硬盘D的物理参数 */
   unsigned char Sys;          /* 系统字节 */
   unsigned int CheckSum;      /* 校验和 */
   unsigned int XMS1;          /* 扩展内存KB数 */
   unsigned char DateCentury;  /* 世纪的BCD值 */
   unsigned char InfoFlags;    /* 信息标志 */
   unsigned char Reserved4[4]; /* 保留 */
   unsigned char password[8];  /* 口令字节 */
   };

struct TCMOSStruc CMOSRec;

/* 获取文件名函数 */
char *getfilename()
{
  char ch,flnm[80];
  printf("\nPlease input the drive name (A/B/C/D): ");
  while ((ch=getchar())=='\n');
  printf("\n");
  flnm[0]=ch;
  flnm[1]='\0';
  strcat(flnm,":\\CMOS.DAT");
  return flnm;
}

/* 从文件(CMOS.DAT)中读出信息 */
void ReadFile()
{
  FILE *f1;
  char flnm[80];
  strcpy(flnm,getfilename());
  if ((f1 = fopen(flnm,"rb"))==NULL) { /* 打开一个二进制文件 */
    printf("File not found !");
    exit(0);
    }
  fread(&CMOSRec,sizeof(CMOSRec),1,f1); /* 从文件中读CMOS内存信息 */
  fclose(f1);
}

/* 将从CMOS内存中读出的信息写入文件 */
void WriteFile()
{
  FILE *f1;
  char flnm[80];
  strcpy(flnm,getfilename());
  if ((f1 = fopen(flnm,"wb"))==NULL) { /* 建立一个二进制文件 */
     printf("File does not opened !");
     exit(1);
     }
  fwrite(&CMOSRec,sizeof(CMOSRec),1,f1); /* 写CMOS内存信息记录到文件 */
  fclose(f1);
}

/* 从CMOS内存中读信息 */
void ReadCMOS()
{
  asm mov di,offset CMOSRec
  asm mov cx,0x40
  asm mov ah,0
  asm mov bx,0
  asm mov dx,0x70 /* CMOS口地址 */
l1:
  asm mov al,ah
  asm out dx,al
  asm inc dx
  asm in al,dx
  asm mov BYTE PTR [di+BX],al
  asm inc ah
  asm inc bx
  asm dec dx
  asm loop l1
}

/* 向CMOS内存写入信息 */
void WriteCMOS()
{
  asm mov di,offset CMOSRec
  asm MOV CX,0x40
  asm MOV AH,0
  asm MOV BX,0
  asm MOV DX,0x70
_L1:
  asm MOV AL,AH
  asm OUT DX,AL
  asm MOV AL,BYTE PTR [di+BX]
  asm INC DX
  asm OUT DX,AL
  asm INC AH
  asm INC BX
  asm DEC dX
  asm loop _L1
}

/* 显示软盘信息 */
void DisplayFloppyDrive(FloppyDriveType,Order)
unsigned char FloppyDriveType,Order;
{
  if (FloppyDriveType != 0) {
    printf("\nFloppy Drive %d : ",Order);
    switch (FloppyDriveType) {
      case 1 : printf("360KB 5.25'");break;
      case 2 : printf("1.2MB 5.25'");break;
      case 4 : printf("1.44MB 3.5'");break;
      case 6 : printf("720KB 3.5'");break;
    }
  }
}

/* 显示硬盘信息 */
void DisplayHardDiskInfo(HDType,HDInfoRec,Order)
unsigned char HDType;
struct hdinfo HDInfoRec;
unsigned char Order;
{
    printf("\nFixed Drive %d: %d",Order,HDType);
    printf("\n  Cylinder : %d",HDInfoRec.Cylinder);
    printf("\n  Head : %d",HDInfoRec.Head);
    printf("\n  Sector: %d",HDInfoRec.Sector);
    printf("\n  LZ: %d",HDInfoRec.LZ);
    printf("\n  WP: %d",HDInfoRec.WP);
}

/* 显示CMOS内存信息 */
void DisplayCMOS()
{
  int i;
  printf("\nCMOS RAM information:");
  printf("\nDate(MM-DD-YY): %d%d-%d%d-%d%d",CMOSRec.Month>>4,CMOSRec.Month & 0xf,
	       CMOSRec.DayOfMonth>>4,CMOSRec.DayOfMonth & 0xf,
	       CMOSRec.Year>>4,CMOSRec.Year & 0xf);
  printf("\nTime(HH:MM:SS): %d%d:%d%d:%d%d",CMOSRec.Hours>>4,CMOSRec.Hours & 0xf,
	       CMOSRec.Minutes>>4,CMOSRec.Minutes & 0xf,
	       CMOSRec.Seconds>>4,CMOSRec.Seconds & 0xf);
  printf("\nConventional Memory: %d KB",CMOSRec.RAM);
  printf("\nExtended Memory: %d KB",CMOSRec.XMS);
  if (CMOSRec.hd.FixedDrive1 != 0) DisplayHardDiskInfo(CMOSRec.FixedDriveType1,CMOSRec.hd1,1);
  if (CMOSRec.hd.FixedDrive2 != 0) DisplayHardDiskInfo(CMOSRec.FixedDriveType2,CMOSRec.hd2,2);
  DisplayFloppyDrive(CMOSRec.fd.FloppyDrive1,1);
  DisplayFloppyDrive(CMOSRec.fd.FloppyDrive2,2);
  printf("\nScan code of password:");
  for (i=0;i<8;++i) printf(" %d",CMOSRec.password[i]);
  printf("\nThe number of disk drives : %d",CMOSRec.equipment.numdrive);
  printf("\nVideo Type : %d",CMOSRec.equipment.videotype);
  printf("\nMath co-processor present :");
  if (CMOSRec.equipment.mpu==1) printf("YES"); else printf("NO");
  printf("\nDisk drives : %d",CMOSRec.equipment.diskdrv);
}

/* 修改硬盘信息 */
void ModifyHDParam(HDType,HDInfoRec,Order)
unsigned char *HDType;
struct hdinfo *HDInfoRec;
unsigned char Order;
{
    int i,j;
    printf("\nType of Fixed Disk %d : (%d) : ",Order,*HDType);
      scanf("%d",HDType);
    printf("\n  Cylinder (%d) : ",HDInfoRec->Cylinder);
      scanf("%d",&HDInfoRec->Cylinder);
    printf("\n  Head (%d) : ",HDInfoRec->Head);
      scanf("%d",&i);
      HDInfoRec->Head = i;
    printf("\n  Sector (%d) : ",HDInfoRec->Sector);
      scanf("%d",&j);
      HDInfoRec->Sector = j;
    printf("\n  LZ  (%d) : ",HDInfoRec->LZ);
      scanf("%d",&HDInfoRec->LZ);
    printf("\n  WP  (%d) : ",HDInfoRec->WP);
      scanf("%d",&HDInfoRec->WP);
}

/* 修改软盘信息 */
void ModifyFDParam(FloppyDriveType,Order)
unsigned char FloppyDriveType,Order;
{
  unsigned char i;
  printf("\nFloppy Drive %d (",Order);
  switch (FloppyDriveType) {
    case 1 : printf("1---360KB 5.25') :");break;
    case 2 : printf("2---1.2MB 5.25') :");break;
    case 4 : printf("4---1.44MB 3.5') :");break;
    case 6 : printf("6---720KB 3.5') :");break;
    }
  while ((i=getchar())=='\n');
  if (Order==1)
    CMOSRec.fd.FloppyDrive1=i;
  else
    CMOSRec.fd.FloppyDrive2=i;
}

/* 修改协处理器信息 */
void ModifyMPU()
{
  char ch;
  printf("Is there a math co-processor (Y/N) :");
  while ((ch=getchar())=='\n');
  if ((ch=='Y') || (ch=='y'))
    CMOSRec.equipment.mpu=1;
  else
    CMOSRec.equipment.mpu=0;
}

/* 修改CMOS内存信息 */
void ModifyCMOS()
{
  unsigned int i;
  unsigned char *data,temp;
  data = &CMOSRec;
  printf("\nPlease input CORRECT CMOS information !!!\n");
  printf("\nConventional Memory (%d KB) : ",CMOSRec.RAM);
  scanf("%d",&CMOSRec.RAM);
  printf("\nExtended Memory (%d KB) : ",CMOSRec.XMS);
  scanf("%d",&CMOSRec.XMS);
  if (CMOSRec.hd.FixedDrive1 != 0) ModifyHDParam(&CMOSRec.FixedDriveType1,&CMOSRec.hd1,1);
  if (CMOSRec.hd.FixedDrive2 != 0) ModifyHDParam(&CMOSRec.FixedDriveType2,&CMOSRec.hd2,2);
  if (CMOSRec.FixedDriveType1!=0) CMOSRec.hd.FixedDrive1 = 0xf;
  if (CMOSRec.FixedDriveType2!=0) CMOSRec.hd.FixedDrive2 = 0xf;
  ModifyFDParam(CMOSRec.fd.FloppyDrive1,1);
  ModifyFDParam(CMOSRec.fd.FloppyDrive2,2);
  ModifyMPU();
  CMOSRec.CheckSum = 0;
  for (i=16;i<46;++i) CMOSRec.CheckSum+=data[i]; /* 计算校验和 */
  temp = data[46];
  data[46] = data[47];
  data[47] = temp;
}

/* 显示程序帮助信息 */
void help()
{
  printf("Syntex:\n");
  printf("    CMOS /R --- read information from CMOS RAM \n");
  printf("                and write it to CMOS.DAT file \n");
  printf("    CMOS /W --- read configuration information from CMOS.DAT\n");
  printf("                and write it to CMOS RAM\n");
  printf("    CMOS /M --- modify CMOS information and save it\n");
  printf("Floppy Drive Type:\n");
  printf("    1 : 360KB 5.25'\n");
  printf("    2 : 1.2MB 5.25'\n");
  printf("    4 : 1.44MB 3.5'\n");
  printf("    6 : 720KB 3.5'");
}

/* 主程序 */
main(argn,argc)
char *argc[];
int argn;
{
  char ch;
  char *temp;
  printf("CMOS Proctector 1.00, Copyright (c) 1995 Dong Zhanshan\n");
  if (argn == 2)
  {
    temp = argc[1];
    ch = toupper(temp[1]);
    switch (ch) {
      case 'R' : ReadCMOS();  /* 读CMOS内存信息,并写入文件 */
		 DisplayCMOS();
		 WriteFile();
		 break;
      case 'W' : ReadFile();  /* 从文件中读CMOS信息,并写入CMOS内存中 */
		 DisplayCMOS();
		 WriteCMOS();
		 break;
      case 'M' : ReadCMOS();  /* 读CMOS内存读取信息,并进行修改, */
		 ModifyCMOS();/* 然后再写回CMOS内存 */
		 DisplayCMOS();
		 WriteFile();
		 WriteCMOS();
		 break;
      default  : help();
    }
  }
  else help();
  return 0;
}

© 1998-, 董占山, 版权所有。
转载文章请注明出处(www.sunfinedata.com/articles)。