2016-04-10 3 views
3

Я печатаю некоторую информацию о CPU в своей ОС с помощью инструкции CPUID.Неисправность торговой марки CPUID?

Чтение и печать строки поставщика (GenuineIntel) работает хорошо, но чтение строки бренда дает мне немного странную строку.

ok cpu-info <= Run command 
CPU Vendor name: GenuineIntel <= Vendor string is good 
CPU Brand: D: l(R) Core(TMD: CPU  MD: <= What..? 
ok 

Vendor строка должна быть:

Intel(R) Core(TM) i5 CPU  M 540 

Но то, что я получил это:

D: l(R) Core(TMD: CPU  MD: 

C++ код:

  char vendorString[13] = { 0, }; 
      Dword eax, ebx, ecx, edx; 
      ACpuid(0, &eax, &ebx, &ecx, &edx); 
      *((Dword*)vendorString) = ebx; 
      *((Dword*)vendorString + 1) = edx; 
      *((Dword*)vendorString + 2) = ecx; 
      Console::Output.Write(L"CPU vendor name: "); 
      for (int i = 0; i < 13; i++) { 
       Console::Output.Write((wchar_t)(vendorString[i])); 
      } 
      Console::Output.WriteLine(); 

      char brandString[48] = { 0, }; 
      ACpuid(0x80000002, &eax, &ebx, &ecx, &edx); 
      *((Dword*)brandString) = eax; 
      *((Dword*)brandString + 1) = ebx; 
      *((Dword*)brandString + 2) = ecx; 
      *((Dword*)brandString + 3) = edx; 
      ACpuid(0x80000003, &eax, &ebx, &ecx, &edx); 
      *((Dword*)brandString + 4) = eax; 
      *((Dword*)brandString + 5) = ebx; 
      *((Dword*)brandString + 6) = ecx; 
      *((Dword*)brandString + 7) = edx; 
      ACpuid(0x80000004, &eax, &ebx, &ecx, &edx); 
      *((Dword*)brandString + 8) = eax; 
      *((Dword*)brandString + 9) = ebx; 
      *((Dword*)brandString + 10) = ecx; 
      *((Dword*)brandString + 11) = edx; 
      Console::Output.Write(L"CPU brand: "); 
      for (int i = 0; i < 48; i++) { 
       Console::Output.Write((wchar_t) brandString[i]); 
      } 
      Console::Output.WriteLine(); 

ПРИМЕЧАНИЕ:

  1. Эта программа является приложением UEFI. Нет проблем с разрешениями.

  2. Консоль - это класс-оболочка для консоли EFI. Не C#.

  3. Dword = неподписанных 32bit целое

код Ассамблеи (MASM):

;Cpuid command 
;ACpuid(Type, pEax, pEbx, pEcx, pEdx) 
ACpuid Proc 
    ;Type => Rcx 
    ;pEax => Rdx 
    ;pEbx => R8 
    ;pEcx => R9 
    ;pEdx => [ rbp + 48 ] ? 
    push rbp 
    mov rbp, rsp 
    push rax 
    push rsi 

    mov rax, rcx 
    cpuid 
    mov [ rdx ], eax 
    mov [ r8 ], ebx 
    mov [ r9 ], ecx 
    mov rsi, [ rbp + 48 ] 
    mov [ rsi ], rdx 

    pop rsi 
    pop rax 
    pop rbp 
    ret 
ACpuid Endp 
+0

Глупый вопрос. Имеет ли ваша программа полные разрешения? – Auriga

+0

Вы имеете в виду C++ или C#? –

+0

@MichaelPetch C++. Консоль - это пространство имен для консоли EFI. (И Console :: Output - консольный вывод). Неконсольный класс в C#. – Gippeumi

ответ

5

Я согласен с Россом Ридж, что вы должны использовать компилятор характеристическая __cpuid. Что касается того, почему ваш код, вероятно, не работает, как есть - есть некоторые ошибки, которые вызовут проблемы.


CPUID уничтожает содержимое RAX, RBX, RCX и RDX и пока вы делаете это в вашем коде:

cpuid 
mov [ rdx ], eax 

RDX был разрушен к моменту выполнения mov [ rdx ], eax, указав указатель в RDX inv Алид. Вам нужно будет переместить RDX в другой регистр перед использованием инструкции CPUID.

согласно Windows 64-bit Calling Convention эти летучие регистры, которые должны быть сохранены с помощью вызывающей:

регистров RAX, RCX, RDX, R8, R9, R10, R11, считаются неустойчивыми и должны быть считаются уничтоженными по функциональным вызовам (если в противном случае безопасность не будет доказана путем анализа, такого как оптимизация всей программы).

Это нелетучие те, которые должны быть сохранены в вызываемым:

Регистры RBX, RBP, RDI, RSI, RSP, R12, R13, R14 и R15 считаются энергонезависимыми и должны быть сохранены и восстановлены с помощью функции, которая их использует.

Мы можем использовать R10 (летучий регистр) для хранения RDX временно. Вместо использования RSI в коде можно использовать повторно R10 для уточнения значения на pEdx. Нам не нужно сохранять RSI, если мы его не используем. CPUID уничтожает RBX и RBX является энергонезависимым, поэтому нам необходимо его сохранить. RAX является изменчивым, поэтому нам не нужно его сохранять.


В коде у вас есть эта строка:

mov [ rsi ], rdx 

RSI является адресом памяти (pEdx) при условии, вызывающей для сохранения значения в EDX. Код, который у вас есть, переместил бы содержимое 8-байтового регистра RDX в ячейку памяти, которая ожидала 4-байтовый DWORD. Это может привести к сбою данных в вызывающем. Это на самом деле должно было быть:

mov [ rsi ], edx 

Со всеми выше в виду, мы могли бы код по ACpuid рутинных так:

option casemap:none 
.code 

;Cpuid command 
;ACpuid(Type, pEax, pEbx, pEcx, pEdx) 
ACpuid Proc 
    ;Type => Rcx 
    ;pEax => Rdx 
    ;pEbx => R8 
    ;pEcx => R9 
    ;pEdx => [ rbp + 48 ] ? 
    push rbp 
    mov rbp, rsp 
    push rbx   ; Preserve RBX (destroyed by CPUID) 

    mov r10, rdx  ; Save RDX before CPUID 
    mov rax, rcx 
    cpuid 
    mov [ r10 ], eax 
    mov [ r8 ], ebx 
    mov [ r9 ], ecx 
    mov r10, [ rbp + 48 ] 
    mov [ r10 ], edx ; Last parameter is pointer to 32-bit DWORD, 
        ; Move EDX to the memory location, not RDX 

    pop rbx 
    pop rbp 
    ret 
ACpuid Endp 

end 
+0

Я также предлагаю изменить подпись функции, чтобы просто передать один указатель на структура! Упрощенный код на обоих концах. (Но еще сложнее, чем использовать компилятор, встроенный как '__cpuid()'). –

+0

@PeterCordes: Я намеренно не меняю структуру своего кода. Я определял основные проблемы, которые отвечали бы за то, что его код не функционирует должным образом. Лучшее решение в первой строке моего ответа. Используйте встроенный компилятор __cpuid, и процедура ассемблера не нужна. –

Смежные вопросы