Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых

Аппаратное обеспечение персонального компьютера

© Александр Фролов, Григорий Фролов
Том 33, М.: Диалог-МИФИ, 1997, 304 стр.

[Назад] [Содеожание] [Дальше]

Определение типа центрального процессора

В некоторых случаях эффективность работы программы можно заметно повысить, если использовать команды новых моделей процессоров Pentium, такие как, например, команды MMX. На сервере Intel с адресом http://www.intel.com вы найдете исчерпывающую информацию о том, как распознать различные модели процессоров, созданных этой фирмой. В нашей книге мы рассмотрим упрощенную методику, которая, тем не менее, может быть использована в большинстве случаев.

Модели Intel 8086/8088

Способ распознавания процессоров Intel 8086/8088 основан на том факте, что биты 12-15 регистра FLAGS всегда установлены в единицу.

Прежде всего программа записывает текущее содержимое регистра FLAGS в регистр AX. Для этого используется стек:


	pushf
	pop ax

Первоначальное содержимое регистра FLAGS сохраняется в регистре CX:


	mov cx, ax

Далее программа пытается записать нулевые значения в биты 12-15 регистра FLAGS:


	and ax, 0fffh
	push ax
	popf

Теперь нужно проверить, изменилось ли содержимое указанных битов регистра FLAGS. Для этого новое содержимое регистра FLAGS записывается через стек в регистр AX, а затем, после наложения маски 0f000h, сравнивается со значением 0f000h:


	pushf
	pop ax
	and ax, 0f000h
	cmp ax, 0f000h
	je is_8086

Если биты 12-15 остались установленными в единичное значение, программа работает на процессоре Intel 8086/8088, если нет – в компьютере установлена более старшая модель процессора.

Модель Intel 80286

В процессоре Intel 80286, когда он работает в реальном режиме адресации, биты 12-15 регистра FLAGS всегда сброшены в нуль, что можно использовать для обнаружения этой модели процессора.

Следующий фрагмент кода пытается записать в эти биты единичное значение:


	mov ax, 0f000h
	push ax
	popf

Затем новое содержимое регистра FLAGS переписывается в регистр AX:


	pushf
	pop ax

Если содержимое битов 12-15 равно нулю, программа работает на процессоре Intel 80286:


	and ax, 0f000h
	jz is_80286

В противном случае необходимо продолжить проверку модели процессора.

Модель Intel 80386

Для того чтобы отличить процессор Intel 80386 от процессоров старших моделей, можно попробовать установить в регистре EFLAGS бит 18. Этот бит был впервые определен в процессоре Intel 80486 для сигнализации ошибки выравнивания. Его невозможно установить в процессоре Intel 80386.

В процессе проверки программа вначале получает исходное содержимое регистра EFLAGS, записывая его в регистры EAX и ECX:


	pushfd
	pop eax
	mov ecx, eax

Далее программа инвертирует значение бита 18 и записывает полученный результат в регистр EFLAGS:


	xor eax, 40000h
	push eax
	popfd

На последнем шаге идентификации новое содержимое регистра EFLAGS извлекается и сравнивается со старым:


	pushfd
	pop eax
	xor eax, ecx
	jz is_80386

Если бит 18 не изменил своего значения, мы имеем дело с процессором Intel 80386.

Модель Intel 80486

Отличительная особенность процессора Intel 80486 – невозможность изменения состояния бита 21 регистра EFLAGS. Этот бит используется процессорами Intel Pentium и более старшими моделями процессоров Intel для определения возможности вызова команды идентификации процессора CPUID, о которой мы скоро расскажем.

Фрагмент кода, который нужно использовать для обнаружения процессора Intel 80486, аналогичен фрагменту для процессора Intel 80386. Отличие заключается в том, что вместо бита 18 проверяется бит 21:


	pushfd
	pop eax
	mov ecx, eax
	xor eax, 200000h
	push eax
	popfd
	pushfd
	pop eax
	xor eax, ecx
	je is_80486

Если же выяснилось, что содержимое бита 21 регистра EFLAGS можно изменять, дальнейшую идентификацию модели процессора следует выполнять с использованием команды CPUID, к описанию которой мы и переходим.

Команда CPUID

В новых процессорах фирмы Intel появилась команда CPUID, специально предназначенная для определения модели процессора. В своей программе, составленной на языке ассемблера, вы можете определить эту команду следующим образом:


	CPU_ID MACRO
	  db 0fh
	  db 0a2h
	ENDM

