インライン・アセンブリに関して
概要
Linux Kernelのソースを読むのに必要だったため簡単にまとめた。参考資料にはサンプルなどが豊富に用意されている。
書式
asm volatile( AssemblerTemplate : OutputOperands : InputOperands : Clobbers)
*asm
やvolatile
が変数名や関数名と被る際は__asm__
や__volatile__
もキーワードとして使用できる。
- volatilea: コンパイラの最適化を抑止
- AssemblerTemplate: アセンブラコード
- OutputOperands: 出力オペランド
- InputOperands: 入力オペランド
- Clobbers: 値の変更を行う対象
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 |