1

Intel Debug Registersを試してみましたが、何かが間違っているようです。非常に単純なLinuxLKMを作成し、インラインアセンブリを使用してレジスターの簡単な操作を実行しようとしました。例えば:

 __asm__ ("movl %eax, %db0");

私が受け取るエラーメッセージは、私が根本的に間違ったことをしていることを示唆しています。例えば:

Error: unsupported for `mov'

誰かがこれらのレジスタを操作する方法について何か洞察を持っていますか?

4

2 に答える 2

5

これは構文エラーです。gcc のインライン アセンブラーは%オペランド識別子として使用し、x86 のレジスタ名で明示的に使用するには、次のように記述する必要があります。

__asm__ ("movl %%eax, %%db0\n\t");

これでコンパイルが通ります。

訂正:
ここには複数の問題があります:

  1. __asm__clobbers のないステートメントは非常に珍しいものです (そして、副作用のないアセンブリで実行できることはほとんどないため、期待どおりに動作することはめったにありません)。それにもかかわらず、命令が実際に副作用がなく、入力がない場合にのみ、クロバーリストを省略できるようです。
    その結果の 1 つは、エスケープ%が不要になったことです。この単純な例のコンパイラは__asm__("movl %eax, %db0\n\t");、完全に指定された の場合と同じオペコードを作成します__asm__("movl %%eax, %%db0\n\t":::);。ただし、これは必ずしも利点ではありません。
  2. 2 番目の問題は移植性です。x86_64 と i386 は似ていますが同一ではありません。違いの 1 つは、デバッグ レジスタのレジスタ幅です。これだけでも、レジスタ名を直接使用する代わりにインライン アセンブリ オペランドを実際に使用する特に適切な理由があります。これは、次のコード
    __asm__("mov %0, %%db0\n\t" : : "a"((uintptr_t)0) : );
    が 64 ビット ( gcc -m64 ...) と 32 ビット( ) の両方でコンパイルされるためです。同じgcc -m32 ...命令が作成されますが、これをアセンブリで記述するときにレジスタが使用されます。 64 ビットでは異なります: 32 ビットでは異なります: ここで入力オペランドを使用すると、レジスタ幅を抽象化する機能が提供されます(
    208: 0f 23 c0 mov %rax,%db0

    269: 0f 23 c0 mov %eax,%db0
    uintptr_t<inttypes.h>常に完全な汎用レジスタ幅であることが保証されているため、同じインライン アセンブリを 32 ビット コンパイルと 64 ビット コンパイルに使用できます。

私は、コンパイラが clobber-list-less__asm__を「通常の」そのようなステートメントとは異なる方法で扱うとは知らなかったと認めます。

いずれにせよ、実際には、デバッグ レジスタを変更するときは、引数/クロバー リストmemory必ず必要になります。これは、これらへのアクセスは、暗黙的にコンパイラーにクロバーとして認識させる必要があるシリアル化命令であるためです。その上、それらから読み込んでいる/それらに書き込んでいる値は、どこかに行く/どこから来る必要があります...したがって、入力/出力。

于 2012-08-03T20:54:45.250 に答える