6

cpuid 命令を使用して Intel CPU の機能を識別したいと考えています。Kernel.framework で cpuid.h ヘッダーを見つけたので、Kernel.framework をプロジェクトに追加<Kernel/i386/cpuid.h>し、ソース ファイルに含めました。それが生み出した

kern/kern_types.h: No such file or directory

わかりません。しかし、do_cpuid私が使いたいと思う function はインラインで定義されているので、それをソースにコピーしてみました。

static inline void
do_cpuid(uint32_t selector, uint32_t *data)
{
    asm("cpuid"
        : "=a" (data[0]),
          "=b" (data[1]),
          "=c" (data[2]),
          "=d" (data[3])
        : "a"(selector));
}

それは私にエラーを与えました:

error: can't find a register in class 'BREG' while reloading 'asm'
error: 'asm' operand has impossible constraints

そのエラーをグーグルで検索すると、次の質問が表示されました:Mac の問題:「asm のリロード中にクラス BREG でレジスタが見つかりません」

しかし、その質問に対する解決策は、dynamic-no-pic オプション (GCC_DYNAMIC_NO_PICビルド設定) を使用することでした。ビルド設定に関する Xcode のヘルプには、「(位置に依存しない必要がある) 共有ライブラリには適していません」と記載されています。私はフレームワークを構築していますが、これは共有ライブラリとして数えられると思います。では、どうすればこれを機能させることができますか?

4

2 に答える 2

2

このやや不可解なエラー メッセージ:

error: can't find a register in class 'BREG' while reloading 'asm'
error: 'asm' operand has impossible constraints

制約の 1 つが許可されていないために発生しています。この場合は ですEBX-fPICオプション (位置独立コード)を使用して 32 ビット コードをコンパイルすると、EBXレジスタが再配置に使用されます。出力として使用することも、破壊されたレジスタとして表示することもできません。

ほとんどの人は特別なコンパイラ フラグを使用してコンパイルすることを提案していますが、レジスタ自体を保存して後で復元するようにアセンブラ コードを変更することで、 x86-64 / IA32およびPIC /非PIC をサポートするように関数を書き直すことができます。EBXこれは、次のようなコードで実行できます。

#include <inttypes.h>

static inline void
do_cpuid(uint32_t selector, uint32_t *data)
{
    __asm__ __volatile__ (
        "xchg %%ebx, %k[tempreg]\n\t"
        "cpuid\n\t"
        "xchg %%ebx, %k[tempreg]\n"
        : "=a" (data[0]),
          [tempreg]"=&r" (data[1]),
          "=c" (data[2]),
          "=d" (data[3])
        : "a"(selector),
          "c"(0));
}

重要な変更点はdata[1]、コンパイラが選択した利用可能なレジスタに値が返されることです。制約は、コンパイラが選択するどのレジスタも、他の入力レジスタのいずれにもならないことをコンパイラに伝えます(コード=&rでレジスタを早期に上書きしxchgます)。EBXコードでは、コンパイラが選択した利用可能なレジスタと交換します。その後、交換いたします。終了EBXすると、 には元の値が含まれ、選択されたフリー レジスタには によって返されたものが含まれCPUIDます。次に、アセンブラ テンプレートは、そのフリー レジスタの内容を に移動しdata[1]ます。

コンパイラが空きレジスタを選択できるようにすることで、問題を効果的に回避しました。EBXコンパイラは、再配置可能なコードに使用される可能性があるため、拘束されている場合は使用しないほどスマートです。64 ビット コードEBXでは、32 ビット コードのように再配置に使用されないため、使用できる可能性があります。

鋭い観察者は、に気づいたかもしれませんxor %%ecx,%%ecx。これは、この問題とは関係なく私が行った変更ですEBX。現在ECX、AMD 製の一部のプロセッサECXはゼロでない場合に古い値を返す可能性があるため、クリアすることをお勧めします。非 PPC Mac プラットフォームのみを対象として開発している場合、Apple はそのような動作を示さない Intel プロセッサを使用しているため、この変更は必要ありません。

一般EBXに、32 ビットの再配置可能/PIC コードでは特殊であるため、コンパイラーは最初にその不可解なメッセージで不平を言いました。

于 2015-09-13T03:18:11.503 に答える