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

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

Embed Size (px)

Citation preview

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

Modulo VI

Escrevendo código em Linguagem de Montagem

(Assembly)

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

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

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

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{<cond>}{S} <Rd>, <operador_de_deslocamento>

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

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{<cond>}{S} <Rd>, <operador_de_deslocamento>

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

Formato Típico das Instruções Assembly

cmp R0, R1ble L1mov R2, R0b L2

L1:mov R2, R1

L2:

if (a > b) c = a;else c = b;

Em C Em Assembly

cmp R0, R1movgt R2, R0movle R2, R1

ouConsidere que R0, R1 e R2 estão carregados com os valores de a, b e c, respectivamente

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

Formato do operador_de_deslocamento

#<immediate> - Valor pode receber somente certos valores

<Rm> - Conteúdo de Rm

<Rm>, LSL #<shift_imm> - Conteúdo de Rm deslocado logicamente à esquerda por um valor imediato, exemplo: R2, LSL #5

<Rm>,LSL <Rs> - Conteúdo de Rm é deslocado logicamente à esquerda por um valor contido em Rs

MOV{<cond>}{S} <Rd>, <operador_de_deslocamento>

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

Formato do operador_de_deslocamento

<Rm>, LSR #<shift_imm> - Conteúdo de Rm é deslocado logicamente à direita por um valor imediato

<Rm>, LSR <Rs> - Conteúdo de Rm é deslocado logicamente à direita por um valor contido em Rs

<Rm>, ASR #<shift_imm> - Conteúdo de Rm é deslocado para direita aritmeticamente por um valor imediato, com ou sem sinal

<Rm>, ASR <Rs> - Conteúdo de Rm é deslocado aritmeticamente à direita por um valor contido em Rs, com ou sem sinal

MOV{<cond>}{S} <Rd>, <operador_de_deslocamento>

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

Formato do operador_de_deslocamento

<Rm>, ROR #<shift_imm> - Conteúdo de Rm é rotacionado à direita por um valor imediato

<Rm>, ROR <Rs> - Conteúdo de Rm é rotacionado à direita por uma quantidade Rs

<Rm>, 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{<cond>}{S} <Rd>, <operador_de_deslocamento>

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

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 bits Imediato 8 bits

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

Formato do operador_de_deslocamento

#<immediate>

mov R0, #127 ;R0 = 127add R0, R1, #0x7f ;R0 = R1 + 127mov R2, #125952 ;R2 = 125952 = 123*4*4*4*4*4ldr R2, =125951 ;R2 = 125951 = 123*4*4*4*4*4 - 1

mov R0, #257 ;erro!add R0, R1, #0x101 ;erro!mov R2, #125951 ;125951 = 123*4*4*4*4*4-1 erro!

LDR R2, =125951 é uma instrução que é desdobrada pelo montador em um carregamento (LDR) de uma

posição de memória com o valor 125951

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

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{<cond>} <Rd>, <modo_de_endereçamento>

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

Formato do modo_de_endereçamento

