Лабораторные работы    
 СОДЕРЖАНИЕ
 Введение
 1. Развитие архитектуры
 2. Структура МП
 3. Ресурсы МП
 4. Управление памятью
 5. Защита
 6. Многозадачность
 7. Прерывания и исключения
 8. Инициализация МП
 9. Эмуляция 8086
 Глоссарий
 ПРАКТИКА
 1. Семантический разрыв
 2. CPUID
 3. Защищенный режим
 Вопросы и задания

2. Методика определения модели процессора IA-32

Цель работы: Познакомится с некоторыми различиями процессоров семейства IA-32 и на их основе научиться определять модель процессора.

Теоретическая часть

Развитие вычислительной техники сопровождается совершенствованием центральных процессоров для персональных ЭВМ. Новые модели процессоров обладают не только улучшенной производительностью, но и новыми возможностями (новые регистры, новые наборы команд и прочие изменения в архитектуре). В то же время, разработчики процессоров при проектировании новых моделей основываются на принципах преемственности или обратной совместимости, т.е. новая модель процессора разрабатывается на основе какой-либо существующей архитектуры. Таким образом, программный код для этой архитектуры должен без изменений выполняться и на новой модели процессора. Ряд моделей, полученных в результате последовательного совершенствования какой-либо архитектуры, образует семейство процессоров.

В настоящее время доминирующее положение на рынке центральных процессоров для ЭВМ занимает семейство IA-32. Это семейство открывают 16-разрядные процессоры 8086 и 8088 с 16/8-битной шиной данных и 20-битной шиной адреса. Второе поколение процессоров представлено процессором Intel286, в котором шина адреса была расширена до 24 бит, что позволяло в особом режиме (protected mode) адресовать до 16Мбайт физической памяти. Начиная с третьего поколения (Intel386) архитектура процессоров этого семейства стала 32-битной, а основным режимом работы - защищенный. В новых моделях совершенствовался кэш (Intel486), появились параллельные конвейеры (Pentium), появились новые архитектурные блоки (Pentium MMX), появился встроенный кэш второго уровня (P6). Эти изменения сопровождались также добавлением новых возможностей при работе в защищенном режиме: VME (Virtual Mode Extension) у Pentium, PAE (Physical Address Extension) у P6 и др.

В семействе IA-32 декларируется программная совместимость моделей процессоров сверху вниз. Это значит, что код, написанный для 8086 должен работать и на Intel386, и на Pentium 4. С другой стороны, программы, разработанные для более поздних процессоров, могут не работать на более ранних, если в них используются какие-либо специфические особенности новой модели. Так, приложение, использующее набор команд MMX, без специального эмулятора не сможет работать на Intel486. Очевидно, что таким приложениям необходимо определить модель процессора, прежде чем использовать ту или иную специфическую возможность. Модель процессора однозначно определяется по значению регистра DX/EDX после аппаратного сброса, но, увы, это значение хранится недолго, поэтому прикладным программам приходится применять нетривиальные способы для определения возможностей процессора.

В данной работе рассматриваются наиболее часто используемые способы определения модели процессора. Процедура определения модели сначала предполагает, что процессор является самой старой моделью (8086/88), затем, манипулируя регистром FLAGS/EFLAGS, последовательно проверяет предположение о том, что процессор - Intel286, затем - Intel386, затем - Intel486. Модель более поздних процессоров однозначно определяется специальной командой CPUID, которая была реализована в поздних моделях Intel486.

Для того, чтобы отличить 8086/88 от более поздних моделей, обычно используют два способа. В первом способе определяется разница в выполнении команды PUSH SP. 8086/88 сначала декрементирует SP, а только потом помещает это значение на вершину стека. Начиная с Intel286, при выполнении этой команды процессор сначала помещает значение SP на вершину стека, а только потом декрементирует SP. Таким образом, если после выполнения этой команды слово на вершине стека отличается от SP, то это процессор Intel286 или более поздний, в противном случае - это процессор 8086/88.

PUSH SP

Второй способ предполагает манипулирование регистром FLAGS. В процессоре 8086/88 биты 12-15 FLAGS были зарезервированы, их значение всегда 1, и изменить их нельзя. У более поздних процессоров зарезервированный бит 15 всегда 0 и изменить его нельзя.

EFLAGS

Дальнейшая идентификация происходит по старшим битам регистра FLAGS и зависит от режима работы. Режим работы определяется по младшему биту Machine Status Word (мл. слово CR0), это слово можно получить при помощи команды SMSW AX. В реальном режиме младший бит - 0, в защищенном - 1.

Биты 12-13 содержат поле IOPL (уровень привилегий для операций ввода-вывода), а бит 14 - NT (Nested Task - в защищенном режиме сигнализирует о вложенности задач и при IRET инициирует переключение задач). У Intel286 в реальном режиме биты 12-15 всегда 0 и их изменить нельзя, у Intel386 эти биты можно поменять, хотя это и не влияет на работу процессора. В защищенном режиме по этим битам нельзя отличить Intel286 от Intel386. Косвенным признаком того, что программа выполняется на процессоре Intel286, может служить то, что зарезервированные биты 4-15 MSW содержат 1.

