かなり前のことですが、今後の参考のためにこれが必要になる可能性があります...
クリスの素晴らしい答えに追加すると、キーは「%」と出力オペランドの数の間の修飾子を使用しています。たとえば、 に"MOV %1, %0"
なる場合があり"MOV %q1, %w0"
ます。
Constraints.md には何も見つかりませんでしたが、/gcc/config/i386/i386.cprint_reg()
のソースに次の潜在的に役立つコメントがありました。
/* Print the name of register X to FILE based on its machine mode and number.
If CODE is 'w', pretend the mode is HImode.
If CODE is 'b', pretend the mode is QImode.
If CODE is 'k', pretend the mode is SImode.
If CODE is 'q', pretend the mode is DImode.
If CODE is 'x', pretend the mode is V4SFmode.
If CODE is 't', pretend the mode is V8SFmode.
If CODE is 'h', pretend the reg is the 'high' byte register.
If CODE is 'y', print "st(0)" instead of "st", if the reg is stack op.
If CODE is 'd', duplicate the operand for AVX instruction.
*/
例を提供するための以下のコメントix86_print_operand()
:
b -- 指定されたオペランドのレジスターの QImode 名を出力します。
operands[0] が reg 0 の場合、%b0 は %al を出力します。
GCC InternalsドキュメントのOutput Templateの下に、さらにいくつかの便利なオプションがリストされています。
'%cdigit' は、通常即値オペランドを示す構文を使用せずに、定数値であるオペランドを置換するために使用できます。
'%ndigit' は '%cdigit' に似ていますが、印刷前に定数の値が否定される点が異なります。
'%adigit' を使用すると、実際のオペランドがアドレスとして扱われ、メモリ参照であるかのようにオペランドを置き換えることができます。これは、「ロード アドレス」命令を出力する場合に便利です。このような命令のアセンブラ構文では、メモリ参照であるかのようにオペランドを記述する必要があることが多いためです。
'%ldigit' は、label_ref をジャンプ命令に置き換えるために使用されます。
'%=' は、コンパイル全体で各命令に固有の番号を出力します。これは、複数のアセンブラ命令を生成する単一のテンプレートでローカル ラベルを複数回参照する場合に便利です。
' %c2
' コンストラクトを使用すると、オフセットを使用して LEA 命令を適切にフォーマットできます。
#define ASM_LEA_ADD_BYTES(ptr, bytes) \
__asm volatile("lea %c1(%0), %0" : \
/* reads/writes %0 */ "+r" (ptr) : \
/* reads */ "i" (bytes));
「 」内の重要だがまばらに文書化されている「c」に注意してください%c1
。このマクロは、
ptr = (char *)ptr + bytes
ただし、通常の整数演算実行ポートは使用しません。
編集して追加:
x64 で直接呼び出しを行うのは、文書化されていない別の修飾子 ' %P0
' (PIC 用のようです) が必要なため、難しい場合があります。
#define ASM_CALL_FUNC(func) \
__asm volatile("call %P0") : \
/* no writes */ : \
/* reads %0 */ "i" (func))
大文字の「P」のみが ICC で認識されますが、小文字の「p」修飾子も GCC で同じように機能するようです。詳細はおそらく/gcc/config/i386/i386.cにあります。"'p'" を検索します。