📄 readcmos.asm
字号:
;==============================================================
stack segment stack ; keep MS link happy by providing null stack
stack ends
CODE SEGMENT PARA ; start off in code.
;==============================================================
data segment byte ; provide a separate DATA segment
; actually all come after the code
;==============================================================
; V A R I A B L E S
BannerMsg DB 'CMOSSAVE',13d,10d
DB 13,10
db '$'
UsageMsg DB 'Error',7,13,10
DB 'Insert a formatted diskette.',13,10
DB 'then try:',13,10
DB 'CMOSSave A:\CMOS.Sav',13,10
DB 'or if want to save on hard disk try:',13,10
DB 'CMOSSave C:\CMOS.Sav',13,10
DB 'Read CMOS.TXT to find how to use it properly.',13,10
db '$'
FileTroubleMsg DB 'Error',7,13,10
DB 'Cannot create the disk file.',13,10
db '$'
WorkedMsg DB 'CMOS successfully saved',13,10
db '$'
FilenamePtr DW 0
; pointer to filename in command line
CMOSSize DB 0
; size of cmos in bytes
CMOSBuff db 0 ; dynamic buffer will grow to 128
; it hangs out past the end of the program
data ends
com group code,data ; force data segment to go at the end
ASSUME CS:com,DS:com,ES:com,SS:com
; seg regs cover everything
ORG 100H ; in Code segment
;==========================
Main proc far
; M A I N L I N E R O U T I N E
Start:
lea dx,BannerMsg ; display the banner
Call Say
Call Parse ; get filename from command line
call GetCMOS ; fetch CMOS to buffer
call WriteCMOS ; write CMOS contents to file
lea dx,WorkedMsg ; crow about success
Call Say
Done:
mov ax,4c00h
int 21h ;normal termination
Main EndP
;===============================================================
Trouble proc near
FileTrouble:
Lea dx,FileTroubleMsg ; display file trouble
Call Say
Jmp Abort
abort:
; error exit
mov ax, 4c04h ; ERRORLEVEL = 4
int 21h ; DIE
Trouble endp
;===============================================================
MLeading PROC Near
; Remove leading blanks
; on entry BX is addr of string, CX its length
; trims off any leading blanks, leaving result in BX CX
; length may also be 0 or 1, but not -ve
; If the entire string is blank the result is the null string
mov di,bx
mov al,20H ; AL = blank -- the search char
jcxz mleading2 ; jump if null string
repe scasb ; scan ES:DI forwards till hit non blank
; DI points just after it (wrap ok)
; cx IS ONE TOO SMALL, OR 0 IF NONE FOUND
je mleading1 ; jump if entire string was blank
inc cx ; CX is length of remainder of string
mleading1:
dec di ; DI points to non-blank
mleading2:
mov bx,di ; put address back
ret
MLeading ENDP
;========================================
MTrailing PROC Near
; Remove trailing blanks.
; on entry BX is addr of string, CX its length
; trims off any trailing blanks, leaving result in BX CX
; length may also be 0 or 1, but not -ve
; If the entire string is blank the result is the null string
mov di,bx
add di,cx ; calc addr last char in string
dec di
mov al,20H ; AL = blank -- the search char
jcxz mtrailing1 ; jump if null string
std
repe scasb ; scan ES:DI backwards till hit non blank
; DI points just ahead of it (wrap ok)
; CX is one too small, or 0 if none found
cld
je mtrailing1 ; jump if whole string was blank
inc cx
mtrailing1:
ret
MTrailing ENDP
;========================================
Parse PROC NEAR
; Parse the command line to remove lead/trail blanks from
; the single drive parameter and terminate it by 2 nulls.
; sample inputs
; CMOSRest A:\CMOS.SAV
; CMOSRest B:\MySub\MyCMOS.SAV
;
; When Done DS:BX points to start of string.
; String will be terminated by 2 nulls
; CX counts bytes in string exclusive of nulls
; counted string at HEX 80 PSP
; contains command line.
; Preceeded by unwanted spaces.
; possibly followed by unwanted spaces.
; currently missing a trailing null.
xor ch,ch
mov cl,ds:80H
mov bx,81H
call Mleading ; get rid of leading blanks
call MTrailing ; get rid of trailing blanks
mov di,bx ; calc addr of byte just past end
add di,cx
mov word ptr [di],0 ; plop in pair of nulls after string
mov FileNamePtr,bx ; remember where filename was
jcxz SyntaxTrouble ; missing parm.
ret
SyntaxTrouble:
lea dx,UsageMsg ; display usage message
Call Say
Jmp Abort
Parse ENDP
;======================================
Say Proc
; on entry DX points to a string to display
push ax
MOV AH,9
Int 21h
pop ax
ret
Say EndP
;======================================
GetCMOS Proc Near
; Get 128 byte contents of CMOS into a buffer.
mov cx,128 ; count of times through loop
lea bx,CMOSBuff ; where to put the contents
sub al,al ; start offset in CMOS
GetLoop:
Call PeekCmos ; al=offset ah=contents
mov byte ptr[bx],ah
inc al
inc bx
loop GetLoop
ret
GetCMOS EndP
;===============================================================
; Add to this list if you need more volatile bytes.
; Remember the trailing h.
VolatileList db 0ch,032h
VolatileCount equ $-VolatileList
Volatile Proc near
; Is cmos offset in AL volatile? If so set carry.
; These bytes will be undisturbed.
; Preserves all registers.
; 00..09, 0C and 32 are volatile, rest are not.
; 0A 0B 0D 0E 0F used to be considered volatile, now are not.
; if cmos is small, all bytes past end are considered volatile
cmp al,CMOSSize ; bytes past end are volatile
jae IsVolatile
cmp al,09h
jbe IsVolatile ; early bytes are for timing
push cx
push di
mov cx,VolatileCount
lea di,VolatileList
repne scasb ; search till find a match
pop di
pop cx
je IsVolatile
IsNotVolatile:
clc ; clear carry
ret
IsVolatile:
stc
ret
Volatile EndP
;===============================================================
CalcCMOSSize Proc near
; Is CMOS 64 or 128 bytes long?
; It is 64 if bytes at 10..2F match those at 50..6F.
; Otherwise it is 128 bytes.
; Preserves all registers.
push si
push di
push cx
lea si,CMOSBuff+10h
lea di,CMOSBuff+50h
mov cx,02fh+1-10h
repe cmpsb
je IsCMOS64
IsCMOS128:
mov CMOSSize,128 ; differ, must be a big CMOS
jmp CalcCMOSSizeDone
IsCMOS64:
mov CMOSSize,128 ; all same, small CMOS
CalcCMOSSizeDone:
pop cx
pop di
pop si
ret
CalcCMOSSize EndP
;===============================================================
ReadCMOS Proc Near
; Open a file read the CMOS into a buffer
mov dx,FileNamePtr ; DS:DX point to file
xor al,al ; AL=0 is attribute read/only
mov ah,03Dh ; DOS open function
int 21h
jc FileTrouble
mov bx,ax ; save handle
mov cx,128 ; read 128 bytes
lea dx,CMOSBuff ; buffer address
mov ah,3fH ; DOS read
int 21h
jc FileTrouble
cmp ax,128
jne FileTrouble
mov ah,3eh ; DOS close
int 21h
jc FileTrouble
ret
ReadCMOS EndP
;===============================================================
WriteCMOS Proc Near
; Create a file write CMOS to it
mov dx,FileNamePtr ; DS:DX point to file
xor cx,cx ; CX=0 is attribute
mov ah,03ch ; DOS create function
int 21h
jc FileTrouble
mov bx,ax ; SAVE HANDLE
MOV CX,128 ; write 128 bytes
lea dx,CMOSBuff ; buffer address
mov ah,40h ; DOS write
int 21h
jc FileTrouble
cmp ax,128
jne FileTrouble
mov ah,3eh ; DOS close
int 21h
jc FileTrouble
ret
WriteCMOS EndP
;===============================================================
PeekCMOS proc near
; Reads one byte from cmos.
; on entry al has offset desired
; on exit ah has the contents of that byte.
; preserves all registers
; See page 5-81 IBM AT Tech ref BIOS listing for how to read CMOS
; We always enable the NMI with bit 7 on.
push bx
push ax
cli ; disable interrupts
or al,80h ; disable NMI
out 70h,al ; output the byte address to CMOS
jmp $+2 ; delay, safer than nop
in al,71h ; read the CMOS byte
jmp $+2 ; delay, safer than nop
mov bl,al
; re-enable the NMI
mov al,0dh ; point to battery status register
out 70h,al ; leave pointing at a safe r/o register
sti ; restore interrupts
pop ax
mov ah,bl
pop bx
ret
PeekCMOS EndP
;===============================================================
CODE ends ; end of code segment
end Start
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -