D x86 인라인 어셈블러

D x86 인라인 어셈블러

시스템 프로그래밍 언어인 D는 인라인 어셈블러(inline assembler)를 제공해요. 인라인 어셈블러는 같은 CPU 계열을 쓰는 D 구현끼리 표준화되어 있어요. 예를 들어 Win32용 D 컴파일러의 Intel Pentium 인라인 어셈블러는, Intel Pentium이 돌아가는 Linux에서 쓰는 인라인 어셈블러와 문법이 호환된다고 보면 돼요.

다만 아키텍처가 서로 다른 D 구현은 메모리 모델, 함수 호출/복귀 규약, 인자 전달 규약 같은 부분을 자유롭게 설계할 수 있어요.

이 문서는 인라인 어셈블러의 x86 구현과 x86_64 구현을 다루어요. 컴파일러가 제공하는 인라인 어셈블러 플랫폼 지원 여부는 각각 D_InlineAsm_X86D_InlineAsm_X86_64 버전 식별자로 드러나요.

출처: https://dlang.org/spec/iasm.html

본문

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],EBXL1이 있는 코드 주소를 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 명령어 바로 다음 명령어로 분기해요. $jmpcall 명령어의 목적지로만 쓸 수 있어요.

__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

더 알아보기 (Learn more)