[<Rn>,#+/-<offset_12>] – O endereço é o conteúdo de Rn mais ou menos o offset_12 de 12 bits com sinal

[<Rn>,+/-<Rm>] – Endereço é o conteúdo de Rm mais ou menos o conteúdo de Rm

[<Rn>,+/-<Rm>, <shift> <shift_imm>] – O endereço é o conteúdo de Rn mais ou menos conteúdo de Rm deslocado por um operador <shift> pelo número de bits em <shift_imm>

[<Rn>,#+/-<offset_12>]! – 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{<cond>} <Rd>, <modo_de_endereçamento>

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

Formato do modo_de_endereçamento

[<Rn>, +/- <Rm>]! – 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)

[<Rn>, +/-<Rm>, <shift> <shift_imm>]! – O endereço é o conteúdo de Rn mais ou menos o conteúdo de Rm deslocado por um operador <shift> pelo número de bits em <shift_imm>, o endereço é escrito de volta para Rn (pré-indexado)

[<Rn>], #+/-<offset_12> - 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{<cond>} <Rd>, <modo_de_endereçamento>

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

Formato do modo_de_endereçamento

[<Rn>] +/-<Rm> - O endereço é o conteúdo de Rn, Rm é adicionado ou subtraído de Rn, escrito de volta para Rn (pós-indexado)

[<Rn>] +/-<Rm>, <shift> <shift_imm> - O endereço é o conteúdo de Rn, conteúdo de Rm é deslocado operador <shift> pelo número de bits em <shift_imm> o valor é adicionado ou subtraído de Rn (pós-indexado)

LDR{<cond>} <Rd>, <modo_de_endereçamento>

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

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

ldr R1, [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], #4str R3, [R2, #4]!str R4, [R5, #4]

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

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

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

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, ...

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

Registradores Pode ser desejável dar nomes mais sugestivos aos registradores,

para isso usa-se a diretiva RN

contador RN R0

resultado RN R1

Pode ser desejável também colocar nomes as constantes literais (valores imediatos)

mascara EQU 0x000000ff

minimoEQU 0

maximo EQU 32767

Usando:

mov contador, #minimo

cmp contador, #maximo

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

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

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

Assembly: Estrutura do Arquivo;cpenable.asm

AREA CPENABLE, CODE, READONLY;CP15 Routines

EXPORT GetCP0Enable

; Retorna valor escrito em r0GetCP0Enable PROC

MRC p15, 0x0, r0, c15, c1, 0x0mov pc,lrENDPEND

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

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

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

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

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

stmdb sp, {r4,r5}ldr r4, [sp]ldr r5, [sp, #4]

; o código vai aquildmdb sp, {r4,r5}mov pc,lrENDPEND

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

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

Retornando da Função em Assembly;count.asm

AREA PARMS, CODE, READONLY;Routines

EXPORT Count Count PROC

stmdb sp, {r4,r5}mov r4, #0mov r5, #0xF8

loopadd r4,r4,#1cmp r4,r5blt loop

mov r0,r4ldmdb sp, {r4,r5}mov pc,lrENDPEND

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

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

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)soma2 PROC

add R0, R0, R1 ;R0 = R0 + R1mov pc,lrENDPEND

Soma os dois parâmetros e retorna o resultado pela função

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

Retornando da Função em Assembly;soma6.asm

AREA SOMA, CODE, READONLY;Routinas

EXPORT soma6

;int soma6(int, int, int, int, int, int)soma6 PROC

stmdb SP, {R4,R5}add R0, R0, R1add R1, R2, R3add R0, R0, R1ldr R4, [SP]ldr R5, [SP, #4]add R1, R4, R5add R0, R0, R1ldmdb SP, {R4,R5}mov PC, LRENDPEND

Soma os seis parâmetros e

retorna o resultado pela função

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

Retornando da Função em Assembly;soma7.asm

AREA SOMA, CODE, READONLY;Routinas

EXPORT soma7

;int soma7(int, int, int, int, int, int, int *)soma7 PROC

add R0, R0, R1add R1, R2, R3add R0, R0, R1ldr R1, [SP]ldr R2, [SP, #4]add R1, R1, R2add R0, R0, R1ldr R1, [SP, #8]str R0, [R1]mov PC, LRENDPEND

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.

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

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, READONLYEXPORT soma7

;int soma7(int, int, int, int, short int, short int, short int *)soma7 PROC

stmdb SP, {R4, R5, R6}add R0, R0, R1add R1, R2, R3add R0, R0, R1ldrh R4, [SP]ldrh R5, [SP, #4]add R1, R4, R5add R0, R0, R1ldr R5, [SP, #8]strh R0, [R5]ldmdb SP, {R4, R5, R6}mov PC, LRENDPEND

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

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 vetorAREA VETOR, CODE, READONLYEXPORT procura

procura PROCmov R2, #0

lacoldr R3, [R0, R2, LSL #2] cmp R1, R3addeq R0, R0, R2moveq PC, LR ;return &v[i]add R2, #1cmp R2, #10movge R0, #0 ;return NULLmovge PC, LRb lacoENDPEND

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

Passando ponteiro por parâmetro em Assembly

typedef struct s_no { long dado; 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, READONLYEXPORT iniciaLista

iniciaLista PROCmov R1, #0str R1, [R0]mov PC, LRENDPEND

&lista, d R0

lista, *d [R0]

d R0

*d [R0]

? antes depois

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

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 DRECTVEDCB “-export:Count”

;count.asmAREA COUNT,CODE,READONLY

; RotinasEXPORT Count

Count PROCstmdb sp, {r4,r5}mov r4, #0mov r5, #0xF8

loopadd r4, r4,#1cmp r4, r5blt loopmov r0, r4ldmdb sp, {r4,r5}mov pc, lrENDPEND

Exportando uma função Assembly de uma DLL

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

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

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

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

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

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; ...

add r6, r7, r8

sub r5, r6, r9

ldrd r0, [r3]

orr r8, r1, #0xf

mul r7, r0, r7

ldrd r0, [r3]

add r6, r7, r8

sub r5, r6, r9

mul r7, r0, r7

orr r8, r1, #0xf

LDRD necessita de 3 ciclos para disponibilizar os dados nos registradores

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

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)

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

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

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

Indo além do básico em Assembly Estude o ARM ARM (ARM Architecture Reference

Manual), também disponível no formato pdf em www.arm.org

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

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

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

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

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

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

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

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

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

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

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)

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

Modulo VI

Técnicas de Otimização

Considerações sobre o código Compilado

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

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 Observe que o compilador realiza dois deslocamentos realiza dois deslocamentos

para estender o sinal do para estender o sinal do valor de ShortSum para valor de ShortSum para retornar o valor de Test. retornar o valor de Test.

Perda de tempo!Perda de tempo!

Diversos Diversos mov’s mov’s para truncar e para truncar e estender o sinal dos operandos estender o sinal dos operandos

e do resultadoe do resultado

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

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 Se necessário manter o mesmo range de o mesmo range de

short, use castshort, use cast

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

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 ; 00000028

mov r3, r0

ldr r0, [sp, #8]

add r0, r0, r3

str r0, [sp, #8]

; indx += DitherIndex(indx);

bl DitherIndex ; 0000003C

mov r3, r0

ldr r0, [sp, #8]

add r0, r0, r3

Já que usamos o Já que usamos o endereço de indx, o endereço de indx, o

compilador é compilador é conservador em mantê-lo conservador em mantê-lo

em um registrador, em um registrador, causando vários acessos causando vários acessos

à memóriaà memória

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

Aperfeiçoando o Códigoint 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 ; 00000028

add r4, r4, r0

; indx += DitherIndex(indx);

mov r0, r4

bl DitherIndex ; 00000034

add r0, r0, r4

Observe que a variável Observe que a variável indxindx é mantida agora em é mantida agora em r4, sem exigir repetidos r4, sem exigir repetidos STR/LDR para [sp, #0]STR/LDR para [sp, #0]

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

Módulo VI

Laboratório