• Nenhum resultado encontrado

Do alto-nível ao assembly

N/A
N/A
Protected

Academic year: 2021

Share "Do alto-nível ao assembly"

Copied!
25
0
0

Texto

(1)

Do alto-nível ao

assembly

Compiladores

(2)

Viagem

Como são implementadas as estruturas

computacionais em assembly?

Revisão dos conceitos relacionados com a

programação em assembly para o MIPS

R3000 (ver disciplina de Arquitectura de

Computadores)

(3)

Do alto-nível ao assembly

Alvo: MIPS R3000

int sum(int A[], int N) {

int i, sum = 0; for(i=0; i<N; i++) { sum = sum + A[i]; }

return sum; }

# $a0 armazena o endereço de A[0] # $a1 armazena o valor de N

Sum: addi $t0, $0, 0 # i = 0 addi $v0, $0, 0 # sum = 0

Loop: beq $t0, $a1, End # if(i == N) goto End; add $t1, $t0, $t0 # 2*i

add $t1, $t1, $t1 # 2*(2*i) = 4*i add $t1, $t1, $a0 # 4*i + base(A) lw $t2, 0($t1) # load A[i]

add $v0, $v0, $t2 # sum = sum + A[i] addi $t0, $t0, 1 # i++

j Loop # goto Loop;

(4)

Do alto-nível ao assembly

Variáveis globais:

Armazenadas na memória

Para cada uso de uma variável global

o compilador tem de gerar instruções

load/store

int a, b, c;

... fun(...) {

...

}

Memória

a

b

c

(5)

Variáveis Globais

int a, b, c;

void fun() {

c = a + b;

}

.data 0x10000000 a: .space 4 b: .space 4 c: .space 4 la $t1, a lw $t1, 0($t1) la $t2, b lw $t2, 0($t2) add $t3, $t2, $t1 la $t4, c sw $t3, 0($t4) … 0x10000008 0x10000004 0x10000000

Alocação

de

memória

Memória

a

b

c

(6)

Do alto-nível ao assembly

 Conceito de chamada a procedimentos

 Cada procedimento tem estados

• Variáveis locais

• Endereço de retorno

 Estado é guardado na área de memória designada por

pilha de chamadas (é utilizado um registo para apontar para a posição actual da pilha)

 Pilha de chamadas

 A pilha de chamadas encontra-se no topo da memória

 A pilha cresce para baixo

void fun() {

int a, b, c;

...

c = a + b;

...

}

Memória

c

b

a

Registos

$sp

(7)

Variáveis Locais

Exemplo:

void fun() {

int a, b, c;

...

c = a + b;

...

}

fun: addi $sp, $sp, -12 … lw $t1, 0($sp) lw $t2, 4($sp) add $t3, $t2, $t1 sw $t3, 8($sp) … addi $sp, $sp, 12 jr $ra

Memória

c

b

a

$sp

Reserva espaço na pilha liberta espaço na pilha Load a Load b store c a + b

(8)

Variáveis Locais

Acesso aos registos internos do processador é muito

mais rápido

Mas os registos internos são em número limitado

E por isso nem todas as variáveis locais podem ser

armazenadas nesses registos

No passado a atribuição de registos internos do

processador a variáveis locais era feita pelo

programador:

A linguagem C tem uma palavra reservada para

orientar o compilador:

register

(e.g., register int c;)

Hoje os compiladores são muito mais eficientes

(9)

Variáveis Locais

Utilização de registos internos

void fun() {

int a, b, c;

...

c = a + b;

...

}

fun: … add $t3, $t2, $t1 … jr $ra

Ficheiro de

Registos

$t1

$t2

$t3

a

b

c

(10)

Do alto-nível ao assembly

Implementar Registos

Registos contêm

vários campos

Cada estrutura é

armazenada em

posições contíguas de

memória

typedef struct {

int x, y, z;

} foo;

foo *p;

Memória

z

y

x

p

(11)

Do alto-nível ao assembly

Exemplo com

estrutura

local:

typedef struct {

int x, y, z;

} foo;

fun() {

foo *p;

p->x = p->y + p->z;

fun: addi $sp, $sp, -16 … lw $t1, 0($sp) addi $t1, $t1, 8 lw $t2, 0($t1) lw $t1, 0($sp) addi $t1, $t1, 12 lw $t3, 0($t1) add $t3, $t2, $t3 lw $t1, 0($sp) addi $t1, $t1, 4 sw $t3, 0($t1) … addi $sp, $sp, 16 Reserva espaço na pilha liberta espaço Endereço de p Load p->y Load p->z p->y + p->z store em p->x

Memória

z

y

x

p

address p->y address p->z address p->x Endereço de p Endereço de p

(12)

Do alto-nível ao assembly

Exemplo com estrutura local

(optimizado):

typedef struct {

int x, y, z;

} foo;

fun() {

foo *p;

p->x = p->y + p->z;

fun: addi $sp, $sp, -16 … lw $t2, 8($sp) lw $t3, 12($sp) add $t3, $t2, $t3 sw $t3, 4($sp) … addi $sp, $sp, 16 … Reserva espaço na pilha liberta espaço na pilha Load p->y Load p->z p->y + p->z store em p->x

Memória

z

y

x

p

(13)

Do alto-nível ao

assembly

Compiladores

(14)

Alinhamento, empacotamento e

enchimento

Requisitos de alinhamento:

Inteiros tipo

int

(4 bytes) a começar em

endereços com os 2 LSBs == “00”

Inteiros tipo

short

(2 bytes) a começar em

endereços com o LSB == ‘0’

Alinhamento requer:

Enchimento (padding) entre campos para

assegurar o alinhamento

Empacotamento de campos para assegurar

a utilização de memória

(15)

Alinhamento

typedef struct {

int w;

char x;

int y;

char z;

} foo;

foo *p;

Memória

z

y

x

p

w

Memória

y

x, z

p

w

Organização

“ingénua”

Organização

Empacotada

(poupa 4 bytes)

(16)

Arrays

Afectação de posições

de memória para os

elementos do array

Elementos são

armazenados

contiguamente

Memória

a[0]

int a[4];

a[1]

a[2]

a[3]

Memória

a[1]

short a[4];

a[0]

a[3]

a[2]

(17)

Arrays

Utilizando

registos do

processador

para

armazenar as

variáveis i e j:

.data

A:

.space 16

.text

Proc:

la

$t0, A

addi

$t2, $0, 4

mult

$t1, $t2

mflo

$t2

add

$t3, $t2, $t0

lw

$t4, 0($t3)

int a[4];

proc() {

int i, j;

i = a[j];

}

(18)

Expressões

a = b * c + d – e;

a

em $t4;

b

em $t0;

c

em $t1;

d

em

$t2;

e

em $t3

mult

$t0, $t1

mflo

$t4

sub

$t5, $t2, $t3

add

$t4, $t4, $t5

mult

$t0, $t1

mflo

$t4

add

$t4, $t4, $t2

sub

$t4, $t4, $t3

(19)

Estruturas condicionais

If(a == 1) b = 2;

a

em $t0;

b

em $t1

If(a == 1) b = 2;

else b = 1;

a

em $t2;

b

em $t1

addi

$t2, $0, 1

bne

$t2, $t0, skip_if

addi

$t1, $0, 2

skip_if: …

addi

$t2, $0, 1

bne

$t2, $t0, else

addi

$t1, $0, 2

j

skip_if

else: addi

$t1, $0, 1

(20)

Estruturas condicionais

Branch-delay

O processador executa

sempre a instrução a

seguir a uma instrução

de salto (quer o salto

seja realizado ou não)

Quando não é possível

deslocar uma instrução

para depois da instrução

de salto, tem de se

introduzir uma instrução

nop

if(a == 1) b = 2;

c = a+1;

a

em $t0;

b

em $t1

addi

$t2, $0, 1

bne

$t2, $t0, skip_if

addi

$t3, $t0, 1

addi

$t1, $0, 2

skip_if: …

(21)

Ciclos

Transformar o fluxo de controlo

(while, for, do while, etc.) em saltos

int sum(int A[], int N) { int i, sum = 0;

for(i=0; i<N; i++) { sum = sum + A[i]; }

return sum; }

# $a0 armazena o endereço de A[0] # $a1 armazena o valor de N

Sum: addi $t0, $0, 0 # i = 0 addi $v0, $0, 0 # sum = 0

Loop: beq $t0, $a1, End # if(i == N) goto End; add $t1, $t0, $t0 # 2*i

add $t1, $t1, $t1 # 2*(2*i) = 4*i add $t1, $t1, $a0 # 4*i + base(A) lw $t2, 0($t1) # load A[i]

add $v0, $v0, $t2 # sum = sum + A[i] addi $t0, $t0, 1 # i++

(22)

Ciclos

Otimizações

Manter i e endereço de a[i] em registos

Determinar endereço de a[0] antes do corpo

do ciclo, e incrementar 4 (no caso de serem

acessos a palavras de 32 bits) no corpo do

ciclo

Caso o ciclo execute pelo menos uma

iteração (N > 0) passar salto do ciclo para o

fim do corpo

(23)

Ciclos

Código após as optimizações

int sum(int A[], int N) { int i, sum = 0;

for(i=0; i<N; i++) { sum = sum + A[i]; }

return sum; }

# $a0 armazena o endereço de A[0] # $a1 armazena o valor de N

Sum: Addi $t0, $0, 0 # i = 0 Addi $v0, $0, 0 # sum = 0 Loop: Lw $t2, 0($a0) # load A[i]

Add $v0, $v0, $t2 # sum = sum + A[i] addi $a0, $a0, 4 # add 4 to address Addi $t0, $t0, 1 # i++

bne $t0, $a1, Loop # if(i != N) goto Loop;

(24)

Procedimentos

Protocolo entre os procedimentos que

invocam e os procedimentos invocados

Dependente do processador

No MIPS:

Procedimento espera argumentos nos registos

$a0-$a3

Coloca valores a retornar nos registos $v0-$v1

Outras formas de passagem de parâmetros

utilizam a pilha de chamadas (por exemplo,

sempre que o número de argumentos ultrapassa

o número de registos para utilizar como

(25)

Sumário

Quais as responsabilidades do compilador?

Esconder

do programador conceitos baixo-nível da

máquina

Produzir

rapidamente

código eficiente

Afetar

variáveis a registos locais ou posições de

memória

Cálculo

de expressões com constantes

Manter

funcionalidade inicial

Geração de instruções de forma a suportar as

chamadas aos procedimentos utilizadas no programa

Referências

Documentos relacionados

a) Concessões subsidiadas: são financeiramente inviáveis, onde o poder que concede introduz facilidades financeiras na forma de subsídios ás concessionarias para

Por fim, nas pesquisas de campo procurou-se investigar como se dá a inserção das mulheres no mercado de trabalho na cidade de Guarabira: as características dessa participação

Os testes de desequilíbrio de resistência DC dentro de um par e de desequilíbrio de resistência DC entre pares se tornarão uma preocupação ainda maior à medida que mais

[r]

Evento que exigiu o fim da impunidade para os Crimes de Maio de 2006 reuniu vítimas da violência policial de vários Estados e deixou claro que os massacres de pobres e jovens

Não existem dados clínicos disponíveis para pacientes com alteração hepática grave (Child Pugh C) (ver itens “Contra-indicações” e “Características Farmacológicas”). -

O valor da reputação dos pseudônimos é igual a 0,8 devido aos fal- sos positivos do mecanismo auxiliar, que acabam por fazer com que a reputação mesmo dos usuários que enviam

servidores, software, equipamento de rede, etc, clientes da IaaS essencialmente alugam estes recursos como um serviço terceirizado completo...