1

良い一日。数日間解決できない問題に直面しました。この関数をC言語でコンパイルしようとすると、エラーが表示されます。

void GetInInterrupt(UChar Interrupt)
{
    //asm volatile(".intel_syntax noprefix");
    asm volatile
    (
        "movb %0, %%al\n"
        "movb %%al, 1(point)\n"
        "point:\n"
        "int $0\n"
        : /*output*/ : "r" (Interrupt) /*input*/ : /*clobbered*/
    );
    //asm volatile(".att_syntax noprefix");
}

私がガスから受け取るメッセージは次のとおりです。

Error: junk '(point)' after expression

2行目のポインタが間違っていることは理解できますが、残念ながら自分で解決することはできません。


助けてくれてありがとう。

4

2 に答える 2

2

以下に、コード内の場所に書き込む方法を示します。そもそもコードが記述可能であると想定していますが、これは通常、主流のOSには当てはまりません。これは、いくつかの厄介なバグを隠すためです。

void GetInInterrupt(UChar Interrupt)
{
    //asm volatile(".intel_syntax noprefix");
    asm volatile
    (
        "movb %0, point+1\n"
        "point:\n"
        "int $0\n"
        : /*output*/ : "r" (Interrupt) /*input*/ : /*clobbered */
    );
    //asm volatile(".att_syntax noprefix");
}

また、2つのレジスタを使用せず、代わりにすでに存在するレジスタを使用するようにコードを簡略化しました。コンパイラがそれについてうめき声を上げた場合は、代わりにそれをInterrupt見つけるか、問題を解決することができます。"a""r"

于 2013-02-23T21:26:49.753 に答える
2

C ++を使用できる場合は、次のようにします。

template <int N> static inline void GetInInterrupt (void)
{
    __asm__ ("int %0\n" : "N"(N));
}

しましょう。そのテンプレートを次のように使用する場合:

GetInInterrupt<123>();
GetInInterrupt<3>();
GetInInterrupt<23>();
GetInInterrupt<0>();

これにより、次のオブジェクトコードが作成されます。

   0:   cd 7b                   int    $0x7b
   2:   cc                      int3
   3:   cd 17                   int    $0x17
   5:   cd 00                   int    $0x0

これはかなり最適です(int3ブレークポイントopである場合でも)。また、オペランドが0..255範囲外の場合、Nそれのみを許可する制約があるため、コンパイル時の警告が作成されます。

編集:もちろん、昔ながらのCスタイルのマクロも同様に機能します。

#define GetInInterrupt(arg) __asm__("int %0\n" : : "N"((arg)) : "cc", "memory")

C++テンプレート関数と同じコードを作成します。動作の仕方により、インラインアセンブリを埋め込むときに命令を並べ替えようとしないように、int(制約を介して)コンパイラにバリアセマンティクスについて通知することをお勧めします。"cc", "memory"

両方の制限は、明らかに、割り込み番号がコンパイル時定数でなければならないという事実です。どうしてもそれを望まない場合は、switch()たとえば、255のケースすべてをカバーすることで作成されたステートメントを作成するBOOST_PP_REPEAT()ことは、自己変更コードよりも優れたオプションです。

#include <boost/preprocessor/repetition/repeat.html>

#define GET_INTO_INT(a, INT, d) case INT: GetInInterrupt<INT>(); break;

void GetInInterrupt(int interruptNumber)
{
    switch(interruptNumber) {
    BOOST_PP_REPEAT(256, GET_INTO_INT, 0)
    default:
        runtime_error("interrupt Number %d out of range", interruptNumber);
    }
}

これはプレーンCで実行できます(もちろん、プレーンのテンプレート関数呼び出しを変更した場合__asm__)-ブーストプリプロセッサライブラリはC++コンパイラに依存しないため...そしてgcc4.7.2はこのために次のコードを作成します:


GetInInterrupt:
.LFB0:
        cmpl    $255, %edi
        jbe     .L262
        movl    %edi, %esi
        xorl    %eax, %eax
        movl    $.LC0, %edi
        jmp     runtime_error
        .p2align 4,,10
        .p2align 3
.L262:
        movl    %edi, %edi
        jmp     *.L259(,%rdi,8)
        .section        .rodata
        .align 8
        .align 4
.L259:
        .quad   .L3
        .quad   .L4
[ ... ]
        .quad   .L258
        .text
.L257:
#APP
# 17 "tccc.c" 1
        int $254

# 0 "" 2
#NO_APP
        ret
[ ... accordingly for the other vectors ... ]

ただし、上記を実行する場合は注意してください...コンパイラ(4.8までのgcc)は、アウェイを最適化するのに十分なインテリジェントではありません。つまり、インラインとしてではなく、の完全なジャンプテーブルバージョンを作成するswitch()と言ってもより単純な実装になります。static __inline__ ...GetInInterrupt(3)int3

于 2013-02-25T17:48:32.327 に答える