一、CMOS內存信息詳解
一般的PC/AT、286、386、486等微機均配有CMOS芯片,CMOS&127;芯片包含了一個實時鐘和64個字節的CMOS內存。在CMOS內存中,0-0DH為實時鐘的有關信息,0E-&127;3FH包含計算機的硬件配置信息,如常規內存的大小、擴展內存的大小、&127;軟盤的類型、固定盤的類型及其物理參數、顯示器的類型等,這些參數與計算機能否正常工作具有密切的關系,另外還有計算機的開機口令和其它輔助設置信息。表1列出了&127;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,&127;再將要寫入的數據送口地址71H。在對CMOS內存進行讀操作時,首先將要讀出的CMOS內存的地址送到口地址70H,再從口地址71H讀出數據到AL寄存器。
三、程序設計與使用
為了方便系統信息丟失后CMOS信息的恢復,作者用BORLAND PASCAL&127;設計了一個CMOS.PAS的程序,它可以將CMOS內存中的信息直接寫入文件,也可以把文件中的信息寫入CMOS內存,同時可以對CMOS內存中的信息進行編輯修改,并重新寫回CMOS內存。它不僅解決了沒有SETUP程序的計算機在加電時不能設置CMOS內存的問題,同時解決了CMOS信息的保存和恢復問題,是廣大計算機用戶的一個好幫手。 該程序的使用很簡單,在DOS提示符下打CMOS,即顯示該程序的使用方法,&127;具體使用方法是:
CMOS [/開關]
開關有3個: R --- 讀取CMOS內存信息,并將其存入CMOS.DAT的文件,共占64個字節。 W --- 從CMOS.DAT中讀取信息,并將其寫入CMOS內存。&127;注意這樣寫入的CMOS信息,其時間和日期是不正確的,寫完之后應當用DOS命令DATE和TIME&127;設置正確的日期和時間。 M --- 從CMOS中讀取當前信息,進行修改,然后將其寫入CMOS內存和CMOS.DAT的文件。
四、程序清單
由于篇幅的限制,程序中略去了用TURBO &127;VISION&127;編寫的程序界面部分。 program CMOS; type TCMOSType = record Seconds : byte; SecondAlarm : byte; Minutes : byte; MinuteAlarm : byte; Hours : byte; HourAlarm : byte; DayOfWeek : byte; DayOfMonth : byte; Month : byte; Year : byte; StatusRegA : byte; StatusRegB : byte; StatusRegC : byte; StatusRegD : byte; DiagStatus : Byte; ShutDownStatus : Byte; FloppyDrive : byte; Reserved1 : byte; FixedDrive : Byte; Reserved2 : byte; Equipment : byte; RAM : word; XMS : word; FixedDriveType1 : byte; FixedDriveType2 : byte; Reserved3 : word; Cylinder1 : word; Head1 : byte; WP1 : word; LZ1 : word; Sector1 : byte; Cylinder2 : word; Head2 : byte; WP2 : word; LZ2 : word; Sector2 : byte; Sys : byte; CheckSum : word; XMS1 : word; DateCentury : byte; InfoFlags : byte; Reserved4: array[1..12] of byte; end; TByte64 = array[1..64] of byte; TCMOS = object CMOSRec : TCMOSType; procedure ReadCMOS; procedure WriteCMOS; procedure DisplayCMOS; procedure ModifyCMOS; procedure ReadFile; procedure WriteFile; end; procedure TCMOS.ReadFile; var f1 : file; data : tbyte64 absolute CMOSRec; ch : char; begin write('Please input the drive name (A/B/C/D): '); readln(ch); assign(f1,ch+':\CMOS.DAT'); reset(f1,1); blockread(f1,data,sizeof(data)); close(f1); end; procedure TCMOS.WriteFile; var f1:file; data : tbyte64 absolute CMOSRec; ch : char; begin write('Please input the drive name (A/B/C/D): '); readln(ch); assign(f1,ch+':\CMOS.DAT'); rewrite(f1,1); blockwrite(f1,data,sizeof(data)); close(f1); end; procedure TCMOS.ReadCMOS; begin asm les di,self add di,CMOSRec MOV CX,40H MOV AH,0H MOV BX,0 @1: MOV DX,70H MOV AL,AH OUT DX,AL INC DX in AL,dx MOV BYTE PTR es:[di+BX],al INC AH INC BX DEC CX JNZ @1 end; end; procedure TCMOS.WriteCMOS; begin asm les di,self add di,CMOSRec MOV CX,40H MOV AH,0H MOV BX,0 @1: MOV DX,70H MOV AL,AH OUT DX,AL MOV AL,BYTE PTR es:[di+BX] INC DX OUT DX,AL INC AH INC BX DEC CX JNZ @1 end; end; procedure TCMOS.DisplayCMOS; var hd1,hd2,fd1,fd2 : byte; begin Writeln(^J^M'CMOS RAM information:'); writeln('Date(MM-DD-YY): ',CMOSRec.Month shr 4,CMOSRec.Month and $f, '-',CMOSRec.DayOfMonth shr 4,CMOSRec.DayOfMonth and $f, '-',CMOSRec.Year shr 4,CMOSRec.Year and $f); writeln('Time(HH:MM:SS): ',CMOSRec.Hours shr 4,CMOSRec.Hours and $f, ':',CMOSRec.Minutes shr 4,CMOSRec.Minutes and $f, ':',CMOSRec.Seconds shr 4,CMOSRec.Seconds and $f); writeln('Conventional Memory: ',CMOSRec.Ram,'KB'); writeln('Extended Memory: ',CMOSRec.XMS,'KB'); hd2 := CMOSRec.FixedDrive and $f; hd1 := CMOSRec.FixedDrive shr 4; if (hd1 <> 0) then begin writeln('Fixed Drive 1: ',CMOSRec.FixedDriveType1); writeln(' Cylinder : ',CMOSRec.Cylinder1); writeln(' Head : ',CMOSRec.Head1); writeln(' Sector: ',CMOSRec.Sector1); writeln(' LZ: ',CMOSRec.LZ1); writeln(' WP: ',CMOSRec.WP1); end; if (hd2 <> 0) then begin writeln('Fixed Drive 2: ',CMOSRec.FixedDriveType2); writeln(' Cylinder : ',CMOSRec.Cylinder2); writeln(' Head : ',CMOSRec.Head2); writeln(' Sector: ',CMOSRec.Sector2); writeln(' LZ: ',CMOSRec.LZ2); writeln(' WP: ',CMOSRec.WP2); end; fd2 := CMOSRec.FloppyDrive and $f; fd1 := CMOSRec.FloppyDrive shr 4; if (fd1 <> 0) then begin write('Floppy Drive 1 : '); case fd1 of 1 : writeln('360KB 5.25'''); 2 : writeln('1.2MB 5.25'''); 4 : writeln('1.44MB 3.5'''); 6 : writeln('720KB 3.5'''); end; end ; if (fd2 <> 0) then begin write('Floppy Drive 2 : '); case fd2 of 1 : writeln('360KB 5.25'''); 2 : writeln('1.2MB 5.25'''); 4 : writeln('1.44MB 3.5'''); 6 : writeln('720KB 3.5'''); end; end; end; procedure TCMOS.ModifyCMOS; var hd1,hd2,fd1,fd2 : byte; data : tbyte64 absolute CMOSRec; i : word; begin Writeln('Please input CORRECT CMOS information !'); write('Conventional Memory (',CMOSRec.ram,'KB): ');readln(CMOSRec.ram); write('Extended Memory (',CMOSRec.XMS,'KB): ');readln(CMOSRec.XMS); write('Type of Fixed Disk 1: (',CMOSRec.FixedDriveType1,'): ');readln(CMOSRe c.FixedDriveType1); write(' Cylinder (',CMOSRec.Cylinder1,'):'); readln(CMOSRec.Cylinder1); write(' Head (',CMOSRec.Head1,'): ');readln(CMOSRec.Head1); write(' Sector (',CMOSRec.Sector1,'): ');readln(CMOSRec.Sector1); write(' LZ (',CMOSRec.LZ1,'): ');readln(CMOSRec.LZ1); write(' WP (',CMOSRec.WP1,'): ');readln(CMOSRec.WP1); write('Type of Fixed Disk 2: (',CMOSRec.FixedDriveType2,'): ');readln(CMOSRe c.FixedDriveType2); write(' Cylinder (',CMOSRec.Cylinder2,'):'); readln(CMOSRec.Cylinder2); write(' Head (',CMOSRec.Head2,'): ');readln(CMOSRec.Head2); write(' Sector (',CMOSRec.Sector2,'): ');readln(CMOSRec.Sector2); write(' LZ (',CMOSRec.LZ2,'): ');readln(CMOSRec.LZ2); write(' WP (',CMOSRec.WP2,'): ');readln(CMOSRec.WP2); hd1 := 0; hd2 :=0; if (CMOSRec.FixedDriveType1>46) then hd1 := $f; if (CMOSRec.FixedDriveType2>46) then hd2 := $f; CMOSRec.FixedDrive := hd1 shl 4 + hd2; fd2 := CMOSRec.FloppyDrive and $f; fd1 := CMOSRec.FloppyDrive shr 4; write('Floppy Drive 1 ('); case fd1 of 1 : write('360KB 5.25''): '); 2 : write('1.2MB 5.25''): '); 4 : write('1.44MB 3.5''): '); 6 : write('720KB 3.5''): '); end; readln(fd1); write('Floppy Drive 2 ('); case fd2 of 1 : write('360KB 5.25''): '); 2 : write('1.2MB 5.25''): '); 4 : write('1.44MB 3.5''): '); 6 : write('720KB 3.5''): '); end; readln(fd2); CMOSRec.FloppyDrive := fd1 shl 4 + fd2; CMOSRec.CheckSum := 0; for i := 17 to 46 do inc(CMOSRec.CheckSum,data[i]); i := CMOSRec.CheckSum; data[47] := hi(i); data[48] := lo(i); end; procedure help; begin WriteLn('Syntex:'+^J^M+ ' CMOS /R --- read information from CMOS RAM '+^J^M+ ' and write it to CMOS.DAT file '+^J^M+ ' CMOS /W --- read configuration information from CMOS.DAT '+^J^M+ ' and write it to CMOS RAM'); Writeln(' CMOS /M --- modify CMOS information and save it'^J^M+ ' Floppy Drive Type:'+^J^M+ ' 1 : 360KB 5.25'''+^J^M+ ' 2 : 1.2MB 5.25'''+^J^M+ ' 4 : 1.44MB 3.5'''+^J^M+ ' 6 : 720KB 3.5'''); end; var ch : char; temp : string; ICMOS : TCMOS; begin WriteLn('CMOS Proctector 1.00, Copyright (c) 1995 Dong Zhanshan'); if paramcount = 1 then begin temp := paramstr(1); ch := upcase(temp[2]); case ch of 'M' : begin ICMOS.ReadCMOS; ICMOS.ModifyCMOS; ICMOS.DisplayCMOS; ICMOS.WriteFile; ICMOS.WriteCMOS; end; 'R' : begin ICMOS.ReadCMOS; ICMOS.DisplayCMOS; ICMOS.WriteFile;
end; 'W' : begin ICMOS.ReadFile; ICMOS.DisplayCMOS; ICMOS.WriteCMOS; end; else help; end; end else help; end.
|