Как работает команда CPUID?

Перед вызовом этой команды необходимо загрузить в регистр EAX значение, которое определяет выполняемые действия. В первый раз вы должны вызвать команду CPUID, загрузив предварительно в регистр EAX нулевое значение:


	mov eax, 00h
	CPU_ID

Команда вернет в регистре EAX максимальное значение, которое можно передавать команде CPUID для определения выполняемых действий. Кроме того, в регистрах EBX, ECX и EDX будут находиться байты текстовой строки описания фирмы-изготовителя процессора. Для процессоров Intel это будет строка GenuineIntel.

Следующая последовательность команд перепишет эти байты в буфер _vendor_id_msg в формате, пригодном для вывода на консоль средствами BIOS:


	_vendor_id_msg db "............", 0dh, 0ah, "$"
	. . .
	mov dword ptr _vendor_id_msg,     ebx
	mov dword ptr _vendor_id_msg[+4], edx
	mov dword ptr _vendor_id_msg[+8], ecx

Для определения модели процессора следует вызвать команду CPUID, загрузив предварительно в регистр EAX значение 1:


	mov eax, 1
	CPU_ID

При этом в регистр EAX будет загружено слово сигнатуры, по которому можно определить модель процессора, а в регистр EDX – слово, состоящее из отдельных флагов, характеризующих возможности процессора (feature flags). Регистры EBX и ECX зарезервированы для моделей процессоров, которые будут разработаны в будущем.

Ниже приведен фрагмент кода, в котором слово сигнатуры и слово возможностей записываются в переменные _cpu_signature и _features_edx для дальнейшего анализа:


	_cpu_signature dd 0
	_features_edx  dd 0
	. . .
	mov _cpu_signature, eax
	mov _features_edx, edx

Рассмотрим формат слова сигнатуры, возвращаемое командой CPUID в регистре EAX:

Биты

Описание

0-3

Код модификации модели (stepping)

4-7

Код модели

8-11

Код семейства моделей

12-13

Тип процессора

14-31

Зарезервировано

Слово сигнатуры состоит из отдельных полей, назначение которых будет описано ниже.

Биты 12 и 13 определяют тип процессора:

Значение битов 12 и 13

Тип процессора

00

Процессор, изготовленный производителем OEM

01

Процессор OverDrive

10

Процессор типа Dual, который можно использовать в двухпроцессорных системах

11

Зарезервировано

Заметим, что многопроцессорные системы могут быть построены не только на базе процессоров типа Dual, но и на обычных процессорах.

Ниже мы привели таблицу, с помощью которой по содержимому трех полей слова сигнатуры (тип процессора, код семейства и код модели) можно распознать процессор:

Тип процессора

Код семейства

Код модели

Описание процессора

00

0100

0100

Intel 486 SL

00

0100

0111

Intel DX2

00

0100

1000

Intel DX4

00, 01

0100

1000

Intel DX4 OverDrive

00

0101

0001

Pentium 60, 66;

Pentium OverDrive для процессоров Pentium 60, 66

00

0101

0010

Pentium 75, 90, 100, 120, 133, 150, 166, 200

01

0101

0010

Pentium OverDrive для процессоров Pentium 75, 90, 100, 120, 133

01

0101

0011

Pentium OverDrive для систем на базе процессора Intel 486

00

0101

0100

Pentium 166, 200 с командами MMX

01

0101

0100

Зарезервировано. Будет использоваться процессорами Pentium OverDrive для процессоров Pentium 75, 90, 100, 120, 133

00

0110

0001

Pentium Pro

00

0110

0011

Pentium II

00

0110

0101

Зарезервировано для новых процессоров P6

01

0110

0011

Зарезервировано для процессоров Pentium OverDrive для процессоров Pentium Pro

Что же касается кода модификации модели (stepping), то он определяет изменения в процессоре. Вы найдете описания этих кодов для процессора Pentium в руководстве Pentium Processor Specification Update, который можно приобрести в фирме Intel.

Приведем описание битов, возвращаемых командой CPUID в регистре EDX. Напомним, что это слово состоит из отдельных флагов, характеризующих возможности процессора (feature flags).

Бит

Описание

0

На кристалле процессора имеется арифметический сопроцессор, совместимый по командам с сопроцессором Intel 387

1

Процессор может работать в режиме виртуального процессора 8086

2

Процессор может работать с прерываниями ввода/вывода, а также с битом DE регистра CR4

3

Возможно использование страниц памяти размером 4 Мбайт

4

В процессоре есть команда RDTSC, которая может работать с битом TSD регистра CR4

5

Набор регистров процессора, специфический для модели, доступен с помощью команд RDMSR, WRMSR

6

Возможна физическая адресация памяти с использованием шины с шириной, большей чем 32 разряда

7

В процессоре реализовано исключение Machine Check (исключение с номером 18). Возможно использование бита MCE регистра CR4

8

В процессоре реализована команда сравнения и обмена 8 байт данных CMPXCHG8

9

В процессоре есть локальный APIC

10

Зарезервировано

11

В процессоре реализованы команды быстрого вызова системы SYSENTER и SYSEXIT

12

В процессоре есть регистры Memory Type Range

13

Доступен глобальный бит в PDE и PTE, а также бит PGE в регистре CR4

14

Применена архитектура Machine Check Architecture

15

В процессоре реализованы команды условного перемещения данных CMOVCC и (при установленном бите 0) FCMOVCC и FCOMI

16-22

Зарезервировано

23

Применена технология MMX

24-31

Зарезервировано

Еще одно применение для команды CPUID – определение характеристик кэша, установленного в процессоре. Для этого перед вызовом команды CPUID в регистр EAX необходимо загрузить значение 2. Подробное изучение этой возможности выходит за рамки нашей книги. При необходимости вы узнать все подробности о команде CPUID на сервере Intel в сети Internet по указанному нами ранее адресу.

Программа CPUINFO

Программа CPUINFO определяет модель и характеристики процессора, пользуясь только что описанной нами методикой. Полученная информация выводится на консоль в следующем виде (для процессора Pentium Pro):


	*CPU Information*, (C) A. Frolov, 1997
	
	CPU model: 5
	Vendor ID: GenuineIntel
	
	CPU Signature    00000619
	CPU Feature EDX  0000F9FF
	
	CPU type:     0
	CPU family:   6
	CPU model:    1
	CPU stepping: 9
	
	FPU detected

В листинге 1.4 вы найдете исходный текст модуля, составленного на языке ассемблера. В этом модуле определены все функции, необходимые для распознавания процессора и получения его характеристик.

Листинг 1.4. Файл cpuinfo\askcpu.asm


	; =====================================================
	; Get CPU information
	;
	; (C) A. Frolov, 1997
	;
	; E-mail: frolov@glas.apc.org
	; WWW:    http://www.glasnet.ru/~frolov
	;            or
	;         http://www.dials.ccas.ru/frolov
	; =====================================================
	  .model small
	
	CPU_ID MACRO
	  db 0fh
	  db 0a2h
	ENDM
	
	  .stack 100h
	  .data
	  
	  public _vendor_id_msg
	  public _cpu_model
	  public _cpu_signature
	  public _features_ecx
	  public _features_edx
	  public _features_ebx
	  public _get_cpu_model
	
	_vendor_id_msg db "............", 0dh, 0ah, "$"
	_cpu_model     db 0
	_cpu_signature dd 0
	_features_ecx  dd 0
	_features_edx  dd 0
	_features_ebx  dd 0
	
	  .code
	; ============================================
	; _get_cpu_model
	; ============================================
	  .8086
	
	_get_cpu_model proc
	
	  call cpu_8086
	  cmp ax, 0
	  jz try_80286
	
	  mov _cpu_model, 0
	  jmp end_of_detect
	
	try_80286:
	
	  call cpu_80286
	  cmp ax, 0
	  jz try_80386
	
	  mov _cpu_model, 2
	  jmp end_of_detect
	
	try_80386:
	
	  call cpu_80386
	  cmp ax, 0
	  jz try_80486
	
	  mov _cpu_model, 3
	  jmp end_of_detect
	
	try_80486:
	
	  call cpu_80486
	  cmp ax, 0
	  jz Pent_CPU
	
	  mov _cpu_model, 4
	  jmp end_of_detect
	
	Pent_CPU:
	
	  mov _cpu_model, 5
	
	  .386
	  pusha
	
	  mov eax, 00h
	  CPU_ID
	
	  mov dword ptr _vendor_id_msg, ebx
	  mov dword ptr _vendor_id_msg[+4], edx
	  mov dword ptr _vendor_id_msg[+8], ecx
	
	  cmp eax, 1
	  jl end_of_detect
	  
	  mov eax, 1
	  CPU_ID
	
	  mov _cpu_signature, eax
	  mov _features_ebx, ebx
	  mov _features_edx, edx
	  mov _features_ecx, ecx
	
	  popa
	
	end_of_detect:
	  
	  .8086
	  ret
	
	_get_cpu_model endp
	
	; ============================================
	; cpu_8086
	; ============================================
	cpu_8086 proc
	  pushf
	  pop ax
	  mov cx, ax
	  and ax, 0fffh
	  push ax
	  popf
	  pushf
	  pop ax
	  and ax, 0f000h
	
	  cmp ax, 0f000h
	  je is_8086
	
	  mov ax, 0
	  ret
	
	is_8086:
	  mov ax, 1
	  ret
	
	cpu_8086 endp
	
	; ============================================
	; cpu_80286
	; ============================================
	  .286
	cpu_80286 proc
	
	  mov ax, 0f000h
	  push ax
	  popf
	  pushf
	  pop ax
	  and ax, 0f000h
	  jz is_80286
	
	  mov ax, 0
	  ret
	
	is_80286:
	  mov ax, 1
	  ret
	
	cpu_80286 endp
	
	; ============================================
	; cpu_80386
	; ============================================
	  .386
	cpu_80386 proc
	  pushfd
	  pop eax
	  mov ecx, eax
	  xor eax, 40000h
	  push eax
	  popfd
	  pushfd
	  pop eax
	  xor eax, ecx
	  jz is_80386
	
	  mov ax, 0
	  ret
	
	is_80386:
	  push ecx
	  popfd
	
	  mov ax, 1
	  ret
	
	cpu_80386 endp
	
	; ============================================
	; cpu_80486
	; ============================================
	cpu_80486 proc
	  pushfd
	  pop eax
	  mov ecx, eax
	
	  xor eax, 200000h
	  push eax
	  popfd
	  pushfd
	  pop eax
	  xor eax, ecx
	  je is_80486
	
	  mov ax, 0
	  ret
	
	is_80486:
	
	  mov ax, 1
	  ret
	
	cpu_80486 endp
	  end

Данный файл был оттранслирован при помощи пакетного файла, представленного в листинге 1.5.

Листинг 1.5. Файл cpuinfo\mk.bat


	masm /Zi askcpu.asm,,,,

Главный файл программы приведен в листинге 1.6.

Листинг 1.6. Файл cpuinfo\cpuinfo.c


	// =====================================================
	// Определение типа процессора
	//
	// (C) Фролов А.В, 1997
	//
	// E-mail: frolov@glas.apc.org
	// WWW:    http://www.glasnet.ru/~frolov
	//            или
	//         http://www.dials.ccas.ru/frolov
	// =====================================================
	#include <stdio.h>
	#include <conio.h>
	#include <stdlib.h>
	#include <memory.h>
	               
	extern void GET_CPU_MODEL(void);
	extern char VENDOR_ID_MSG[12];
	extern char CPU_MODEL;
	extern long CPU_SIGNATURE;
	extern long FEATURES_ECX;
	extern long FEATURES_EDX;
	extern long FEATURES_EBX;
	
	int main(void)
	{         
	  char buf[128];
	  printf("*CPU Information*, (C) A. Frolov, 1997\n\n");
	
	  GET_CPU_MODEL();
	  
	  printf("CPU model: %d\n", (unsigned)CPU_MODEL);
	  
	  if(CPU_MODEL >= 5)
	  {
	    memcpy(buf, VENDOR_ID_MSG, 12);
	    buf[12] = 0;
	    printf("Vendor ID: %s\n\n", buf);
	  
	    printf("CPU Signature    %08.8X\n", CPU_SIGNATURE);
	    printf("CPU Feature EDX  %08.8X\n\n", FEATURES_EDX);
	    
	    printf("CPU type:     %d\n", 
	      (CPU_SIGNATURE & 0x3000) >> 12);
	
	    printf("CPU family:   %d\n", 
	      (CPU_SIGNATURE & 0xF00) >> 8);
	
	    printf("CPU model:    %d\n", 
	      (CPU_SIGNATURE & 0xF0) >> 4);
	
	    printf("CPU stepping: %d\n\n", CPU_SIGNATURE & 0xF);
	    
	    if(FEATURES_EDX & 0x1)
	      printf("FPU detected\n");
	
	    if(FEATURES_EDX & 0x800000)
	      printf("MMX supported\n");
	  }
	
	  getch();
	  return 0;
	}
[Назад] [Содеожание] [Дальше]