Improve this page Github へのログインが必要です。 簡単な修正は、ここから fork、オンライン編集、pull request ができます。 大きな修正については、 通常の clone で行って下さい。 Page wiki 関連するWikiページを参照・編集 English このページの英語版(原文)

インラインアセンブラ

Some Assembly Required

D はシステムプログラミングのできる言語ですから、 インラインアセンブラを備えています。同一のCPUファミリ上では、 Dのインラインアセンブラは標準化されています。例えば、Win32版の D Compiler の Intel Pentium 向けインラインアセンブラは、 Linux版のIntel Pentium 向けのものと同じ構文が使用できます。

しかし、 異なるアーキテクチャでのDの実装の違いによって、 メモリモデルや関数呼び出し規約の違いが存在する可能性はあります。

このドキュメントでは、 インラインアセンブラのx86での実装について記述します。

AsmInstruction:
    Identifier : AsmInstruction
    align IntegerExpression
    even
    naked
    db Operands
    ds Operands
    di Operands
    dl Operands
    df Operands
    dd Operands
    de Operands
    Opcode
    Opcode Operands

Operands:
    Operand
    Operand , Operands

ラベル

他のDの文同様、 アセンブラの命令にもラベル付けできます。 goto文の飛び先とすることも可能です。例えば:

void *pc;
asm
{
  call L1          ;
 L1:               ;
  pop  EBX         ;
  mov  pc[EBP],EBX ; // pcはL1のコードを指すようになる
}

align IntegerExpression

IntegerExpression:
    IntegerLiteral
    Identifier

必要ならばアセンブラにNOP命令を出力させ、 次の命令をメモリの IntegerExpression 境界へ整列します。 IntegerExpression はコンパイル時に2の累乗へ評価される定数です。

ループ先頭を整列すると、 しばしば劇的に実行速度が改善されます。

even

必要ならばアセンブラにNOP命令を出力させ、 次の命令をメモリの偶数番地へ配置します。

naked

コンパイラに、関数のprolog,epilogコードを生成しないように指示します。 これはつまり、そのような処理はインラインアセンブラコードの書き手が 自分で全て書く責任を負うことを意味します。 関数全体をインラインアセンブラで書くときによく使われます。

db, ds, di, dl, df, dd, de

これらの疑似命令は、 生のデータを直接コードに埋め込むときに使います。 db で byte, ds で 16bit word, di で 32bit word, dl で 64bit word, df で 32bit float, dd で 64bit double, de で 80bit extended real を埋め込みます. それぞれ複数のオペランドを指定できます。 オペランドが文字列リテラルだった場合、 文字数個のオペランドが指定されたとみなします。 一文字一文字が一オペランドになります。例えば:
asm
{
  db 5,6,0x83;   // insert bytes 0x05, 0x06, and 0x83 into code
  ds 0x1234;     // insert bytes 0x34, 0x12
  di 0x1234;     // insert bytes 0x34, 0x12, 0x00, 0x00
  dl 0x1234;     // insert bytes 0x34, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  df 1.234;      // insert float 1.234
  dd 1.234;      // insert double 1.234
  de 1.234;      // insert real 1.234
  db "abc";      // insert bytes 0x61, 0x62, and 0x63
  ds "abc";      // insert bytes 0x61, 0x00, 0x62, 0x00, 0x63, 0x00
}

オペコード

対応しているオペコードの一覧はこの文書の末尾にあります。

以下のレジスタをサポートします。 レジスタ名は常に大文字を用います。

Register:
    AL AH AX EAX
    BL BH BX EBX
    CL CH CX ECX
    DL DH DX EDX
    BP EBP
    SP ESP
    DI EDI
    SI ESI
    ES CS SS DS GS FS
    CR0 CR2 CR3 CR4
    DR0 DR1 DR2 DR3 DR6 DR7
    TR3 TR4 TR5 TR6 TR7
    ST
    ST(0) ST(1) ST(2) ST(3) ST(4) ST(5) ST(6) ST(7)
    MM0 MM1 MM2 MM3 MM4 MM5 MM6 MM7
    XMM0 XMM1 XMM2 XMM3 XMM4 XMM5 XMM6 XMM7

特殊な場合

lock, rep, repe, repne, repnz, repz
これら接頭命令は、修飾する命令と同じ文には入れません。 これらの命令一つで一つの文になります。 例:
asm {
  rep   ;
  movsb ;
}
pause
アセンブラはこのオペコードをサポートしません。代わりに次のように:
asm {
  rep  ;
  nop  ;
}
書くと、同じ効果が得られます。
浮動小数点演算命令
命令形式として、2オペランド形を使います:
fdiv ST(1);	// 間違い
fmul ST;        // 間違い
fdiv ST,ST(1);	// 正しい
fmul ST,ST(0);	// 正しい

オペランド

Operand:
    AsmExp

AsmExp:
    AsmLogOrExp
    AsmLogOrExp ? AsmExp : AsmExp

AsmLogOrExp:
    AsmLogAndExp
    AsmLogAndExp || AsmLogAndExp

AsmLogAndExp:
    AsmOrExp
    AsmOrExp && AsmOrExp

AsmOrExp:
    AsmXorExp
    AsmXorExp | AsmXorExp

AsmXorExp:
    AsmAndExp
    AsmAndExp ^ AsmAndExp

AsmAndExp:
    AsmEqualExp
    AsmEqualExp & AsmEqualExp

AsmEqualExp:
    AsmRelExp
    AsmRelExp == AsmRelExp
    AsmRelExp != AsmRelExp

AsmRelExp:
    AsmShiftExp
    AsmShiftExp < AsmShiftExp
    AsmShiftExp <= AsmShiftExp
    AsmShiftExp > AsmShiftExp
    AsmShiftExp >= AsmShiftExp

AsmShiftExp:
    AsmAddExp
    AsmAddExp << AsmAddExp
    AsmAddExp >> AsmAddExp
    AsmAddExp >>> AsmAddExp

AsmAddExp:
    AsmMulExp
    AsmMulExp + AsmMulExp
    AsmMulExp - AsmMulExp

AsmMulExp:
    AsmBrExp
    AsmBrExp * AsmBrExp
    AsmBrExp / AsmBrExp
    AsmBrExp % AsmBrExp

AsmBrExp:
    AsmUnaExp
    AsmBrExp [ AsmExp ]

AsmUnaExp:
    AsmTypePrefix AsmExp
    offsetof AsmExp
    seg AsmExp
    + AsmUnaExp
    - AsmUnaExp
    ! AsmUnaExp
    ~ AsmUnaExp
    AsmPrimaryExp

AsmPrimaryExp:
    IntegerLiteral
    FloatLiteral
    __LOCAL_SIZE
    $
    Register
    DotIdentifier

DotIdentifier:
    Identifier
    Identifier . DotIdentifier

オペランドの構文は、 おおよそのところIntelのCPUドキュメントの規約に従っています。 特に、2オペランド命令では、 ソースが右オペランドでデスディネーションが 左オペランドです。Intelと違うのは、 D言語の字句解析器との互換性を重視し、 パーズを簡単にした部分です。

seg は、シンボルが存在するセグメントの番号を意味します。 これはフラットモデルのコードには無関係です。 代わりに、対応するセグメントレジスタから move します。

オペランド型

AsmTypePrefix:
    near ptr
    far ptr
    byte ptr
    short ptr
    int ptr
    word ptr
    dword ptr
    qword ptr
    float ptr
    double ptr
    real ptr

オペランドのサイズが曖昧な場合、例えば:

add	[EAX],3		;

iには、AsmTypePrefix を書いて曖昧性を解消します:

add  byte ptr [EAX],3 ;
add  int ptr [EAX],7  ;

far ptr はフラットモデルのコードには無関係です。

構造体/共用体/クラス メンバのオフセット

集成体へのポインタがレジスタにあってそのメンバへアクセスしたいときは、 メンバの修飾名を使います:

struct Foo { int a,b,c; }
int bar(Foo *f) {
  asm {
    mov EBX,f          ;
    mov EAX,Foo.b[EBX] ;
  }
}

スタック変数

スタック変数 (関数ローカルの変数で、スタックに割り当てられる) は、 EBP で添え字付けされた変数名でアクセスできます:

int foo(int x) {
  asm {
    mov EAX,x[EBP] ; // 引数xの値をEAXにロード
    mov EAX,x      ; // 同上
  }
}

[EBP] が省略された場合、ローカル変数への参照と仮定されます。 naked が使われていた場合はその限りではありません。

特殊シンボル

$
直後の命令の先頭のプログラムカウンタを表します。 従って
jmp  $  ;
はjmpの直後の命令へと分岐します。 $ は jmp か call 命令のターゲットとしてのみ 使用することができます。
__LOCAL_SIZE
このシンボルは、 ローカルのスタックフレームのバイト数で置き換えられます。naked を使ってスタックフレームを自分で操作するときに便利です。

対応しているオペコード

