2016-04-10 11 views
3

CPUID命令を使用して、私のOSに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. コンソールは、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 
+0

愚かな質問:私たちはACpuidルーチンをこのようにコーディングすることができ念頭に置いて、上記のすべてと

mov [ rsi ], edx 

。あなたのプログラムは完全な権限を持っていますか? – Auriga

+0

C++またはC#を意味しますか? –

+0

@MichaelPetch C++。コンソールはEFIコンソールのネームスペースです(コンソール::出力はコンソール出力です)。C#のコンソールクラスではありません。 – Gippeumi

答えて

5

は、私はあなたが本来の__cpuidコンパイラを使用する必要があることをロスリッジに同意します。なぜあなたのコードはおそらく動作しないのでしょうか?問題を引き起こすいくつかのバグがあります。


CPUIDあなたのコードでこれを行う、まだRCX RBX、RAXの内容を破壊し、RDXと:

cpuid 
mov [ rdx ], eax 

RDXが破壊されていますmov [ rdx ], eaxが実行されると、ポインタがにレンダリングされます。RDX invアリッド。 CPUID命令を使用する前に、RDXを別のレジスタに移動する必要があります。

RAX、RCX、RDX、R8、R9、R10、R11は、揮発性とみなされ、レジスタである必要があります:Windows 64-bit Calling Conventionこれらは呼び出し側によって保存する必要がある揮発性レジスタですパー

関数呼び出しで破壊されたとみなされます(プログラム全体の最適化などの分析によって安全性が証明されない限り)。

これらは呼び出し先によって保存する必要が不揮発性のものです:

ザ・はRBX、RBP、RDI、RSI、RSP、R12、R13、R14、およびR15を登録します不揮発性とみなされ、それらを使用する機能によって保存および復元する必要があります。

我々はRDX一時記憶するためのR10(揮発性レジスタ)を使用することができます。コードでRSIを使用する代わりに、pEdxの値を更新するためにR10を再利用することができます。 RSIを使用しない場合は、保存する必要はありません。 CPUIDは破壊されません。RBXおよびRBXは不揮発性なので、保存する必要があります。 RAXは揮発性であるため、保存する必要はありません。あなたのコードで


あなたは、この行があります。

mov [ rsi ], rdx 

RSIEDXに値を保存するために、呼び出し側が提供するメモリアドレス(pEdx)です。あなたが持っているコードは、8バイトレジスタRDXの内容を、4バイトのDWORDが必要なメモリ位置に移動します。これにより、発信者のデータが破棄される可能性があります。これは本当にされている必要があります:

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コンパイラ組み込み関数を使用すると、アセンブラルーチンは不要です。 –

関連する問題