D x86 인라인 어셈블러
D x86 인라인 어셈블러
시스템 프로그래밍 언어인 D는 인라인 어셈블러(inline assembler)를 제공해요. 인라인 어셈블러는 같은 CPU 계열을 쓰는 D 구현끼리 표준화되어 있어요. 예를 들어 Win32용 D 컴파일러의 Intel Pentium 인라인 어셈블러는, Intel Pentium이 돌아가는 Linux에서 쓰는 인라인 어셈블러와 문법이 호환된다고 보면 돼요.
다만 아키텍처가 서로 다른 D 구현은 메모리 모델, 함수 호출/복귀 규약, 인자 전달 규약 같은 부분을 자유롭게 설계할 수 있어요.
이 문서는 인라인 어셈블러의 x86 구현과 x86_64 구현을 다루어요. 컴파일러가 제공하는 인라인 어셈블러 플랫폼 지원 여부는 각각 D_InlineAsm_X86과 D_InlineAsm_X86_64 버전 식별자로 드러나요.
본문
asm 문 (Asm statement)
어셈블러 명령어는 반드시 asm 블록 안에 있어야 해요. 함수처럼 asm 문도 호출하는 쪽과 호환되도록 적절한 함수 속성(function attribute)을 붙여 줘야 하는데, asm 문의 속성은 추론되지 않으니 명시적으로 적어야 해요.
AsmStatement:
asm FunctionAttributesopt { AsmInstructionListopt }
AsmInstructionList:
AsmInstruction ;
AsmInstruction ; AsmInstructionList
@safe는 속성으로 쓸 수 없어요. 컴파일러는 어셈블리 문에 대해 안전성 검사를 하지 않으니까요. 그 자리에는 @trusted를 쓰면 돼요.
아래 예제를 볼게요. ok 함수는 asm 문에 pure, nothrow, @trusted, @nogc를 명시해서 잘 동작해요. 반면 error 함수처럼 asm 문에 속성을 따로 붙이면 시스템 수준으로 간주돼 에러가 나거나, @safe를 붙이면 폐기(deprecation) 경고가 나와요.
void ok() pure nothrow @safe @nogc
{
asm pure nothrow @trusted @nogc
{}
}
void error() @safe @nogc
{
asm @nogc // Error: asm statement is assumed to be @system - mark it with '@trusted' if it is not
{}
asm @safe @nogc // Deprecation: asm statement cannot be @safe, use @trusted instead
{}
}
asm 명령어 (Asm instruction)
AsmInstruction:
Identifier : AsmInstruction
align IntegerExpression
even
naked
db Operands
ds Operands
di Operands
dl Operands
df Operands
dd Operands
de Operands
db StringLiteral
ds StringLiteral
di StringLiteral
dl StringLiteral
dw StringLiteral
dq StringLiteral
Opcode
Opcode Operands
Opcode:
Identifier
int
in
out
Operands:
Operand
Operand , Operands
레이블 (Labels)
어셈블러 명령어도 다른 문장처럼 레이블을 달 수 있어요. 그리고 레이블은 goto 문의 목적지가 될 수 있어요. 예를 들어 아래처럼 쓰죠.
void *pc;
asm
{
call L1 ;
L1: ;
pop EBX ;
mov pc[EBP],EBX ; // pc now points to code at L1
}
여기서 L1: 레이블을 call의 목적지로 쓰고, 나중에 mov pc[EBP],EBX로 L1이 있는 코드 주소를 pc에 저장해요.
align IntegerExpression
IntegerExpression:
IntegerLiteral
Identifier
align은 다음 어셈블러 명령어가 IntegerExpression 경계에 맞춰지도록 어셈블러가 NOP 명령어를 넣게 해요. IntegerExpression은 컴파일 타임에 2의 거듭제곱인 정수로 평가되어야 해요.
루프 본문의 시작을 정렬하면 실행 속도에 때로 극적인 영향을 주곤 해요.
even
even은 다음 어셈블러 명령어가 짝수 경계에 맞춰지도록 어셈블러가 NOP 명령어를 넣게 해요.
naked
naked는 컴파일러가 함수 프롤로그(prolog)와 에필로그(epilog) 시퀀스를 생성하지 않게 해요. 그러면 그 책임은 인라인 어셈블러 프로그래머 몫이 되는데, 함수 전체를 어셈블러로 작성할 때 주로 쓰여요.
db, ds, di, dl, df, dd, de
이 계열은 가상 연산(pseudo op)으로, 코드에 원시 데이터를 바로 끼워 넣어요. 용도가 각각 달라요.
db는 바이트(byte)ds는 16비트 워드di는 32비트 워드dl은 64비트 워드df는 32비트 부동소수점(float)dd는 64비트 배정밀도(double)de는 80비트 확장 실수(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
}
오퍼코드 (Opcodes)
지원하는 오퍼코드 목록은 문서 끝부분에 있어요.
지원되는 레지스터는 다음과 같아요. 레지스터 이름은 항상 대문자예요.
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
x86_64에서는 여기에 레지스터가 더 추가돼요.
Register64:
RAX
RBX
RCX
RDX
BPL
RBP
SPL
RSP
DIL
RDI
SIL
RSI
R8B
R8W
R8D
R8
R9B
R9W
R9D
R9
R10B
R10W
R10D
R10
R11B
R11W
R11D
R11
R12B
R12W
R12D
R12
R13B
R13W
R13D
R13
R14B
R14W
R14D
R14
R15B
R15W
R15D
R15
XMM8
XMM9
XMM10
XMM11
XMM12
XMM13
XMM14
XMM15
YMM0
YMM1
YMM2
YMM3
YMM4
YMM5
YMM6
YMM7
YMM8
YMM9
YMM10
YMM11
YMM12
YMM13
YMM14
YMM15
특별한 경우 (Special Cases)
lock, rep, repe, repne, repnz, repz
이 접두(prefix) 명령어들은 접두할 대상 명령어와 같은 문에 나오지 않아요. 각자 따로 문을 만들어 써야 해요. 예를 들면 이렇게요.
asm
{
rep ;
movsb ;
}
pause
이 오퍼코드는 어셈블러가 지원하지 않아요. 대신 아래처럼 쓰면 같은 결과를 얻어요.
asm
{
rep ;
nop ;
}
floating point ops
부동소수점 연산은 두 오퍼랜드 형태를 써야 해요.
fdiv ST(1); // wrong
fmul ST; // wrong
fdiv ST,ST(1); // right
fmul ST,ST(0); // right
오퍼랜드 (Operands)
Operand:
AsmExp
AsmExp:
AsmLogOrExp
AsmLogOrExp ? AsmExp : AsmExp
AsmLogOrExp:
AsmLogAndExp
AsmLogOrExp || AsmLogAndExp
AsmLogAndExp:
AsmOrExp
AsmLogAndExp && AsmOrExp
AsmOrExp:
AsmXorExp
AsmOrExp | AsmXorExp
AsmXorExp:
AsmAndExp
AsmXorExp ^ AsmAndExp
AsmAndExp:
AsmEqualExp
AsmAndExp & AsmEqualExp
AsmEqualExp:
AsmRelExp
AsmEqualExp == AsmRelExp
AsmEqualExp != AsmRelExp
AsmRelExp:
AsmShiftExp
AsmRelExp < AsmShiftExp
AsmRelExp <= AsmShiftExp
AsmRelExp > AsmShiftExp
AsmRelExp >= AsmShiftExp
AsmShiftExp:
AsmAddExp
AsmShiftExp << AsmAddExp
AsmShiftExp >> AsmAddExp
AsmShiftExp >>> AsmAddExp
AsmAddExp:
AsmMulExp
AsmAddExp + AsmMulExp
AsmAddExp - AsmMulExp
AsmMulExp:
AsmBrExp
AsmMulExp * AsmBrExp
AsmMulExp / AsmBrExp
AsmMulExp % AsmBrExp
AsmBrExp:
AsmUnaExp
AsmBrExp [ AsmExp ]
AsmUnaExp:
AsmTypePrefix AsmExp
offsetof AsmExp
seg AsmExp
+ AsmUnaExp
- AsmUnaExp
! AsmUnaExp
~ AsmUnaExp
AsmPrimaryExp
AsmPrimaryExp:
IntegerLiteral
FloatLiteral
__LOCAL_SIZE
$
Register
Register : AsmExp
Register64
Register64 : AsmExp
DotIdentifier
this
DotIdentifier:
Identifier
Identifier . DotIdentifier
FundamentalType . Identifier
오퍼랜드 문법은 대체로 Intel CPU 문서의 관례를 따라가요. 특히 두 오퍼랜드를 쓰는 명령어에서 **오른쪽이 소스(source), 왼쪽이 목적지(destination)**라는 관례가 있어요. 다만 D 언어 토크나이저와 호환되고 파싱을 단순하게 만들기 위해 Intel 문법과는 살짝 달라요.
seg는 심볼이 들어 있는 세그먼트 번호를 읽어 오라는 뜻이에요. 플랫 모델(flat model) 코드에서는 이게 의미가 없으니, 대신 해당 세그먼트 레지스터에서 move를 하면 돼요.
점(.)으로 연결된 표현식은 컴파일 과정에서 평가되는데, 상수를 만들거나 대상 레지스터/변수에 들어맞는 더 높은 수준의 변수를 가리켜야 해요.
오퍼랜드 타입 (Operand Types)
AsmTypePrefix:
near ptr
far ptr
word ptr
dword ptr
qword ptr
FundamentalType ptr
오퍼랜드 크기가 애매한 경우가 있어요. 가령 아래처럼요.
add [EAX],3 ;
이럴 때는 AsmTypePrefix로 모호함을 풀 수 있어요.
add byte ptr [EAX],3 ;
add int ptr [EAX],7 ;
far ptr는 플랫 모델 코드에서는 의미가 없어요.
구조체/공용체/클래스 멤버 오프셋 (Struct/Union/Class Member Offsets)
레지스터에 애그리게이트(aggregate)를 가리키는 포인터가 들어 있을 때, 그 멤버에 접근하려면 멤버의 한정된 이름(qualified name)에서 .offsetof 프로퍼티를 쓰면 돼요.
struct Foo { int a,b,c; }
int bar(Foo *f)
{
asm
{
mov EBX,f ;
mov EAX,Foo.b.offsetof[EBX] ;
}
}
void main()
{
Foo f = Foo(0, 2, 0);
assert(bar(&f) == 2);
}
또는 애그리게이트 스코프 안이라면 멤버 이름만으로 충분해요.
struct Foo // or class
{
int a,b,c;
int bar()
{
asm
{
mov EBX, this ;
mov EAX, b[EBX] ;
}
}
}
void main()
{
Foo f = Foo(0, 2, 0);
assert(f.bar() == 2);
}
스택 변수 (Stack Variables)
스택 변수(함수에 지역이고 스택에 할당되는 변수)는 변수 이름을 EBP로 인덱싱해서 접근해요.
int foo(int x)
{
asm
{
mov EAX,x[EBP] ; // loads value of parameter x into EAX
mov EAX,x ; // does the same thing
}
}
[EBP]를 생략하면 지역 변수에 대해서는 자동으로 가정돼요. 다만 naked를 쓰면 이 가정이 더 이상 성립하지 않아요.
특별 기호 (Special Symbols)
$
$는 다음 명령어 시작 지점의 프로그램 카운터를 나타내요. 그래서 아래처럼요.
jmp $ ;
jmp $는 jmp 명령어 바로 다음 명령어로 분기해요. $는 jmp나 call 명령어의 목적지로만 쓸 수 있어요.
__LOCAL_SIZE
__LOCAL_SIZE는 로컬 스택 프레임의 로컬 바이트 수로 치환돼요. naked를 쓰면서 커스텀 스택 프레임을 직접 프로그래밍할 때 가장 유용해요.
지원되는 오퍼코드 (Opcodes Supported)
Opcodes
다음 오퍼코드가 지원돼요.
| aaa | aad | aam | aas | adc |
| 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 | cmpxchg | cmpxchg8b | cmpxchg16b |
| 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 |
| iretq | 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 |
| syscall | sysenter | sysexit | sysret | test |
| ucomisd | ucomiss | ud2 | unpckhpd | unpckhps |
| unpcklpd | unpcklps | verr | verw | wait |
| wbinvd | wrmsr | xadd | xchg | xlat |
| xlatb | xor | xorpd | xorps |
| ### Pentium 4 (Prescott) Opcodes Supported |
| Pentium 4 Opcodes |
| addsubpd | addsubps | fisttp | haddpd | haddps |
| hsubpd | hsubps | lddqu | monitor | movddup |
| movshdup | movsldup | mwait |
| ### AMD Opcodes Supported |
| AMD Opcodes |
| pavgusb | pf2id | pfacc | pfadd | pfcmpeq |
| pfcmpge | pfcmpgt | pfmax | pfmin | pfmul |
| pfnacc | pfpnacc | pfrcp | pfrcpit1 | pfrcpit2 |
| pfrsqit1 | pfrsqrt | pfsub | pfsubr | pi2fd |
| pmulhrw | pswapd |
| ### SIMD |
| SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2 and AVX are supported. |
| ## GCC syntax |
| The GNU D Compiler uses an alternative, GCC-based syntax for inline assembler: |
| d | | GccAsmStatement: | | asm FunctionAttributesopt { GccAsmInstructionList } | | GccAsmInstructionList: | | GccAsmInstruction ; | | GccAsmInstruction ; GccAsmInstructionList | | GccAsmInstruction: | | GccBasicAsmInstruction | | GccExtAsmInstruction | | GccGotoAsmInstruction | | GccBasicAsmInstruction: | | GccAsmStringExpression | | GccExtAsmInstruction: | | GccAsmStringExpression : GccAsmOperandsopt | | GccAsmStringExpression : GccAsmOperandsopt : GccAsmOperandsopt | | GccAsmStringExpression : GccAsmOperandsopt : GccAsmOperandsopt : GccAsmClobbersopt | | GccGotoAsmInstruction: | | GccAsmStringExpression : : GccAsmOperandsopt : GccAsmClobbersopt : GccAsmGotoLabelsopt | | GccAsmStringExpression: | | StringLiteral | | ( ConditionalExpression ) | | GccAsmOperands: | | GccSymbolicNameopt GccAsmStringExpression ( AssignExpression ) | | GccSymbolicNameopt GccAsmStringExpression ( AssignExpression ) , GccAsmOperands | | GccSymbolicName: | | [ Identifier ] | | GccAsmClobbers: | | GccAsmStringExpression | | GccAsmStringExpression , GccAsmClobbers | | GccAsmGotoLabels: | | Identifier | | Identifier , GccAsmGotoLabels | | |
Pentium 4 (Prescott) 지원 오퍼코드
Pentium 4 Opcodes
| addsubpd | addsubps | fisttp | haddpd | haddps |
| hsubpd | hsubps | lddqu | monitor | movddup |
| movshdup | movsldup | mwait |
| ### AMD Opcodes Supported |
| AMD Opcodes |
| pavgusb | pf2id | pfacc | pfadd | pfcmpeq |
| pfcmpge | pfcmpgt | pfmax | pfmin | pfmul |
| pfnacc | pfpnacc | pfrcp | pfrcpit1 | pfrcpit2 |
| pfrsqit1 | pfrsqrt | pfsub | pfsubr | pi2fd |
| pmulhrw | pswapd |
| ### SIMD |
| SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2 and AVX are supported. |
| ## GCC syntax |
| The GNU D Compiler uses an alternative, GCC-based syntax for inline assembler: |
| d | | GccAsmStatement: | | asm FunctionAttributesopt { GccAsmInstructionList } | | GccAsmInstructionList: | | GccAsmInstruction ; | | GccAsmInstruction ; GccAsmInstructionList | | GccAsmInstruction: | | GccBasicAsmInstruction | | GccExtAsmInstruction | | GccGotoAsmInstruction | | GccBasicAsmInstruction: | | GccAsmStringExpression | | GccExtAsmInstruction: | | GccAsmStringExpression : GccAsmOperandsopt | | GccAsmStringExpression : GccAsmOperandsopt : GccAsmOperandsopt | | GccAsmStringExpression : GccAsmOperandsopt : GccAsmOperandsopt : GccAsmClobbersopt | | GccGotoAsmInstruction: | | GccAsmStringExpression : : GccAsmOperandsopt : GccAsmClobbersopt : GccAsmGotoLabelsopt | | GccAsmStringExpression: | | StringLiteral | | ( ConditionalExpression ) | | GccAsmOperands: | | GccSymbolicNameopt GccAsmStringExpression ( AssignExpression ) | | GccSymbolicNameopt GccAsmStringExpression ( AssignExpression ) , GccAsmOperands | | GccSymbolicName: | | [ Identifier ] | | GccAsmClobbers: | | GccAsmStringExpression | | GccAsmStringExpression , GccAsmClobbers | | GccAsmGotoLabels: | | Identifier | | Identifier , GccAsmGotoLabels | | |
AMD 지원 오퍼코드
AMD Opcodes
| pavgusb | pf2id | pfacc | pfadd | pfcmpeq | | pfcmpge | pfcmpgt | pfmax | pfmin | pfmul | | pfnacc | pfpnacc | pfrcp | pfrcpit1 | pfrcpit2 | | pfrsqit1 | pfrsqrt | pfsub | pfsubr | pi2fd | | pmulhrw | pswapd |
SIMD
SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, 그리고 AVX가 지원돼요.
GCC 문법 (GCC syntax)
GNU D 컴파일러(GDC)는 인라인 어셈블러에 GCC 기반의 다른 문법을 사용해요.
GccAsmStatement:
asm FunctionAttributesopt { GccAsmInstructionList }
GccAsmInstructionList:
GccAsmInstruction ;
GccAsmInstruction ; GccAsmInstructionList
GccAsmInstruction:
GccBasicAsmInstruction
GccExtAsmInstruction
GccGotoAsmInstruction
GccBasicAsmInstruction:
GccAsmStringExpression
GccExtAsmInstruction:
GccAsmStringExpression : GccAsmOperandsopt
GccAsmStringExpression : GccAsmOperandsopt : GccAsmOperandsopt
GccAsmStringExpression : GccAsmOperandsopt : GccAsmOperandsopt : GccAsmClobbersopt
GccGotoAsmInstruction:
GccAsmStringExpression : : GccAsmOperandsopt : GccAsmClobbersopt : GccAsmGotoLabelsopt
GccAsmStringExpression:
StringLiteral
( ConditionalExpression )
GccAsmOperands:
GccSymbolicNameopt GccAsmStringExpression ( AssignExpression )
GccSymbolicNameopt GccAsmStringExpression ( AssignExpression ) , GccAsmOperands
GccSymbolicName:
[ Identifier ]
GccAsmClobbers:
GccAsmStringExpression
GccAsmStringExpression , GccAsmClobbers
GccAsmGotoLabels:
Identifier
Identifier , GccAsmGotoLabels