A apresentação está carregando. Por favor, espere

A apresentação está carregando. Por favor, espere

Modulo VI Escrevendo código em Linguagem de Montagem (Assembly)

Apresentações semelhantes


Apresentação em tema: "Modulo VI Escrevendo código em Linguagem de Montagem (Assembly)"— Transcrição da apresentação:

1 Modulo VI Escrevendo código em Linguagem de Montagem (Assembly)

2 Conjunto de Instruções  Arquitetura RISC  Reduced Instruction Set Computer  Operação com dados se dão nos registradores, nunca na memória  Instruções de carga (Load) de dados da memória em registradores  Instruções de armazenagem (Store) de dados de registradores para a memória

3 Formato Típico das Instruções Assembly  Itens entre { } são opcionais  Itens entre são uma breve descrição sobre um tipo de valor que será passado pelo programador  Muitas instruções podem ser executadas condicionalmente  Isso pode evitar os desvios (branch). Desvios podem prejudicar o desempenho de arquiteturas com muitos níveis no pipeline MOV{ }{S},

4 Formato Típico das Instruções Assembly  Muitas instruções podem alterar ou não os bits de estados dependendo da forma da instrução  Facilita a comparação de dados (pos, neg, zero..)  Operações aritméticas em dados não relacionados podem ocorrer durante uma pendência, sem alterar os bits de estados  O último operando é um operador de deslocamento, outros são registradores. MOV{ }{S},

5 Formato Típico das Instruções Assembly cmpR0, R1 bleL1 mov R2, R0 b L2 L1: mov R2, R1 L2: if (a > b) c = a; else c = b; Em C Em Assembly cmp R0, R1 movgt R2, R0 movle R2, R1 ou Considere que R0, R1 e R2 estão carregados com os valores de a, b e c, respectivamente

6 Formato do operador_de_deslocamento  # - Valor pode receber somente certos valores  - Conteúdo de Rm , LSL # - Conteúdo de Rm deslocado logicamente à esquerda por um valor imediato, exemplo: R2, LSL #5 ,LSL - Conteúdo de Rm é deslocado logicamente à esquerda por um valor contido em Rs MOV{ }{S},

7 Formato do operador_de_deslocamento , LSR # - Conteúdo de Rm é deslocado logicamente à direita por um valor imediato , LSR - Conteúdo de Rm é deslocado logicamente à direita por um valor contido em Rs , ASR # - Conteúdo de Rm é deslocado para direita aritmeticamente por um valor imediato, com ou sem sinal , ASR - Conteúdo de Rm é deslocado aritmeticamente à direita por um valor contido em Rs, com ou sem sinal MOV{ }{S},

8 Formato do operador_de_deslocamento , ROR # - Conteúdo de Rm é rotacionado à direita por um valor imediato , ROR - Conteúdo de Rm é rotacionado à direita por uma quantidade Rs , RRX – Conteúdo de Rm é deslocado um bit à direita, o bit de Carry é deslocado para alto e o bit 0 de Rm é colocado no bit de carry As operações de deslocamento não mudam o conteúdo de Rm, apenas o valor do resultado usado como o operando MOV{ }{S},

9 Operador de deslocamento: Formas do imediato  Pode rotacionar à direita um valor imediato de 8 bits por qualquer número par de bits  O campo de rotação tem seu valor multiplicado por dois, dessas forma é possível deslocar até 30 bits  Apenas valores especiais de constantes podem ser representados  0xFF (possível)  0xFF0 (possível)  0xFF1 (Não)  0x1FE (Não)  Pode ser necessário formar constantes em mais de uma etapa, por exemplo: 0xFFFF  Evite, se for possível, criar espaços para dados constantes ROR 4 bitsImediato 8 bits

10 Formato do operador_de_deslocamento # movR0, #127;R0 = 127 addR0, R1, #0x7f;R0 = R movR2, #125952;R2 = = 123*4*4*4*4*4 ldrR2, =125951;R2 = = 123*4*4*4*4*4 - 1 movR0, #257;erro! addR0, R1, #0x101;erro! movR2, #125951; = 123*4*4*4*4*4-1 erro! LDR R2, = é uma instrução que é desdobrada pelo montador em um carregamento (LDR) de uma posição de memória com o valor

11 Formato típico de uma instrução LDR/STR  LDR - Usado para carregar um valor da memória para um registrador  STR - Usado para armazenar o valor em um registrador na memória  Pode ser executado condicionalmente  Não altera os bits de estados CSPR (Current Status Program Register)  Usa modo_de_endereçamento para endereçar o dado na memória LDR{ },

12 Formato do modo_de_endereçamento  [,#+/- ] – O endereço é o conteúdo de Rn mais ou menos o offset_12 de 12 bits com sinal  [,+/- ] – Endereço é o conteúdo de Rm mais ou menos o conteúdo de Rm  [,+/-, ] – O endereço é o conteúdo de Rn mais ou menos conteúdo de Rm deslocado por um operador pelo número de bits em  [,#+/- ]! – O endereço é o conteúdo de Rn mais ou menos um offset_12 de 12 bits com sinal, endereço é escrito de volta para Rn (pré-indexado) LDR{ },

13 Formato do modo_de_endereçamento  [, +/- ]! – O endereço é o conteúdo de Rn mais ou menos o conteúdo de Rm, endereço é escrito de volta para Rn (pré-indexado)  [, +/-, ]! – O endereço é o conteúdo de Rn mais ou menos o conteúdo de Rm deslocado por um operador pelo número de bits em, o endereço é escrito de volta para Rn (pré-indexado)  [ ], #+/- - O endereço é o conteúdo de Rn, o valor offset_12 de 12 bits com sinal é adicionado a Rn, escrito de volta para Rn (pós-indexado) LDR{ },

14 Formato do modo_de_endereçamento  [ ] +/- - O endereço é o conteúdo de Rn, Rm é adicionado ou subtraído de Rn, escrito de volta para Rn (pós-indexado)  [ ] +/-, - O endereço é o conteúdo de Rn, conteúdo de Rm é deslocado operador pelo número de bits em o valor é adicionado ou subtraído de Rn (pós- indexado) LDR{ },

15 Formato do modo_de_endereçamento ;Coloca o valor apontado por R0 em R1 e incrementa R0 para ;indicar o próximo inteiro de 32 bits ldrR1, [R0], #4 ;Incrementa o conteúdo de R2 fazendo-o apontar para o próximo ;inteiro de 32 bits, esse inteiro é atribuído para R3 ldr R3, [R2, #4]! ;O endereço é o valor R5 deslocado 4 bytes, o resultado aponta ;para o próximo inteiro de 32 bits, esse inteiro é atribuído para R4. ;R5 não é alterado ldr R4, [R5, #4] ;O mesmo endereçamento pode ser usado pela instrução STR str R1, [R0], #4 str R3, [R2, #4]! str R4, [R5, #4]

16 Instruções Dignas de Atenção  BIC – Bit Clear  desliga os bits indicados na mascara  CLZ – Count Leading Zeros  ideal para determinar o número de bits necessários para representar um número  LDM/STM – Load/Store Multiple  usado para salvar e recuperar registradores na pilha  especialmente útil: STMDB, LDMDB  RSB – Reverse Substract Operand Order  permitem que o operador_de_deslocamento seja subtraídos do registrador

17 Registradores  R0 até R3 – Propósito geral, salvos pelo chamador da rotina  R4 até R11 – Propósito geral, salvos pela rotina chamada  R12 – Frame Pointer (algumas vezes)  R13 – Stack Pointer (SP – Apontador da Pilha)  R14 – Link Register (LR)  R15 – Program Counter (PC)  CSPR – Currente Status Program Register, contém a sinalização de overflow, zero, underflow,...

18 Registradores  Pode ser desejável dar nomes mais sugestivos aos registradores, para isso usa-se a diretiva RN contador RNR0 resultadoRNR1  Pode ser desejável também colocar nomes as constantes literais (valores imediatos) mascaraEQU0x000000ff minimoEQU0 maximoEQU32767  Usando: movcontador, #minimo cmpcontador, #maximo

19 Convenção da Pilha  A Pilha cresce “para baixo”  Dados colocados na pilha têm endereços de memória menores que os dados colocados previamente  O armazenamento dos dados na pilha é pré-decrementado.  Ponteiro da pilha aponta para o último elemento colocado nela. SP + 16 SP + 12 SP + 8 SP + 4 SP Crescimento da pilha Topo

20 Assembly: Estrutura do Arquivo ;cpenable.asm AREA CPENABLE, CODE, READONLY ;CP15 Routines EXPORT GetCP0Enable ; Retorna valor escrito em r0 GetCP0Enable PROC MRC p15, 0x0, r0, c15, c1, 0x0 mov pc,lr ENDP END Comentários se iniciam com ; Informações sobre a área que será usada EXPORT é usado para exportar o nome da função para uso externo Rótulos começam na coluna 1, PROC é uma diretiva usada para identificar funções END indica onde o arquivo acaba ENDP mostra onde a função acaba

21 Chamando um Módulo em Assembly  Por convenção no C para o ARM os quatro primeiros parâmetros são passados nos registradores R0 – R3  O restante é passado na pilha, da esquerda para a direita, sendo que o parâmetro mais à esquerda está no topo da pilha  O registrador Stack Pointer aponta para o 5º parâmetro se ele estiver presente  Ajustes são necessários se a função não for uma função folha  Para funções folha, podemos usar o stack pointer tanto para pilha quanto para frame pointer  Para funções não folha o stack pointer será ajustado, ou usa-se R12 como frame pointer ou ajusta-se as referências das variáveis colocadas na pilha pelo chamador

22 Exemplo da Manipulação de Parâmetros em uma função Asm ; parms.asm AREA PARMS, CODE, READONLY ;Routines EXPORT Parms ;Parms (a,b,c,d,e,f) Parms PROC stmdbsp, {r4,r5} ldrr4, [sp] ldr r5, [sp, #4] ; o código vai aqui ldmdb sp, {r4,r5} mov pc,lr ENDP END Parâmetros de a-d estão em R0-R3, respectivamente O parâmetro e é o mais baixo na pilha, o ponteiro da pilha stack pointer aponta para ele. Agora, ele está em R4. Parâmetro f é o próximo na pilha, assim, stack pointer+4 é atribuido para R5 Salva os registradores R4 e R5 na pilha

23 Retornando da Função em Assembly ;count.asm AREA PARMS, CODE, READONLY ;Routines EXPORT Count Count PROC stmdb sp, {r4,r5} mov r4, #0 mov r5, #0xF8 loop add r4,r4,#1 cmp r4,r5 blt loop mov r0,r4 ldmdb sp, {r4,r5} mov pc,lr ENDP END Valores de retorno da função são passados em R0 Restaura os valores de R4 e R5, ajuste o stack pointer se necessário Restaura o PC com o conteúdo do Link Register. Lembre-se de salvar o conteúdo de LR se esta função não for uma função folha

24 Exemplo da Manipulação de Parâmetros em uma função Asm ;soma2.asm AREA SOMA, CODE, READONLY ;Routinas EXPORT soma2 ; int soma2(int, int) soma2PROC addR0, R0, R1;R0 = R0 + R1 mov pc,lr ENDP END Soma os dois parâmetros e retorna o resultado pela função

25 Retornando da Função em Assembly ;soma6.asm AREA SOMA, CODE, READONLY ;Routinas EXPORT soma6 ;int soma6(int, int, int, int, int, int) soma6PROC stmdb SP, {R4,R5} addR0, R0, R1 addR1, R2, R3 addR0, R0, R1 ldr R4, [SP] ldr R5, [SP, #4] addR1, R4, R5 addR0, R0, R1 ldmdb SP, {R4,R5} mov PC, LR ENDP END Soma os seis parâmetros e retorna o resultado pela função

26 Retornando da Função em Assembly ;soma7.asm AREA SOMA, CODE, READONLY ;Routinas EXPORT soma7 ;int soma7(int, int, int, int, int, int, int * ) soma7PROC addR0, R0, R1 addR1, R2, R3 addR0, R0, R1 ldr R1, [SP] ldr R2, [SP, #4] addR1, R1, R2 addR0, R0, R1 ldr R1, [SP, #8] strR0, [R1] mov PC, LR ENDP END Soma os seis parâmetros e retorna o resultado no sétimo parâmetro Observe que os registradores R4 e R5 não estão mais sendo usados.

27 Retornando da Função em Assembly Soma os seis parâmetros e retorna o resultado no sétimo parâmetro Observe que os três últimos parâmetros têm 16 bits cada AREA SOMA, CODE, READONLY EXPORT soma7 ;int soma7(int, int, int, int, short int, short int, short int * ) soma7PROC stmdb SP, {R4, R5, R6} addR0, R0, R1 addR1, R2, R3 addR0, R0, R1 ldr h R4, [SP] ldr h R5, [SP, #4] addR1, R4, R5 addR0, R0, R1 ldr R5, [SP, #8] str h R0, [R5] ldmdb SP, {R4, R5, R6} mov PC, LR ENDP END

28 Passando vetor por parâmetro em Assembly int vet[10]; int p*; int * procura(int v[ ], int x) { int i; for (i=0; i<10; i++) if (v[i]==x) return &v[i]; return NULL; } void main(void) {. p=procura(vet, 1234);. } Retorna o endereço de um elemento em um vetor AREA VETOR, CODE, READONLY EXPORT procura procura PROC movR2, #0 laco ldrR3, [R0, R2, LSL #2] cmpR1, R3 addeqR0, R0, R2 moveq PC, LR;return &v[i] addR2, #1 cmpR2, #10 movgeR0, #0;return NULL movgePC, LR blaco ENDP END

29 Passando ponteiro por parâmetro em Assembly typedefstruct s_no { longdado; struct s_no*prox; } no; no *lista; void iniciaLista(no**d) { *d=NULL; } void main(void) {. iniciaLista(&lista). } Iniciação de uma lista linear simplesmente encadeada AREA LISTA, CODE, READONLY EXPORT iniciaLista iniciaListaPROC movR1, #0 strR1, [R0] mov PC, LR ENDP END &lista, d R0 lista, *d [R0] d R0 *d [R0] ? antes depois

30 DCB é usado para definir uma string na qual contém diretivas para o ligador ajustar o código como sendo uma exportação.dll A diretiva deve estar na área DRECTVE em uma seção chamada.drectve AREA.drectve DRECTVE DCB “-export:Count” ;count.asm AREA COUNT,CODE,READONLY ; Rotinas EXPORT Count Count PROC stmdb sp, {r4,r5} mov r4, #0 mov r5, #0xF8 loop add r4, r4,#1 cmp r4, r5 blt loop mov r0, r4 ldmdb sp, {r4,r5} movpc, lr ENDP END Exportando uma função Assembly de uma DLL

31 Usando Assembly na IDE  Clique na pasta Source files, adicione um arquivo.asm no projeto  Selecione ‘All Files’ na caixa de diálogo, assim você pode ver os arquivos.asm  Clique com o botão direito no arquivo ASM na pasta source do projeto, vá para settings  Na aba Custom Build  Digite armasm para chamar o montador  Utilize a opção xscale cpu se estiver chamando mnemônicos xscale (armasm –cpu xscale)  Use o caminho relativo ao arquivo como o apresentado no arquivo de entrada (input File)  Use apenas o nome do arquivo com a extensão.obj como saída

32 Melhorando as Dependências Usando LDR ldr r0, [r5] add r1, r2, r3 sub r8, r2, r3 add r6, r0, r1 mul r9, r2, r3 add r1, r2, r3 ldr r0, [r5] add r6, r0, r1 sub r8, r2, r3 mul r9, r2, r3 Com o dado na Cache, três ciclos são necessários para a transferência do valor ao registrador Como o dado pode não estar na cache, o LDR deve ser colocado o mais cedo possível antes do ponto de utilização

33 Instruções LDRD/STRD  Lê e armazena 64 bits em dois registradores  O Endereço deve estar alinhado em 8 bytes (64bits)  Os registradores devem ser os pares:  R0,R1; R2,R3; R4,R5;... addr6,r7,r8 subr5,r6,r9 ldrdr0,[r3] orrr8,r1,#0xf mulr7,r0,r7 ldrdr0,[r3] addr6,r7,r8 subr5,r6,r9 mulr7,r0,r7 orrr8,r1,#0xf LDRD necessita de 3 ciclos para disponibilizar os dados nos registradores

34 Instruções LDM/STM  2 a 20 ciclos para disponibilizar os valores nos registradores,  depende do número de registradores envolvidos na troca de dados  A latência é de 2 ciclos mais 1 ciclo por registrador envolvido  A próxima instrução é atrasada um ciclo (com ou sem dependências e acessos à memória)

35 Utilizando LDM ou LDRD ldm r0, {r2, r3} ldm r1, {r4, r5} adds r0, r2, r4 adc r1, r3, r5 ldrd r2, [r0] ldrd r4, [r1] adds r0, r2, r4 adc r1, r3, r5  Soma de dois valores de 64 bits  r0 endereço do primeiro valor  r1 endereço do segundo valor Mais rápido para executar

36 Indo além do básico em Assembly  Estude o ARM ARM (ARM Architecture Reference Manual), também disponível no formato pdf em  Estude o help do EVC++, tópico ARM Assembly  Compile seu código com a opção de disassembly ativada e veja o que o compilador gera:  Misture código C com assembly  Desligue as otimizações do compilador

37 Indo além do básico em Assembly: Use o eVC++ Vá em Project Settings-> C/C++ tab -> Selecione Listing Files Coloque List Assembly with Source

38 Quando e onde substituir o código por Assembly  Apenas em regiões do código críticas no desempenho  Para tirar maior proveito do pipeline do processador Intel® XScale™  O número de variáveis envolvidas for grande  O compilador é incapaz de fazer um bom uso de muitos registradores  O compilador está armazenando valores locais em memória  Quando esses valores poderiam ser mantidos nos registradores  Há instruções muito melhores em Assembly para:  Melhor acesso a overflow  Melhor acesso a instruções DSP

39 Quando for escrever o código em Assembly  Utilize muitos comentários  Inclua o código em C, que o Assembly estiver substituindo, como comentário  Use as diretivas RN e EQU para dar nomes esclarecedores aos registradores e aos valores imediatos  Sempre salve e recupere os conteúdos dos Registradores usados pela função que faz a chamada se você os usa  Cuidado ao trabalhar com funções que não são do tipo folha  Salve o conteúdo de LR  Observe as alterações em SP

40 Quando for escrever o código em Assembly  Tome cuidado com o alinhamento de dados  Para ler dados do tipo short em um vetor use as instruções LDRH ou LDRSH  Use STRH para escrever dados do tipo short em um vetor  Assim como com os tipos short, tenha certeza de estar usando LDRB para vetores de bytes  Desconsiderar essas instruções para dados do tipo short ou byte pode causar problemas de alinhamento de dados Erros de alinhamento em geral causam o travamento da máquina, deixando-o sem pistas do que pode ter dado errado com o seu programa

41 Otimizando Código em Assembly  Não armazena dados de volta a pilha  Mantenha as variáveis em registradores o máximo de tempo possível  Observe a tabela de latências  Ordene as instruções tendo em mente o tempo de latência de cada uma delas  Tente desenrolar o laço  Tente usar PreLoad também em Assembly (Instrução PLD)  Lembre-se que algumas instruções aritméticas levam mais de 1 ciclo de clock  Não deixe de tirar proveito das instruções de execução condicional  Repita pequenos pedaços de código se isso conseguir evitar desvios (branches)

42 Modulo VI Técnicas de Otimização Considerações sobre o código Compilado

43 Evite o uso desnecessário de Shorts int Test(void) { short x, y; x = 3; y = 4; return ShortSum(x, y); } short ShortSum(short a, short b) { return a+b; } ; depois de retornar de ShortSum mov r1,r0,lsl #16 mov r0,r1,#asr #16 mov pc,lr ENDP ShortSum PROC ; start mov r0,r0,lsl #16 mov r2,r0,asr #16 mov r1,r1,lsl #16 add r0,r2,r1,asr #16 mov r2,r0,lsl #16 mov r0,r2,asr #16 mov pc,lr ; return ENDP Observe que o compilador realiza dois deslocamentos para estender o sinal do valor de ShortSum para retornar o valor de Test. Perda de tempo! Diversos mov’s para truncar e estender o sinal dos operandos e do resultado

44 Corrija as suas variáveis shorts int Test(void) { int x,y; x = 3; y = 4; return (short)ShortSum(x, y); } int ShortSum(int a, int b) { return a+b; } ;Depois de retornar de ShotSum mov r1,r0,lsl #16 mov r0,r1,#asr #16 mov pc,lr ENDP ShortSum PROC ; start add r0,r0,r1 mov pc,lr ; return ENDP Se necessário manter o mesmo range de short, use cast

45 Evite o Apelidamento de Variáveis [Aliasing of Variables] int AliasTaken(int indx) { TransIndex(&indx); indx += 5; indx += DisplaceIndex(indx); indx += DitherIndex(indx); return indx; } ; TransIndex(&indx) add r0, sp,#8 bl TransIndex ; indx += 5; ldr r3, [sp, #8] add r0, r3, #5 str r0, [sp, #8] ;indx += DisplaceIndex(indx); bl DisplaceIndex ; mov r3, r0 ldr r0, [sp, #8] add r0, r0, r3 str r0, [sp, #8] ; indx += DitherIndex(indx); bl DitherIndex ; C mov r3, r0 ldr r0, [sp, #8] add r0, r0, r3 Já que usamos o endereço de indx, o compilador é conservador em mantê-lo em um registrador, causando vários acessos à memória

46 Aperfeiçoando o Código int AliasTaken(int indx) { inf ref = indx; TransIndex(&ref); indx += 5; indx += DisplaceIndex(indx); indx += DitherIndex(indx); return indx; } ; ref = indx; mov r4, r0 ; TransIndex(&ref); add r0, sp, #0 str r4, [sp] bl TransIndex ; indx += 5; add r4, r4, #5 ; indx += DisplaceIndex(indx); mov r0, r4 bl DisplaceIndex ; add r4, r4, r0 ; indx += DitherIndex(indx); mov r0, r4 bl DitherIndex ; add r0, r0, r4 Observe que a variável indx é mantida agora em r4, sem exigir repetidos STR/LDR para [sp, #0]

47 Módulo VI Laboratório


Carregar ppt "Modulo VI Escrevendo código em Linguagem de Montagem (Assembly)"

Apresentações semelhantes


Anúncios Google