mov cx, ax. and ax, 0fffh. push ax. and ax, 0f000h. cmp ax, 0f000h. Модель Intel 80286. mov ax, 0f000h. Потом программа проверят, изменилось ли содержимое указанных битов регистра FLAGS
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
В данном процессоре, когда он работает в реальном режиме адресации, биты 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
Для того чтобы отличить этот процессор от процессоров старших моделей, можно попробовать установить в регистре 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
Отличительная особенность этого процессора – невозможность изменения состояния бита 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
Перед вызовом этой команды необходимо загрузить в регистр EAX значение, которое определяет выполняемые действия. В первый раз нужно вызвать команду CPUID, загрузив предварительно в регистр EAX нулевое значение: mov eax, 00h CPU_ID Команда вернет в регистре EAX максимальное значение, которое можно передавать команде CPUID для определения выполняемых действий. Кроме того, в регистрах EBX, ECX и EDX будут находиться байты текстовой строки описания фирмы-изготовителя процессора.
Следующая последовательность команд перепишет эти байты в буфер _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:
Биты 12 и 13 определяют тип процессора:
Таблица, с помощью которой по содержимому трех полей слова сигнатуры (тип процессора, код семейства и код модели) можно распознать процессор:
Биты, возвращаемых командой CPUID в регистре EDX (слово, состоящее из отдельных флагов, характеризующих возможности процессора).
Пример:
; ================================== ; Get CPU information ; ================================== . 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
Данный файл был оттранслирован при помощи следующего пакетного файла: masm /Zi askcpu. asm,,,,
Главный файл программы: // ===================================================== // Определение типа процессора // ===================================================== #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]; 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; }
Воспользуйтесь поиском по сайту: ©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...
|