Сломанная строка бренда CPUID?

Я печатаю некоторую информацию о CPU в моей ОС, используя инструкцию 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

Строка поставщика должна быть:

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. Console — это класс-оболочка для консоли EFI. Не C # материал.

  3. Dword = 32-разрядное целое число без знака

Код сборки (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

3

Решение

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


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

cpuid
mov [ rdx ], eax

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

В соответствии с Windows 64-bit Соглашение о вызовах это изменчивые регистры, которые должны быть сохранены гость:

Регистры 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
5

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]