Всем доброго дня! Решил сейчас написать функцию на ассемблере (тут они называются процедурами) для проверки конфигурации процессора. Но столкнулся с некоторым непониманием. Во-первых, мне нужно определить, поддерживает ли процессор 32-битные инструкции. Во-вторых, мне нужно определить, поддерживает ли процессор 64-битные инструкции. В общем решил для этого дела разобраться с инструкцией CPUID (хотя возможно мне не она и нужна-то). Нашёл про CPUID статью на русской Wiki: http://ru.wikipedia.org/wiki/Cpuid. Получается, что для того чтобы определить поддерживается ли сама инструкция CPUID в процессоре, мне нужно поработать с EFLAGS. А ведь EFLAGS появился только в 32-битных процессорах. А что будет, если вдруг мой код запустят на 16-битном процессоре (например на i286)? У него нет расширенного регистра флагов, то есть нет 21 бита там. Если честно, мне кажется очень сомнительная такая проверка. Я чего-то упустил или есть другой способ проверить?
http://www.intel.com/Assets/PDF/appnote/241618.pdf Тоже проверяется по битам. Но другим. Вот читай там и код есть.
Нашёл статью на этом сайте: http://www.wasm.ru/article.php?article=hardzen Там написано: И вот я не понял. Регистр FLAGS 16-битный, как это тогда тут вообще указана команда POPF? Она же берёт из стека 16-битное значение и вносит его в регистр FLAGS. А ведь бит 18 никак не входит в 16-бит. Вот я и запутался. В общем если кто-то знает как проверить является ли процессор 32-битным (то есть поддерживает 32-битные инструкции и имеет регистр EFLAGS), напиши, пожалуйста как это проверить. Вот именно после такой проверки можно будет проверять на CPUID по той самой статье с Wiki. Ведь там на Wiki написано: Как такую проверку сделать?
s3dworld процессоры поддерживают 32-битные инструкции начиная с 386. Можешь не делать такую проверку - не думаю, что твоей программе доведется попасть на 286-й
Кое что накапал в Интернете и на основании этого переделал под свои нужды функцию определения поддержки CPUID. Вот привожу код (просто не знаю насколько он правильный): Код (Text): ; ------------------------------------------------------------------------------------- ; Название: bool TestCPUID(void); ; Описание: Проверка процессора на допустимость инструкции CPUID ; Результат: Если false - инструкция CPUID не поддерживается, в противном случае - true ; ------------------------------------------------------------------------------------- TestCPUID: pushf mov DX,0xF000 sub AX,AX push AX popf pushf pop AX popf and AX,DX cmp AX,DX je _testThereCPUID_False push SP pop BX cmp BX,SP jne _testThereCPUID_False pushf mov AX,DX push AX popf pushf pop AX popf and AX,DX je _testThereCPUID_False db 0x66 pushf db 0x66 pushf db 0x66 pop AX db 0x66 or AX,0000h db 0x04,0x00 db 0x66 push AX db 0x66 popf db 0x66 pushf db 0x66 pop AX db 0x66 popf db 66h test AX,0x0000 db 0x04,0x00 jz _testThereCPUID_False db 0x66 pushf db 0x66 pushf db 0x66 pop AX db 0x66 mov BX,AX db 0x66 xor AX,0x0000 db 0x20,0x00 db 0x66 push AX db 0x66 popf db 0x66 pushf db 0x66 pop AX db 0x66 popf db 0x66 and AX,0x0000 db 0x20,0x00 db 0x66 and BX,0x0000 db 0x20,0x00 db 0x66 cmp AX,BX je _testThereCPUID_False pushfd pop EAX mov EBX,EAX xor EAX,0x200000 push EAX popfd pushfd pop EAX xor EAX,EBX jne _testThereCPUID_True _testThereCPUID_False: xor AX,AX jmp _testThereCPUID_Exit _testThereCPUID_True: mov AX,1 _testThereCPUID_Exit: ret
Что-то не так. Всё время выводит что не поддерживается CPUID. Делал по этой статье: http://www.realcoding.net/articles/primery-nebolshikh-podprogramm-na-assemblere.html#dtct Неужели там ошибка?
Исправил. Теперь всё работает. Если кому нужна функция определения поддержки CPUID инструкции, то держите: Код (Text): ; ------------------------------------------------------------------------------------- ; Название: bool TestCPUID(void); ; Описание: Проверка процессора на допустимость инструкции CPUID ; Результат: Если false - инструкция CPUID не поддерживается, в противном случае - true ; ------------------------------------------------------------------------------------- TestCPUID: pushf mov DX,0xF000 sub AX,AX push AX popf pushf pop AX popf and AX,DX cmp AX,DX jne _testCPUID_CPU_8088 jmp _testThereCPUID_False _testCPUID_CPU_8088: push SP pop BX cmp BX,SP je _testCPUID_CPU_186 jmp _testThereCPUID_False _testCPUID_CPU_186: pushf mov AX,DX push AX popf pushf pop AX popf and AX,DX jne _testCPUID_CPU_286 jmp _testThereCPUID_False _testCPUID_CPU_286: pushfd pushfd pop EAX or EAX,0x00040000 push EAX popfd pushfd pop EAX popfd test EAX,0x00040000 jnz _testCPUID_CPU_386 jmp _testThereCPUID_False _testCPUID_CPU_386: pushfd pushfd pop EAX mov EBX,EAX xor EAX,0x00200000 push EAX popfd pushfd pop EAX popfd and EAX,0x00200000 and EBX,0x00200000 cmp EAX,EBX jne _testCPUID_CPU_486 jmp _testThereCPUID_False _testCPUID_CPU_486: pushfd pop EAX mov EBX,EAX xor EAX,0x00200000 push EAX popfd pushfd pop EAX xor EAX,EBX jne _testThereCPUID_True _testThereCPUID_False: xor AX,AX jmp _testThereCPUID_Exit _testThereCPUID_True: mov AX,1 _testThereCPUID_Exit: ret
s3dworld Код (Text): CPUTest: mov dx, 0xF000 pushf pop ax push ax and ax, 0x0FFF push ax popf pushf pop ax popf anx ax, dx test ax, dx jz .8086 mov ax, 2 push ax smsw ax test al, 1 jz .not_v8086 pop ax or ax, 8 push ax .not_v8086 pushf pop ax push ax or ax, dx push ax popf pushf pop ax popf and ax, dx jz .retn pop ax inc ax push ax pushfd pop cx pop ax push ax push cx mov dx, ax xor dx, 4 push dx push cx popfd pushfd pop cx pop dx popfd xor ax, dx jz .retn pop ax inc ax push ax pushfd pop cx pop ax push ax push cx mov dx, ax xor dx, 32 push dx push cx popfd pushfd pop cx pop dx popfd xor ax, dx jz .retn pop ax inc ax retn .8086: push sp pop ax cmp ax, sp jz .unknown xor ax, ax retn .unknown: mov ax, 6 retn .retn: pop ax retn Возвращает: - 0: 8086 - 1: 80186 - 2: 80286 - 3: 80386 - 4: 80486 - 5: Pentium или выше - 6: неизвестный CPU - бит 3: виртуальный 8086 хотя можно расшифровать и неизвестные процы, а также сделать проверки для 8086/8088 и 80186/80188 FatMoon Ну у меня есть 8088, и я на нем иногда что-нибудь гоняю для проверки