Проверка конфигурации процессора

Тема в разделе "WASM.BEGINNERS", создана пользователем s3dworld, 26 янв 2011.

  1. s3dworld

    s3dworld Сергей

    Публикаций:
    0
    Регистрация:
    16 мар 2010
    Сообщения:
    387
    Адрес:
    Ртищево
    Всем доброго дня!

    Решил сейчас написать функцию на ассемблере (тут они называются процедурами) для проверки конфигурации процессора. Но столкнулся с некоторым непониманием.

    Во-первых, мне нужно определить, поддерживает ли процессор 32-битные инструкции. Во-вторых, мне нужно определить, поддерживает ли процессор 64-битные инструкции. В общем решил для этого дела разобраться с инструкцией CPUID (хотя возможно мне не она и нужна-то). Нашёл про CPUID статью на русской Wiki: http://ru.wikipedia.org/wiki/Cpuid.

    Получается, что для того чтобы определить поддерживается ли сама инструкция CPUID в процессоре, мне нужно поработать с EFLAGS. А ведь EFLAGS появился только в 32-битных процессорах. А что будет, если вдруг мой код запустят на 16-битном процессоре (например на i286)? У него нет расширенного регистра флагов, то есть нет 21 бита там. Если честно, мне кажется очень сомнительная такая проверка. Я чего-то упустил или есть другой способ проверить?
     
  2. spa

    spa Active Member

    Публикаций:
    0
    Регистрация:
    9 мар 2005
    Сообщения:
    2.240
    из той самой вики
     
  3. Pavia

    Pavia Well-Known Member

    Публикаций:
    0
    Регистрация:
    17 июн 2003
    Сообщения:
    2.409
    Адрес:
    Fryazino
    http://www.intel.com/Assets/PDF/appnote/241618.pdf
    Тоже проверяется по битам. Но другим. Вот читай там и код есть.
     
  4. s3dworld

    s3dworld Сергей

    Публикаций:
    0
    Регистрация:
    16 мар 2010
    Сообщения:
    387
    Адрес:
    Ртищево
    Нашёл статью на этом сайте: http://www.wasm.ru/article.php?article=hardzen

    Там написано:

    И вот я не понял. Регистр FLAGS 16-битный, как это тогда тут вообще указана команда POPF? Она же берёт из стека 16-битное значение и вносит его в регистр FLAGS. А ведь бит 18 никак не входит в 16-бит. Вот я и запутался.

    В общем если кто-то знает как проверить является ли процессор 32-битным (то есть поддерживает 32-битные инструкции и имеет регистр EFLAGS), напиши, пожалуйста как это проверить. Вот именно после такой проверки можно будет проверять на CPUID по той самой статье с Wiki. Ведь там на Wiki написано:

    Как такую проверку сделать?
     
  5. FatMoon

    FatMoon New Member

    Публикаций:
    0
    Регистрация:
    28 ноя 2002
    Сообщения:
    954
    Адрес:
    Russia
    s3dworld
    процессоры поддерживают 32-битные инструкции начиная с 386. Можешь не делать такую проверку - не думаю, что твоей программе доведется попасть на 286-й
     
  6. s3dworld

    s3dworld Сергей

    Публикаций:
    0
    Регистрация:
    16 мар 2010
    Сообщения:
    387
    Адрес:
    Ртищево
    Кое что накапал в Интернете и на основании этого переделал под свои нужды функцию определения поддержки CPUID. Вот привожу код (просто не знаю насколько он правильный):

    Код (Text):
    1. ; -------------------------------------------------------------------------------------
    2. ; Название: bool TestCPUID(void);
    3. ; Описание: Проверка процессора на допустимость инструкции CPUID
    4. ; Результат: Если false - инструкция CPUID не поддерживается, в противном случае - true
    5. ; -------------------------------------------------------------------------------------
    6. TestCPUID:
    7.     pushf
    8.     mov DX,0xF000
    9.     sub AX,AX
    10.     push AX
    11.     popf
    12.     pushf
    13.     pop AX
    14.     popf
    15.     and AX,DX
    16.     cmp AX,DX
    17.     je _testThereCPUID_False
    18.    
    19.     push SP
    20.     pop BX
    21.     cmp BX,SP
    22.     jne _testThereCPUID_False
    23.    
    24.     pushf
    25.     mov AX,DX
    26.     push AX
    27.     popf
    28.     pushf
    29.     pop AX
    30.     popf
    31.     and AX,DX
    32.     je _testThereCPUID_False
    33.    
    34.     db 0x66
    35.     pushf
    36.     db 0x66
    37.     pushf
    38.     db 0x66
    39.     pop AX
    40.     db 0x66
    41.     or AX,0000h
    42.     db 0x04,0x00
    43.     db 0x66
    44.     push AX
    45.     db 0x66
    46.     popf
    47.     db 0x66
    48.     pushf
    49.     db 0x66
    50.     pop AX
    51.     db 0x66
    52.     popf
    53.     db 66h
    54.     test AX,0x0000
    55.     db 0x04,0x00
    56.     jz _testThereCPUID_False
    57.    
    58.     db 0x66
    59.     pushf
    60.     db 0x66
    61.     pushf
    62.     db 0x66
    63.     pop AX
    64.     db 0x66
    65.     mov BX,AX
    66.     db 0x66
    67.     xor AX,0x0000
    68.     db 0x20,0x00
    69.     db 0x66
    70.     push AX
    71.     db 0x66
    72.     popf
    73.     db 0x66
    74.     pushf
    75.     db 0x66
    76.     pop AX
    77.     db 0x66
    78.     popf
    79.     db 0x66
    80.     and AX,0x0000
    81.     db 0x20,0x00
    82.     db 0x66
    83.     and BX,0x0000
    84.     db 0x20,0x00
    85.     db 0x66
    86.     cmp AX,BX
    87.     je _testThereCPUID_False
    88.    
    89.     pushfd
    90.     pop EAX
    91.     mov EBX,EAX
    92.     xor EAX,0x200000
    93.     push EAX
    94.     popfd
    95.     pushfd
    96.     pop EAX
    97.     xor EAX,EBX
    98.     jne _testThereCPUID_True
    99.  
    100. _testThereCPUID_False:
    101.     xor AX,AX
    102.     jmp _testThereCPUID_Exit
    103.    
    104. _testThereCPUID_True:
    105.     mov AX,1
    106.    
    107. _testThereCPUID_Exit:
    108. ret
     
  7. s3dworld

    s3dworld Сергей

    Публикаций:
    0
    Регистрация:
    16 мар 2010
    Сообщения:
    387
    Адрес:
    Ртищево
  8. s3dworld

    s3dworld Сергей

    Публикаций:
    0
    Регистрация:
    16 мар 2010
    Сообщения:
    387
    Адрес:
    Ртищево
    Исправил. Теперь всё работает. Если кому нужна функция определения поддержки CPUID инструкции, то держите:

    Код (Text):
    1. ; -------------------------------------------------------------------------------------
    2. ; Название: bool TestCPUID(void);
    3. ; Описание: Проверка процессора на допустимость инструкции CPUID
    4. ; Результат: Если false - инструкция CPUID не поддерживается, в противном случае - true
    5. ; -------------------------------------------------------------------------------------
    6. TestCPUID:
    7.     pushf
    8.     mov DX,0xF000
    9.     sub AX,AX
    10.     push AX
    11.     popf
    12.     pushf
    13.     pop AX
    14.     popf
    15.     and AX,DX
    16.     cmp AX,DX
    17.     jne _testCPUID_CPU_8088
    18.     jmp _testThereCPUID_False
    19.    
    20. _testCPUID_CPU_8088:
    21.     push SP
    22.     pop BX
    23.     cmp BX,SP
    24.     je _testCPUID_CPU_186
    25.     jmp _testThereCPUID_False
    26.    
    27. _testCPUID_CPU_186:
    28.     pushf
    29.     mov AX,DX
    30.     push AX
    31.     popf
    32.     pushf
    33.     pop AX
    34.     popf
    35.     and AX,DX
    36.     jne _testCPUID_CPU_286
    37.     jmp _testThereCPUID_False
    38.  
    39. _testCPUID_CPU_286:
    40.     pushfd
    41.     pushfd
    42.     pop EAX
    43.     or EAX,0x00040000
    44.     push EAX
    45.     popfd
    46.     pushfd
    47.     pop EAX
    48.     popfd
    49.     test EAX,0x00040000
    50.     jnz _testCPUID_CPU_386
    51.     jmp _testThereCPUID_False
    52.  
    53. _testCPUID_CPU_386:
    54.     pushfd
    55.     pushfd
    56.     pop EAX
    57.     mov EBX,EAX
    58.     xor EAX,0x00200000
    59.     push EAX
    60.     popfd
    61.     pushfd
    62.     pop EAX
    63.     popfd
    64.     and EAX,0x00200000
    65.     and EBX,0x00200000
    66.     cmp EAX,EBX
    67.     jne _testCPUID_CPU_486
    68.     jmp _testThereCPUID_False
    69.  
    70. _testCPUID_CPU_486:
    71.     pushfd
    72.     pop EAX
    73.     mov EBX,EAX
    74.     xor EAX,0x00200000
    75.     push EAX
    76.     popfd
    77.     pushfd
    78.     pop EAX
    79.     xor EAX,EBX
    80.     jne _testThereCPUID_True
    81.  
    82. _testThereCPUID_False:
    83.     xor AX,AX
    84.     jmp _testThereCPUID_Exit
    85.    
    86. _testThereCPUID_True:
    87.     mov AX,1
    88.    
    89. _testThereCPUID_Exit:
    90. ret
     
  9. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    s3dworld
    Код (Text):
    1. CPUTest:
    2.  mov dx, 0xF000
    3.  pushf
    4.  pop ax
    5.  push ax
    6.  and ax, 0x0FFF
    7.  push ax
    8.  popf
    9.  pushf
    10.  pop ax
    11.  popf
    12.  anx ax, dx
    13.  test ax, dx
    14.  jz .8086
    15.  mov ax, 2
    16.  push ax
    17.  smsw ax
    18.  test al, 1
    19.  jz .not_v8086
    20.  pop ax
    21.  or ax, 8
    22.  push ax
    23. .not_v8086
    24.  pushf
    25.  pop ax
    26.  push ax
    27.  or ax, dx
    28.  push ax
    29.  popf
    30.  pushf
    31.  pop ax
    32.  popf
    33.  and ax, dx
    34.  jz .retn
    35.  pop ax
    36.  inc ax
    37.  push ax
    38.  pushfd
    39.  pop cx
    40.  pop ax
    41.  push ax
    42.  push cx
    43.  mov dx, ax
    44.  xor dx, 4
    45.  push dx
    46.  push cx
    47.  popfd
    48.  pushfd
    49.  pop cx
    50.  pop dx
    51.  popfd
    52.  xor ax, dx
    53.  jz .retn
    54.  pop ax
    55.  inc ax
    56.  push ax
    57.  pushfd
    58.  pop cx
    59.  pop ax
    60.  push ax
    61.  push cx
    62.  mov dx, ax
    63.  xor dx, 32
    64.  push dx
    65.  push cx
    66.  popfd
    67.  pushfd
    68.  pop cx
    69.  pop dx
    70.  popfd
    71.  xor ax, dx
    72.  jz .retn
    73.  pop ax
    74.  inc ax
    75.  retn
    76. .8086:
    77.  push sp
    78.  pop ax
    79.  cmp ax, sp
    80.  jz .unknown
    81.  xor ax, ax
    82.  retn
    83. .unknown:
    84.  mov ax, 6
    85.  retn
    86. .retn:
    87.  pop ax
    88.  retn
    Возвращает:
    - 0: 8086
    - 1: 80186
    - 2: 80286
    - 3: 80386
    - 4: 80486
    - 5: Pentium или выше
    - 6: неизвестный CPU
    - бит 3: виртуальный 8086
    хотя можно расшифровать и неизвестные процы, а также сделать проверки для 8086/8088 и 80186/80188
    FatMoon
    Ну у меня есть 8088, и я на нем иногда что-нибудь гоняю для проверки