aaaaadaamaasadc
add addpd addps addsd addss
and andnpd andnps andpd andps
arpl bound bsf bsr bswap
bt btc btr bts call
cbw cdq clc cld clflush
cli clts cmc cmova cmovae
cmovb cmovbe cmovc cmove cmovg
cmovge cmovl cmovle cmovna cmovnae
cmovnb cmovnbe cmovnc cmovne cmovng
cmovnge cmovnl cmovnle cmovno cmovnp
cmovns cmovnz cmovo cmovp cmovpe
cmovpo cmovs cmovz cmp cmppd
cmpps cmps cmpsb cmpsd cmpss
cmpsw cmpxch8b cmpxchg comisd comiss
cpuid cvtdq2pd cvtdq2ps cvtpd2dq cvtpd2pi
cvtpd2ps cvtpi2pd cvtpi2ps cvtps2dq cvtps2pd
cvtps2pi cvtsd2si cvtsd2ss cvtsi2sd cvtsi2ss
cvtss2sd cvtss2si cvttpd2dq cvttpd2pi cvttps2dq
cvttps2pi cvttsd2si cvttss2si cwd cwde
da daa das db dd
de dec df di div
divpd divps divsd divss dl
dq ds dt dw emms
enter f2xm1 fabs fadd faddp
fbld fbstp fchs fclex fcmovb
fcmovbe fcmove fcmovnb fcmovnbe fcmovne
fcmovnu fcmovu fcom fcomi fcomip
fcomp fcompp fcos fdecstp fdisi
fdiv fdivp fdivr fdivrp feni
ffree fiadd ficom ficomp fidiv
fidivr fild fimul fincstp finit
fist fistp fisub fisubr fld
fld1 fldcw fldenv fldl2e fldl2t
fldlg2 fldln2 fldpi fldz fmul
fmulp fnclex fndisi fneni fninit
fnop fnsave fnstcw fnstenv fnstsw
fpatan fprem fprem1 fptan frndint
frstor fsave fscale fsetpm fsin
fsincos fsqrt fst fstcw fstenv
fstp fstsw fsub fsubp fsubr
fsubrp ftst fucom fucomi fucomip
fucomp fucompp fwait fxam fxch
fxrstor fxsave fxtract fyl2x fyl2xp1
hlt idiv imul in inc
ins insb insd insw int
into invd invlpg iret iretd
ja jae jb jbe jc
jcxz je jecxz jg jge
jl jle jmp jna jnae
jnb jnbe jnc jne jng
jnge jnl jnle jno jnp
jns jnz jo jp jpe
jpo js jz lahf lar
ldmxcsr lds lea leave les
lfence lfs lgdt lgs lidt
lldt lmsw lock lods lodsb
lodsd lodsw loop loope loopne
loopnz loopz lsl lss ltr
maskmovdqu maskmovq maxpd maxps maxsd
maxss mfence minpd minps minsd
minss mov movapd movaps movd
movdq2q movdqa movdqu movhlps movhpd
movhps movlhps movlpd movlps movmskpd
movmskps movntdq movnti movntpd movntps
movntq movq movq2dq movs movsb
movsd movss movsw movsx movupd
movups movzx mul mulpd mulps
mulsd mulss neg nop not
or orpd orps out outs
outsb outsd outsw packssdw packsswb
packuswb paddb paddd paddq paddsb
paddsw paddusb paddusw paddw pand
pandn pavgb pavgw pcmpeqb pcmpeqd
pcmpeqw pcmpgtb pcmpgtd pcmpgtw pextrw
pinsrw pmaddwd pmaxsw pmaxub pminsw
pminub pmovmskb pmulhuw pmulhw pmullw
pmuludq pop popa popad popf
popfd por prefetchnta prefetcht0 prefetcht1
prefetcht2 psadbw pshufd pshufhw pshuflw
pshufw pslld pslldq psllq psllw
psrad psraw psrld psrldq psrlq
psrlw psubb psubd psubq psubsb
psubsw psubusb psubusw psubw punpckhbw
punpckhdq punpckhqdq punpckhwd punpcklbw punpckldq
punpcklqdq punpcklwd push pusha pushad
pushf pushfd pxor rcl rcpps
rcpss rcr rdmsr rdpmc rdtsc
rep repe repne repnz repz
ret retf rol ror rsm
rsqrtps rsqrtss sahf sal sar
sbb scas scasb scasd scasw
seta setae setb setbe setc
sete setg setge setl setle
setna setnae setnb setnbe setnc
setne setng setnge setnl setnle
setno setnp setns setnz seto
setp setpe setpo sets setz
sfence sgdt shl shld shr
shrd shufpd shufps sidt sldt
smsw sqrtpd sqrtps sqrtsd sqrtss
stc std sti stmxcsr stos
stosb stosd stosw str sub
subpd subps subsd subss sysenter
sysexit test ucomisd ucomiss ud2
unpckhpd unpckhps unpcklpd unpcklps verr
verw wait wbinvd wrmsr xadd
xchg xlat xlatb xor xorpd
xorps

対応している Pentium 4 (Prescott) オペコード

addsubpd addsubps fisttp haddpd haddps
hsubpd hsubps lddqu monitor movddup
movshdup movsldup mwait

対応しているAMDのオペコード

pavgusb pf2id pfacc pfadd pfcmpeq
pfcmpge pfcmpgt pfmax pfmin pfmul
pfnacc pfpnacc pfrcp pfrcpit1 pfrcpit2
pfrsqit1 pfrsqrt pfsub pfsubr pi2fd
pmulhrw pswapd