D
Linguagem
Phobos
Comparações

· Léxico
· Módulos
· Declarações
· Tipos
· Propriedades
· Atributos
· Pragmas
· Expressões
· Instruções
· Arrays
· Estruturas & Uniões
· Classes
· Interfaces
· Enums
· Funções
· Sobrecarda de Operadores
· Gabaritos
· Mixins
· Contratos
· Compilação Condicional
· Controlando Erros
· Coleta de Lixo
· Gerênciamento de Memória
· Ponto Flutuante
· Inline Assembler
· Comentários de Documentação
· Conectando com C
· Guia de Portabilidade
· Embutindo D em HTML
· Entidades de Caractéres Nomeadas
· Interface de Aplicação Binária

D x86 Inline Assembler

D, sendo uma linguagem de programação de sistemas, provê um inline assembler. O inline assembler é padronizado para implementações de D para a mesma família de CPU, por exemplo, o inline assembler para Intel Pentium para um compilador D para Win32 será de sintaxe compatível com o inline assembler para Linux executando em um Intel Pentium.

Implementações de D divergentes, porém, são livres para inovar no modelo de memória, convenções de chamada/retorno de função, converções de passagem de argumentos, etc.

Esse documento descreve a implementação x86 do inline assembler.

InstruçãoAsm:
Identificador : InstruçãoAsm
align ExpressãoInteiro
even
naked
db Operandos
ds Operandos
di Operandos
dl Operandos
df Operandos
dd Operandos
de Operandos
Opcode
Opcode Operandos
Operandos
Operando
Operando , Operandos

Marcadores

Instruções Assembler podem ser marcadas como outras instruções. Elas podem ser o alvo de instruções goto. Por exemplo:
void* pc;
asm
{
call L1 ;
L1: ;
pop EBX ;
mov pc[EBP],EBX ; // pc agora aponta para código em L1
}

align ExpressãoInteiro

Faz o assembler emitir instruções NOP para alinhar a próxima instrução assembler em um limite ExpressãoInteiro. ExpressãoInteiro deve ser um inteiro que é potência de 2.

Alinhar o começo do corpo de um laço pode às vezes ter um efeito dramático na velocidade de execução.

even

Faz o assembler emitir instruções NOP para alinhar a próxima instrução assembler em um mesmo limite.

naked

Faz o compilador não gerar as seqüências de função prolog e epilog sequences. Isso significa é a responsabilidade do programador inline assembly, e é normalmente usado quando toda a função será escrita em assembler.

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

Esses pseudo ops são para inserir dados crus diretamente no código. db é para bytes, ds é para palavras de 16 bits, di é para palavras de 32 bits, dl é para palavras de 64 bits, df é para floats de 32 bits, dd é para doubles de 64 bits, e de é para reais extendidos de 80 bits. Todos podem ter multiplos operandos. Se um operando é uma string literal, é como se houvessem operandos length, onde length é o número de caracteres na string. Um caracter é usado por operando. Por exemplo:
asm
{
db 5,6,0x83; // insere bytes 0x05, 0x06, and 0x83 no código
ds 0x1234; // insere bytes 0x34, 0x12
di 0x1234; // insere bytes 0x34, 0x12, 0x00, 0x00
dl 0x1234; // insere bytes 0x34, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
df 1.234; // insere float 1.234
dd 1.234; // insere double 1.234
de 1.234; // insere real 1.234
db "abc"; // insere bytes 0x61, 0x62, and 0x63
ds "abc"; // insere bytes 0x61, 0x00, 0x62, 0x00, 0x63, 0x00
}

Opcodes

Uma lista dos opcodes suportados está no fim.

Os seguintes registradores são suportados. Nomes de registradores são sempre em letras maiúsculas.

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

Casos Especiais

lock, rep, repe, repne, repnz, repz
Essas instruções prefixos não aparecem na mesma instrução que as instruções que eles préfixam; elas aparecem em suas próprias instruções. Por exemplo:
asm
{
rep ;
movsb ;
}
pause
Esse opcode não é suportado pelo assembler, use em seu lugar
{
rep ;
nop ;
}
que produz o mesmo resultado.
ops de ponto flutuante
Use a forma de dois operandos do formato da instrução;
fdiv ST(1); // errado
fmul ST; // errado
fdiv ST,ST(1); // certo
fmul ST,ST(0); // certo

Operandos

Operando:
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
offset AsmExp
seg AsmExp
+ AsmUnaExp
- AsmUnaExp
! AsmUnaExp
~ AsmUnaExp
AsmPrimaryExp
AsmPrimaryExp
IntegerConstant
FloatConstant
__LOCAL_SIZE
$
Registrador
PontoIdentificador
PontoIdentificador
Identificador
Identificador . PontoIdentificador
A sintaxe de operando segue mais ou menos as convenções de documentação de CPU Intel. Em particular, a convenção é que para instruções de dois operandos a fonte é o operando da direita e o destino é o operando da esquerda. A sintaxe difere disso de Intel para ser compatível com o tokenizer (algo como marcador/sinalizador) da linguagem D e para simplificar a análise.

Tipos de Operandos

PrefixoTipoAsm:
near ptr
far ptr
byte ptr
short ptr
int ptr
word ptr
dword ptr
float ptr
double ptr
real ptr
Em casos em que o tamanho do aperando é ambíguo, como em:
add [EAX],3 ;
ele pode ser identificado usando um PrefixoTipoAsm:
add byte ptr [EAX],3 ;
add int ptr [EAX],7 ;

Offsets de Membros de Estrutura/União/Classe

Para acessar membros de um agregado, dado um ponteiro para o agregado está em um registrador, use o nome qualificado do membro:
struct Foo { int a, b, c; }
int bar(Foo *f)
{
asm
{ mov EBX,f ;
mov EAX,Foo.b[EBX] ;
}
}

Símbolos Especiais

$$
Representa o contador do programa do começo da próxima instrução. Então,
jmp $ ;
ramifica para a instrução seguindo a instrução jmp.

__LOCAL_SIZE
Isso é substituído pelo número de bytes locais no quadro de pilha local. Isso é mais útil quando o naked é invocado e um quadro de pilha customizado é programado.

Opcodes Suportados

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 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) Opcodes Suportados

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

AMD Opcodes Suportados

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