Jeśli zastanawialiście się kiedyś, jak wyłączać dyski twarde lub resetować komputer używając tylko oprogramowania (nie naciskając żadnych przycisków), to w tym artykule powinniście znaleźć odpowiedź na wszystkie wasze pytania.
Zajmijmy się najpierw teorią. Przerwanie, którym najpierw się zajmiemy, to.... int 10h, przerwanie sterowników karty graficznej. Co one mają wspólnego z energią? Otóż, można z użyciem int 10h wyłączyć monitor. Zajrzyjmy do RBIL, w opis funkcji numer 4F10h. Uruchomienie jej z BL=0 powinno nas upewnić, że odpowiednie funkcje są zainstalowane (zwróci AL=4Fh):
mov ax, 4f10h mov bl, 0 xor di, di mov es, di ; przerwanie żąda ES:DI = 0 int 10h cmp al, 4fh jne wychodzimy ; gdy klęska....
Teraz, jeśli wiemy, że ta funkcja działa, to patrzymy na kolejną. Wpisując 1 do BL możemy zmienić aktualny stan zasilania. W BH podajemy, co chcemy zrobić: 0-włączyć, 1-przełączyć w stan oczekiwania, 2-zawiesić, 4-wyłączyć monitor. Zanim jednak zaczniecie ochoczo pisać, dam wam radę: program należy napisać tak, aby po jakimś czasie monitor wracał jednak do stanu włączonego (bez resetowania komputera...). Wiem, że potrafilibyście coś takiego sami napisać, ale podam tutaj gotowe (i sprawdzone - działa nawet pod Win98) rozwiązanie:
; Program wyłącza monitor ; ; Autor: Bogdan D. ; kontakt: bogdandr (at) op (dot) pl ; ; nasm -O999 -o mon_off.com -f bin mon_off.asm org 100h start: mov ax,4f10h ; wybranie numeru funkcji mov bx,0401h ; BL=1 - zmień stan. BH=4 - wyłącz int 10h xor ah,ah int 16h ; poczekaj na naciśnięcie klawisza mov ax,4f10h mov bx,1 ; BL=1 - zmień stan. BH=0 - włącz int 10h mov ax,4c00h int 21h
Z dyskami twardymi jest nieco gorzej. Tutaj trzeba się znać na kontrolerze
HDD - na jego
portach i wysyłanych tam komendach. Dlatego posłużę się gotowcem. Ma on wyłączyć 2 pierwsze
dyski twarde. Dla dokładniejszych opisów portów i ich komend spójrzcie
do pliku ports.lst
dołączonego do RBIL.
Gotowiec ten jest częścią doskonałego programu FDAPM
(FreeDOS Advanced Power Management),
który wraz z kodem źródłowym można znaleźć na stronach
projektu FreeDOS.
mov dx,1f6h ; pierwszy kontroler IDE (drugi: 176) mov al,0a0h ; bez LBA, dysk nadrzędny (Master) out dx,al inc dx ; DX = 1F7 call miniWait ; chwila przerwy mov al,0e0h ; e0 = standby, e1 = włączony/idle out dx,al dec dx ; DX = 1F6 call miniWait mov al,0b0h ; bez LBA, dysk podrzędny (Slave) out dx,al inc dx ; DX = 1F7 call miniWait mov al,0e0h ; e0 = standby, e1 = włączony/idle out dx,al mov ax,4c00h int 21h miniWait: ; bardzo krótki okres przerwy xchg ax, bx xchg bx, ax xchg ax, bx xchg bx, ax ret
Po zatrzymaniu twardego dysku można go uruchomić wykonując dowolną operację na systemie plików (na przykład wyświetlić zawartość bieżącego katalogu).
Parkowanie głowic twardego dysku jest sprawą prostszą, gdyż w tym przypadku pomaga nam BIOS. Aby zaparkować głowice pierwszego dysku twardego, użyj następującego kodu:
mov ah, 19h mov dl, 80h int 13h jc blad ; nie pokazuje błędów pod Windows 98
Jeśli chcecie zaparkować głowice drugiego dysku, zamiast 80h wpiszcie 81h, jeśli trzeciego - 82h itd.
Teraz ciekawsze sprawy - resetowanie komputera lub wyłączanie go. Na początek grzecznie
posłużymy się przerwaniem - będzie to int15h, numery funkcji 5300h i 5307h (po szczegółowe
opisy tych funkcji posyłam oczywiście do RBIL).
Najpierw sprawdźmy w ogóle, czy Advanced Power Management (APM)
- bo o nim mowa - jest zainstalowane:
mov ax, 5300h xor bx, bx ; numer urządzenia = 0 = BIOS int 15h jc niestety ; gdy coś poszło nie tak (na przykład brak APM), to CF=1
Teraz spróbujmy wyłączyć system:
mov ax, 5307h ; funkcja APM mov cx, 3 ; wyłącz system. CX=2 - zawieś system, CX=1 - ; przełącz system w stan oczekiwania stand-by mov bx, 1 ; wszystkie urządzenia int 15h ; spróbujemy wyłączyć...
Jeśli istnieje możliwość wyłączenia prądu w systemie, to powyższy kod powinien to załatwić.
Teraz przejdziemy do innych grzecznych
sposobów na zresetowanie komputera. W
RBIL znalazłem:
INT 16 - AMI BIOS - BIOS-FLASH Interface - GENERATE CPU RESET
AX = E0FFh
INT 14 - FOSSIL - REBOOT SYSTEM
AH = 17h
AL = method
00h = cold boot
01h = warm boot
Jak widać, nie wygląda to skomplikowanie.
Niestety, żaden z powyższych sposobów nie działa u
mnie pod czystym
DOS-em,
a pod Windows98 działa jedynie sposób z APM (int15h).
A teraz pokażę kilka niegrzecznych
(ale za to sprawdzonych przeze mnie i działających bez
pudła) sposobów na zresetowanie komputera.
Pierwszym takim sposobem jest długi skok pod adres FFFF:0000 (tam znajduje się część BIOSu odpowiedzialna za operacje wykonywane przy starcie komputera). Wcześniej do segmentu danych BIOSu (segment 40h), pod adres 72h należy wpisać 0, gdy chcemy zimny reset (taki, co obejmuje testy pamięci i wszystko inne), a 1234h, gdy chcemy gorący reset.
Odpowiednie kawałki kodu wyglądają tak (przypominam, że adres 0040h:0072h = 0000:0472h - patrz część 2 mojego kursu):
; zimny reset: mov ax, 40h mov ds, ax ; DS = 40h mov word [ds:72h], 0 ; zimny reset ; niektóre kompilatory (na przykład TASM) nie lubią instrukcji w stylu ; jmp 0FFFFh:0000h, więc zakoduję ją ręcznie db 0eah ; kod instrukcji wzięty z podręczników Intela dw 0 ; offset dw 0ffffh ; segment ; gorący reset: xor ax, ax mov ds, ax ; DS = 0 mov word [ds:472h], 1234h ; gorący reset db 0eah ; kod instrukcji wzięty z podręczników Intela dw 0 ; offset dw 0ffffh ; segment
Drugim (i prostszym) sposobem
jest zapisanie do jednego z portów klawiatury (64h)
jednego z bajtów od F0 do FE, który ma bit0 = 0 (jest takich oczywiście kilka, najczęściej
stosuje się FEh), chociaż ten sposób nie jest zalecany.
Kod jest wyjątkowo prosty i wygląda tak:
mov al, 0feh out 64h, al
Celowo nie wspominam tutaj o jednym: o przerwaniu int19h, które służy do ponownego przeczytania bootsektorów i przeładowania systemu od nowa. Gdy wkładacie niesystemową dyskietkę do stacji i resetujecie komputer, to (o ile macie możliwość uruchomienia systemu z dyskietki) pojawia się napis informujący o nieprawidłowym dysku systemowym. Po naciśnięciu Entera uruchamiane jest właśnie int19h, które nie wykonuje żadnych resetów, tylko czyta bootsektory od nowa.
Nie wspominałem o int19h, gdyż jest ono niebezpieczne. Jeżeli jakikolwiek program przejął przerwanie na przykład zegara, to int19h nie przywróci poprzedniej procedury, co jest nieprzewidywalne w skutkach!
Sposoby na wyłączanie urządzeń mogą się Wam przydać, gdy na przykład będziecie pisać własny wygaszacz
ekranu, a możliwość zresetowania komputera przyda się, gdy Wasze oprogramowanie zostanie
zainstalowane i musi zmienić na przykład zawartość pliku autoexec.bat
.
Informacje, które tutaj podałem mogą się Wam też przydać przy pisaniu
boot-sektorów do własnych mini-systemów operacyjnych
.