レガシーガジェット研究所

気になったことのあれこれ。

インライン・アセンブリに関して

概要

Linux Kernelのソースを読むのに必要だったため簡単にまとめた。参考資料にはサンプルなどが豊富に用意されている。

書式

asm volatile(
    AssemblerTemplate
    : OutputOperands
    : InputOperands
    : Clobbers)

*asmvolatileが変数名や関数名と被る際は__asm____volatile__もキーワードとして使用できる。

e.g.

#define switch_to(prev,next,last) do {                    \
   unsigned long esi,edi;                        \
   asm volatile("pushfl\n\t"                    \
            "pushl %%ebp\n\t"                 \
            "movl %%esp,%0\n\t"   /* save ESP */      \
            "movl %5,%%esp\n\t"   /* restore ESP */   \
            "movl $1f,%1\n\t"      /* save EIP */      \
            "pushl %6\n\t"     /* restore EIP */   \
            "jmp __switch_to\n"                \
            "1:\t"                     \
            "popl %%ebp\n\t"                  \
            "popfl"                     \
            :"=m" (prev->thread.esp),"=m" (prev->thread.eip),  \
             "=a" (last),"=S" (esi),"=D" (edi)            \
            :"m" (next->thread.esp),"m" (next->thread.eip),    \
             "2" (prev), "d" (next));                \
} while (0)

#define local_irq_restore(x)   do { 
    typecheck(unsigned long,x); 
    __asm__ __volatile__(
        "pushl %0 ; popfl"
        : /* no output */ 
        :"g" (x)
        :"memory", "cc"); 
    } 
while (0)

AssemblerTemplate内でレジスタを指定する場合は%%eaxというように%を2つプレフィックスとしてレジスタ名に付加する。

制御文字

レジスタオペランド制約

OutputOperandsまたはInputOperandsの箇所に指定する。

文字 意味
a %eax
b %ebx
c %ecx
d %edx
S %esi
D %edi
r eax,ebx,ecx,edx,esi,ediのいずれか
q eax,ebx,ecx,edxのいずれか
A eaxとedxを合わせて64bitで使う。元々は64bitの値を返す時に、edxに上位32bitを、eaxに下位32bitを指定するのに使われた制約である。
g メモリ・即値オペランドを許容する、任意の汎用レジスタ
f 浮動小数レジスタのいずれか
t 第一浮動小数レジスタ
u 第二浮動小数レジスタ

メモリ・オペランド制約

OutputOperandsまたはInputOperandsの箇所に指定する。

文字 対応
m メモリ
o

マッチング(ディジット)制約

OutputOperandsまたはInputOperandsの箇所に指定する。

文字 対応
0 %0
1 %1
2 %2
: :
n %n

制約修飾子

OutputOperandsの制約に付与する。

文字 説明
無し 読み込み専用オペラント
= 書き込み専用オペランド
+ 読み込み・書き込みオペランド
& 早期破壊オペラント(基本的には=と組み合わせて使用される)

値の変更を行う対象の指定(Clobbers)

文字 説明
レジスタ e.g. "%eax"や"%ebx"のようにレジスタ名を指定
cc 命令によってステータスレジスタが更新される場合に指定
memory 入出力に指定していないメモリ領域に変更が加わる場合に指定

その他の制約

文字 説明
I 0 ~ 31の定数
J 0 ~ 63の定数
K 0xff
L 0xffff
M 0 ~ 3
N 0 ~ 255

参考