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çõ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:
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.