plik


Rozpoznawanie typu procesora Autor: Bogdan Drozdowski, bogdandr (at) op.pl Jak zapewne wiecie, wiele programow (systemy operacyjne, gry, ...) potrafi jakos "dowiedziec sie", na jakim procesorze zostaly uruchomione. Rozpoznanie typu procesora umozliwia np. uruchomienie dodatkowych optymalizacji w programie lub odmowe dalszego dzialania, jesli program musi korzystac z instrukcji niedostepnych na adanym procesorze. Wykrywanie rodzaju CPU i FPU nie jest trudne i pokaze teraz, jak po kolei sprawdzac typ procesora (nie mozna przeciez zaczac sprawdzania od najwyzszych). Informacje, ktore tutaj podam, sa oczywiscie sluszne dla wszystkich procesorow rodziny x86 (AMD, Cyrix, ...), a nie tylko Intela. Generalnie sposoby wykrywania sa dwa: poprzez rejestr FLAG lub poprzez zakodowanie w kodzie instrukcji, ktore wykonaja sie tylko na danym modelu (i pozniejszych). Drugi sposob jest troche trudniejszy: nalezy przejac przerwanie INT6 (nieprawidlowa instrukcja) i sprawdzac, kiedy zostalo wywolane. 1. odroznienie 8088 od reszty Procesor 8088 od pozostalych odroznia to, ze zmniejsza on rejestr SP przed umieszczeniem go na stosie. Reszta robi to po umieszczeniu SP na stosie. Kod wygladalby wiec na przyklad tak: mov ax, sp push sp pop cx xor ax, cx ; lub cmp ax, cx jz nie_8088 2. 8086 Na tym procesorze w rejestrze flag bity 12-15 zawsze maja wartosc 1. pushf ; flagi na stos pop ax ; AX = flagi and ax, 0fffh ; czyscimy bity 12-15 push ax ; AX na stos popf ; flagi = AX pushf ; z powrotem na stos pop ax ; AX = flagi and ax, 0f000h ; zerujemy bity poza bitami 12-15 cmp ax, 0f000h ; jesli ustawione, to 8086 jz jest_8086 3. 80186 Test polega na probie wykonania instrukcji "smsw dx", nieprawidlowej na procesorach wczesniejszych niz 80286. Przerwanie nieprawidlowej instrukcji przejmujemy tak: xor ax, ax mov es, ax les bx, [es:6 << 2] mov [_stare06+2], es mov [_stare06], bx mov es, ax mov word [es:(6 << 2)], moje06 mov word [es:(6 << 2) + 2], seg moje06 Sama procedura obslugi przerwania wygladac bedzie tak: moje06: pop ax add ax, 3 push ax xor ax, ax iret Proste: zwiekszamy adres powrotny o 3 (dlugosc instrukcji "smsw dx") i zerujemy AX (potem w kodzie sprawdzimy jego wartosc). Sam kod sprawdzajacy wyglada tak: mov ax, 1 db 0fh, 1, 0e2h ; smsw dx or ax, ax jz jest_286 Przywrocenie oryginalnej procedury wyglada tak: xor ax, ax les cx, [_stare06] mov ds, ax mov [ds:(6 << 2)], cx mov [ds:(6 << 2) + 2], es 4. 80286 Na tym procesorze bity 12-15 flag zawsze maja wartosc 0. Przykladowy kod wyglada wiec tak: pushf ; flagi na stos pop ax ; AX = flagi or ax, 0f000h ; ustawiamy bity 12-15 push ax ; AX na stos popf ; flagi = AX pushf ; flagi na stos pop ax ; AX = flagi and ax, 0f000h ; jesli wyczyszczone, to 286 jnz nie_286 5. 80386 Na tym procesorze nie mozna zmienic bitu numer 18 we flagach (wiemy, ze rejestr flag ma 32 bity). Bit ten odpowiada za Alignment Check i spowoduje przerwanie m.in wtedy, gdy SP nie bedzie podzielne przez 4. Dlatego, zanim bedziemy testowac ten bit, musimy zachowac SP i wyzerowac jego najmlodsze 2 bity. mov dx, sp and sp, ~3 ; aby uniknac AC fault pushfd ; flagi na stos pop eax ; EAX = E-flagi mov ecx, eax ; zachowanie EAX xor eax, 40000h ; zmiana bitu 18 push eax ; EAX na stos popfd ; E-flagi = EAX pushfd ; flagi na stos pop eax ; EAX = flagi xor eax, ecx ; czy takie same? jesli tak, to 386 mov sp, dx ; przywrocenie SP jz jest_386 6. 80486 Na tym procesorze nie mozna zmienic bitu 21 we flagach. Jesli ten bit mozna zmienic, to procesor obsluguje instrukcje CPUID, ktorej bedziemy uzywac do dalszego rozpoznania. Kod: pushfd ; flagi na stos pop eax ; EAX = E-flagi mov ecx, eax ; zachowanie EAX xor eax, 200000h ; zmiana bitu 21 push eax ; EAX na stos popfd ; E-flagi = EAX pushfd ; flagi na stos pop eax ; EAX = flagi xor eax, ecx ; czy takie same? jesli tak, to 486 jz jest_486 jmp jest_586 Zanim omowie sposob korzystania z instrukcji CPUID, zajmijmy sie sposobem rozpoznania typu koprocesora. ----------------------------------------------------------------------------- Koprocesor Tutaj mozliwosci sa tylko 4: brak, 8087, 80287, 80387. No to do roboty. 1. czy w ogole jest jakis koprocesor? To sprawdzamy bardzo latwo. Jesli nie ma koprocesora, to w chwili wykonania instrukcji FPU moze wystapic przerwanie INT6 (nieprawidlowa instrukcja), ale nie o tym sposobie chcialem powiedziec. Koprocesor mozna wykryc, jesli slowo stanu zostanie zapisane prawidlowo. Oto kod: fninit ; inicjalizacja zeruje rejestry mov word [_fpu_status], 5a5ah ; jakas niezerowa wartosc fnstsw [_fpu_status] ; zapisz slowo statusowe do pamieci mov ax, [_fpu_status] or al, al ; jesli zapisalo dobrze (zera ; oznaczaja puste rejestry), to jest FPU jz jest_FPU 2. 8087 Sztuczka polega na wykorzystaniu instrukcji FDISI (wylaczenie przerwan), ktora rzeczywiscie cos robi tylko na 8087. Po wylaczeniu przerwan w slowie kontrolnym zostaje wlaczony bit numer 7. fnstcw [_fpu_status] ; zachowaj slowo kontrolne do pamieci and word [_fpu_status], 0ff7fh ; wylaczamy wszystkie przerwania ; (poprzez slowo kontrolne) fldcw [_fpu_status] ; zaladuj slowo kontrolne z pamieci fdisi ; wylaczamy wszystkie przerwania ; (jako instrukcja) fstcw [_fpu_status] ; zachowaj slowo kontrolne do pamieci test byte [_fpu_status], 80h ; bit 7 ustawiony? jesli nie, to nie ; jest to 8087 jz nie_8087 3. 80287 Koprocesor ten nie odroznia minus nieskonczonosci od plus nieskonczonosci. Kod na sprawdzenie tego wyglada tak: finit fld1 ; st(0)=1 fldz ; st(0)=0,st(1)=1 fdivp st1 ; tworzymy nieskonczonosc, dzielac przez 0 fld st0 ; st(1):=st(0)=niesk. fchs ; st(0)= -niesk. ; porownanie st0 z st1 i zdjecie obu ze stosu fcompp ; 8087/287: -niesk. = +niesk., ; 387: -niesk. != +niesk. fstsw [_fpu_status] ; zapisz status do pamieci mov ax, [_fpu_status] ; AX = status sahf ; zapisz AH we flagach. tak sie sklada, ze tutaj rowniez ; flaga ZF wskazuje na rownosc argumentow. jz jest_287 jmp jest_387 Dalsze informacje o procesorze - instrukcja CPUID Od procesorow 586 (choc niektore 486 tez podobno ja obslugiwaly), Intel i inni wprowadzili instrukcje CPUID. Pozwala ona odczytac wiele roznych informacji o procesorze (konkretny typ, rozmiary pamieci podrecznych, dodatkowe rozszerzenia, ...). Korzystanie z tej instrukcji jest bardzo proste: do EAX wpisujemy numer (0-3) i wywolujemy instrukcje, np. mov eax, 1 cpuid Teraz omowie, co mozna dostac przy roznych wartosciach EAX. 1. EAX=0 EAX = maksymalny numer funkcji dla CPUID. EBX:EDX:ECX = marka procesora (12 znakow ASCII). Intel - "GenuineIntel" AMD - "AuthenticAMD" NexGen - "NexGenDriven" Cyrix, VIA - "CyrixInstead" RISE - "RiseRiseRise", Centaur Technology/IDT - "CentaurHauls" (programowalne, moze byc inne) United Microelectronics Corporation - "UMC UMC UMC " Transmeta Corporation - "GenuineTMx86" SiS - "SiS SiS SiS " National Semiconductor - "Geode by NSC". 2. EAX=1 EAX = informacje o wersji: * bity 0-3: stepping ID * bity 4-7: model * bity 8-11: rodzina. Wartosci moga byc od 4 (80486) do 7 (Itanium) oraz 15 ("sprawdz rozszerzone informacje o rodzinie") * bity 12-13: typ procesora (0=Original OEM Processor, 1=Intel Overdrive, 2=Dual) * bity 16-19 (jesli jest taka mozliwosc): rozszerzona informacja o modelu. * bity 20-27 (jesli jest taka mozliwosc): rozszerzona informacja o rodzinie. EDX = cechy procesora (tutaj akurat z procesorow Intela; najpierw numery bitow): * 0: procesor zawiera FPU * 1: Virtual 8086 Mode Enchancements * 2: Debugging Extensions * 3: Page Size Extension * 4: Time Stamp Counter * 5: Model Specific Registers * 6: Physical Address Extensions * 7: Machine Check Exception * 8: instrukcja CMPXCHG8B * 9: zawiera Zaawansowany Programowalny Kontroler Przerwan (APIC) * 11: instrukcje SYSENTER i SYSEXIT * 12: Memory Type Range Registers * 13: Page Table Entries Global Bit * 14: Machine Check Architecture * 15: instrukcje CMOV* * 16: Page Attribute Table * 17: 32-bit Page Size Extensions * 18: numer seryjny procesora * 19: instrukcja CLFLUSH * 21: Debug Store * 22: monitorowanie temperatury i mozliwosc modyfikacji wydajnosci procesora * 23: technologia MMX * 24: instrukcje FXSAVE i FXRSTOR * 25: technologia SSE * 26: technologia SSE2 * 27: Self-Snoop * 28: technologia Hyper-Threading * 29: monitorowanie temperatury, uklady kontroli temperatury * 31: Pending Break Enable 3. EAX=2 EBX, ECX, EDX = informacje o pamieci podrecznej cache i TLB Nawet te informacje, ktore tu przedstawilem sa juz bardzo szczegolowe i z pewnoscia nie beda takie same na wszystkich procesorach. To jest tylko wstep. Dalsze informacje mozna znalezc na stronach producentow procesorow, np. AMD Intel, ale takze tutaj: Sandpile Lista przerwan Ralfa Brown'a (plik opcodes.lst)

Wyszukiwarka

Podobne podstrony:
DOS DIOD TUT
DOS PWR TUT
CPU TUT
DOS MYSZ TUT
DOS GRAF TUT
DOS SPKR TUT
DOS BOOT TUT
DOS SYS TUT
CPU TUT
DOS BIBL TUT
CPU TUT
DOS TSR TUT
DOS BMP TUT
cpu
FUNFACE DOS OPIS
do pomiary temperatury cpu ReadMe!
ART121 tut 2

więcej podobnych podstron