Чтобы отличить Intel386 от Intel486 надо попытаться изменить бит 18 регистра EFLAGS. У Intel386 этот бит изменить нельзя, он зарезервирован. У Intel486 этот бит отвечает за включение контроля выравнивания (AC - Alignment Check). И, наконец, если программа может изменить 21-й бит регистра EFLAGS, то процессор поддерживает инструкцию CPUID, с помощью которой можно однозначно определить его модель. Следует отметить, что выполнение команды CPUID в защищенном режиме не гарантирует получение корректной информации для некоторых процессоров. Выполнение команды CPUID зависит от значения регистра EAX, которое определяет подфункцию этой команды. Для команды CPUID принято номер подфункции (значение EAX) записывать рядом в скобках.

EAX=0 - определить производителя и максимальный номер подфункции. После выполнения CPUID(0) EAX содержит максимальный номер подфункции, а EBX-EDX-ECX - идентификационную строку производителя, например: "GenuineIntel" (EBX=756E6547h EDX=49656E69h ECX=6C65746Eh), "AuthenticAMD", "CyrixInstead", "CentaurHauls" и т.д.

EAX=1 - определить модель и возможности процессора. После выполнения CPUID(1) EAX содержит код модели процессора, а EDX - битовое поле, идентифицирующее возможности процессора. Код модели расшифровывается следующим образом:

Биты 8-11
Семейство
Биты 4-7
Модель
Биты 0-3
Модификация
Расшифровка
GenuineIntelAuthenticAMD
01000001xxxxi486DX 
0010 i486DX 
0011 i486SX 
0100 i486DX2 
0101 i486SL 
1000 i486SX2 
1110 i486DX4Am5x86
1111  Am5x86
01010001xxxxPentium 60,66K5-PR120,133
0010 Pentium 75-200K5-PR166
0100 Pentium MMX 
0110  K6
0111  K6
1000  K6-2
1001  K6-3
1101  K6-2+, K6-III+
01100001xxxxPentium ProAthlon 0.25µ
0011 Pentium II (Klamath)Duron
0100  Athlon 0.18µ
0101 P-II (Deschutes), Celeron (Covington), Xeon 
0110 Celeron (Mendocino)Athlon XP
0111 Pentium III (Katmai) 
1000 Pentium III (Coppermine), Celeron 533A+ 
1010 Pentium III Xeon (Cascades) 
11110000xxxxPentium 4 

Вот расшифровка некоторых битов в EDX:

БитНазваниеРасшифровка
0FPUНаличие математического сопроцессора
4TSCНаличие счетчика меток реального времени
6PAEВозможность расширения физического адреса до 36 бит
9APICНаличие встроенного контроллера прерываний APIC
18PNПоддержка серийного номера по инструкции CPUID(3)
22ACPIПоддержка расширенного управления питанием ACPI
23MMXПоддержка MMX
25XMMНаличие блока XMM (поддержка SSE)
26SSE2Поддержка SSE2
29TMТермоконтроль

Различные модели архитектуры P6 (Pentium II-III, Celeron, Xeon) отличаются размерами кэша, сообщаемыми по команде CPUID(2).

Как видно, с помощью команды CPUID можно также определить наличие в процессоре встроенных блоков FPU и XMM. Для процессоров, не поддерживающих CPUID, наличие сопроцессора определяется попыткой прочитать его регистр статуса:

FNINIT
MOV [status],5A5Ah
FNSTSW [status]
MOV AX,[status]
CMP AL,0
JNE NO_FPU_PRESENT

После инициализации младший байт слова статуса FPU содержит ноль. Если при попытке его сохранения в памяти этот ноль не появился, очевидно, FPU отсутствует.

Задание: Напишите программу, определяющую модель процессора и наличие сопроцессора. Считайте, что программа работает в реальном режиме.

Чтобы ассемблер позволил вам использовать 32-битные регистры и новые команды Intel386, следует вставить директиву ".386". Примерный вид программы (вариант для создания .COM-файла):

MODEL TINY
.CODE
ORG 100h
Entry:
; наличие сопроцессора можно проверить сразу же
; проверяем, что процессор новее 8086/8088
; проверяем, что процессор новее Intel286
.386
; проверяем, что процессор новее Intel386
; проверяем, что процессор поддерживает CPUID
; получаем информацию о процессоре при помощи CPUID
MOV EAX,1
DB 0Fh, 0A2h
; выводим информацию
MOV AH,4Ch
INT 21h ; завершение работы
END Entry

Если ассемблер не распознает мнемонику какой-либо команды, ее можно вставить в текст программы непосредственно в виде кода. В приведенном примере таким способом вставлена команда CPUID (ее код - 0Fh 0A2h). Коды команд, использующие 32-битные регистры такие же, как и соответствующие им 16-битные команды, однако в 16-битной программе ассемблер перед каждой такой командой автоматически вставляет префикс замены размера операндов, чтобы программа выполнялась корректно. Т.е. Командам PUSHF (поместить в стек 16-битное значение регистра FLAGS (младшая часть EFLAGS)) и PUSHFD (поместить в стек 32-битное значение регистра EFLAGS) соответствует один и тот же код - 9Ch, однако в 16-битной программе второй команде должен предшествовать префикс 66h (ассемблер вставляет его автоматически). При компоновке с помощью TLINK необходимо указать опцию "/3", разрешающую использование 32-битных команд. Опция "/t" отвечает за генерацию .COM-файла.

Контрольные вопросы:

  1. Укажите разрядность шин адреса и данных для следующих процессоров: 8086, 8088, 80286, 80386, i486DX, Pentium, P6 (Pentium Pro).
  2. Перечислите основных представителей семейства IA-32 с 32-разрядной архитектурой.
  3. Предложите способ определения наличия сопроцессора по регистру CR0 (MSW).
  4. Предложите способ определения наличия сопроцессора по команде CPUID(1).