Я печатаю некоторую информацию о 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();
НОТА:
Эта программа является приложением UEFI. Нет проблем с разрешениями.
Console — это класс-оболочка для консоли EFI. Не C # материал.
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
Я согласен с Россом Риджем, что вы должны использовать встроенный компилятор __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
Других решений пока нет …