1.3 – interpretadores 1.3.1 – compiladores versus interpretadores execução de um programa...
TRANSCRIPT
1.3 – Interpretadores1.3 – Interpretadores
1.3.1 – Compiladores versus 1.3.1 – Compiladores versus InterpretadoresInterpretadores
ExecuçãoExecução de um programa gerado por de um programa gerado por compiladorcompilador::
Programa fonte
Programa em
linguagemde
máquina
Dados
Resultados
Compilador+
MontadorEm tempo de
compilação
Em tempo de
execução
ExecuçãoExecução de um programa de um programa interpretadointerpretado::
O O interpretadorinterpretador faz análise léxica, sintática faz análise léxica, sintática e semântica do programa-fonte, e semântica do programa-fonte, armazenando-o numa armazenando-o numa estrutura internaestrutura interna
Em seguida, ele percorre a Em seguida, ele percorre a estrutura estrutura internainterna, , executandoexecutando as operações ali as operações ali especificadas, consumindo os especificadas, consumindo os dadosdados por elas por elas pedidos pedidos
Programa fonte
Programa numa
estrutura interna
Dados
Resultados
Módulo de análise
e armazena
-mento
Módulo de
execução
Em Tempo de execução
Interpretador
ExecuçãoExecução de um programa de um programa interpretadointerpretado::
Não há criação de um programa em Não há criação de um programa em linguagem de máquinalinguagem de máquina equivalente ao equivalente ao programa-fonteprograma-fonte
O O único programaúnico programa executado é o executado é o interpretadorinterpretador
Programa fonte
Programa numa
estrutura interna
Dados
Resultados
Módulo de análise
e armazena
-mento
Módulo de
execução
Em Tempo de execução
Interpretador
Exemplo:Exemplo: seja o comando de atribuição seja o comando de atribuição
v1 = v2 + v3 * v4;v1 = v2 + v3 * v4;
Um interpretador pode construir-lhe uma Um interpretador pode construir-lhe uma árvore de execução árvore de execução (estrutura interna):(estrutura interna):
= Depois ele caminha pela árvore, executando as operações
Na raiz, ele faz uma atribuição da expressão do Na raiz, ele faz uma atribuição da expressão do lado direitolado direito à variável do à variável do lado esquerdolado esquerdo
No cálculo dessa No cálculo dessa expressãoexpressão, ele soma a , ele soma a variável dovariável do lado esquerdo lado esquerdo com a expressão do com a expressão do lado direitolado direito (chamada (chamada recursivarecursiva do cálculo do cálculo de expressão)de expressão)
=
Há interpretadores de código Há interpretadores de código fontefonte e de e de código código intermediáriointermediário
Interpretador de código fonte:Interpretador de código fonte: Deve haver Deve haver uma forma de armazenamento do programa uma forma de armazenamento do programa fontefonte
Interpretador de código intermediário:Interpretador de código intermediário: o o código intermediário pode ser gerado pelo código intermediário pode ser gerado pelo mesmo processo usado nos compiladoresmesmo processo usado nos compiladores
1.3.2 – Interpretadores de código-fonte1.3.2 – Interpretadores de código-fonte
Durante a Durante a análise sintáticaanálise sintática, o programa-fonte , o programa-fonte é é armazenadoarmazenado numa estrutura denominada numa estrutura denominada árvore do programaárvore do programa
Depois, essa estrutura é Depois, essa estrutura é percorridapercorrida, para que , para que os comandos do programa sejam os comandos do programa sejam executadosexecutados
Exemplo:Exemplo: programa para o programa para o Bubble-SortBubble-Sort
void main () {void main () {int n, i, p, aux, vetor[50]; int n, i, p, aux, vetor[50]; char trocou;char trocou;read (n);read (n);for (i=0; i<n; i++)for (i=0; i<n; i++)
read (vetor[i]);read (vetor[i]);trocou = 1;trocou = 1;for (p = n-2; p>=0 && trocou == 1; p--) {for (p = n-2; p>=0 && trocou == 1; p--) {
trocou = 0; trocou = 0; for (i = 0; i<=p; i++)for (i = 0; i<=p; i++)
if (vetor[i] > vetor[i+1]) {if (vetor[i] > vetor[i+1]) {aux = vetor[i]; aux = vetor[i]; vetor[i] = vetor[i+1];vetor[i] = vetor[i+1];vetor[i+1] = aux; vetor[i+1] = aux; trocou = 1;trocou = 1;
}}}}for (i=0; i<n; i++) for (i=0; i<n; i++)
write (vetor[i]);write (vetor[i]);}}
Sua árvore de armazenamento
As declarações podem ser eliminadas
Cada nó retangular pode ser mais detalhado
Cada nó retangular pode ser mais detalhado
Ver detalhes
Cada nome de variável deve ser substituído por um ponteiro para sua posição na tabela de símbolos
Lá deve haver um campo para guardar seu valor
Interpretação Interpretação de código de código fonte é muito fonte é muito ineficienteineficiente
Os programas Os programas costumam ter costumam ter muitos muitos aninhamentoaninhamentoss
Cada tipo de Cada tipo de comando é comando é executado por executado por um módulo um módulo específicoespecífico
O módulo de O módulo de um comando um comando repetitivo irá repetitivo irá chamar os chamar os módulos dos módulos dos comandos de comandos de seu escoposeu escopo
Se um deles Se um deles for um for um comando comando condicional, condicional, ocorrerá com ocorrerá com ele o mesmoele o mesmo
Num dado Num dado momento, momento, poderão estar poderão estar ativas várias ativas várias versões de versões de diversos diversos módulosmódulos
Há Há consumoconsumo de muita memória e de muita memória e sobrecarga sobrecarga de trabalhode trabalho para gerenciá-la para gerenciá-la
Os interpretadores de código Os interpretadores de código intermediáriointermediário são os são os preferidospreferidos
No entanto, o conceito de No entanto, o conceito de árvore de árvore de programaprograma é muito útil em softwares que é muito útil em softwares que fazem fazem análise do programa-fonteanálise do programa-fonte
Por exemplo, em Por exemplo, em compiladores paraleloscompiladores paralelos, a , a detecção de paralelismo exige detecção de paralelismo exige análise de análise de dependênciasdependências que só pode ser feita se o que só pode ser feita se o programa-fonteprograma-fonte estiver apropriadamente estiver apropriadamente armazenadoarmazenado
1.3.3 – Interpretadores de código 1.3.3 – Interpretadores de código intermediáriointermediário
Podem ter os mesmos componentes da Podem ter os mesmos componentes da frentefrente de de um compilador convencional:um compilador convencional:
Analisadores léxico, sintático e semântico Analisadores léxico, sintático e semântico Gerador de código intermediárioGerador de código intermediário Otimizador de código intermediárioOtimizador de código intermediário
Além desses, devem ter o componente que vai fazer Além desses, devem ter o componente que vai fazer a a interpretaçãointerpretação propriamente dita do propriamente dita do código código intermediáriointermediário
Esse componente Esse componente percorre o códigopercorre o código, executando , executando as as operaçõesoperações ali especificadas e processando os ali especificadas e processando os dadosdados por elas solicitados por elas solicitados
Exemplo:Exemplo: laço do programa anterior: laço do programa anterior:
for (i = 0; i<=p; i++)for (i = 0; i<=p; i++)
if (vetor[i] > vetor[i+1]) {if (vetor[i] > vetor[i+1]) {
aux = vetor[i]; vetor[i] = vetor[i+1];aux = vetor[i]; vetor[i] = vetor[i+1];
vetor[i+1] = aux; trocou = 1;vetor[i+1] = aux; trocou = 1;
}}
Suas Suas quádruplasquádruplas com alguma otimização: com alguma otimização:
A propósito, A propósito, quádruplas para indexaçãoquádruplas para indexação::
Sejam as seguintes declarações e comandos:Sejam as seguintes declarações e comandos:
int i, j, k, A[6][5]; int i, j, k, A[6][5];
i = 4; j = 3;i = 4; j = 3;
k = A[i][j-2];k = A[i][j-2];
A[10-i][2*j+3] = i + j * k;A[10-i][2*j+3] = i + j * k;
Acesso a um elemento genérico Acesso a um elemento genérico A[i][j]:A[i][j]:
Uma vez conhecido o Uma vez conhecido o endereço inicialendereço inicial da da matriz matriz AA, é necessário , é necessário localizarlocalizar o elemento o elemento A[i][j]A[i][j]
Seja a seguir o mapa de Seja a seguir o mapa de A[6][5] A[6][5] na memória:na memória:
Seja Seja mm o número de linhas o número de linhas e e nn o número de colunas da o número de colunas da matriz matriz AA
O endereço do elemento O endereço do elemento A[i][j] A[i][j] é dado pela fórmula:é dado pela fórmula:
Ender (A) + i * n + jEnder (A) + i * n + j
Para Para m = 6m = 6, , n = 5n = 5, o , o endereço de endereço de A[4][3]A[4][3] é é
Ender (A) + 23Ender (A) + 23
No programa, cada No programa, cada índiceíndice pode ser uma pode ser uma expressão expressão inteirainteira
Calcula-se o valor de cada Calcula-se o valor de cada índiceíndice, empilhando-o numa , empilhando-o numa pilha de índicespilha de índices
Isso pode ser feito pela Isso pode ser feito pela execução de uma execução de uma quádruplaquádrupla de operador de operador INDIND::
IND, i , ---- , ----IND, i , ---- , ----
IND, j , ---- , ----IND, j , ---- , ----
Calcula-se o endereço de Calcula-se o endereço de A[i]A[i][j][j], usando uma quádrupla de , usando uma quádrupla de operador operador INDEXINDEX::
INDEX , A , 2 , temp1INDEX , A , 2 , temp1
Sua Sua execuçãoexecução consiste em: consiste em: Pegar as Pegar as dimensõesdimensões e o e o
endereçoendereço de de AA na tabela de na tabela de símbolossímbolos
Desempilhar Desempilhar dois índicesdois índices Calcular o Calcular o endereçoendereço, ,
colocando-o na variável colocando-o na variável temp1temp1
A variável A variável temp1 temp1 é portanto um é portanto um ponteiroponteiro
Formação do código intermediário:Formação do código intermediário:
int i, j, k, A[6][5];
i = 4; j = 3;
k = A[i][j-2] + 5;
A[10-i][2*j+3] = i+j*k;
:=, 4, ..., i :=, 3, ..., j
IND, i, ..., ... -, j, 2, temp1 IND, temp1, ..., ... INDEX, A, 2, temp2
@, temp2, ..., temp3 +, temp3, 5, ktemp2 tem o endereço
do elemento A[i][j-2]
É necessário saber o valor guardado nesse elemento
A quádrupla@, temp2, ..., temp3
atribui a temp3 o valor do local apontado por temp2
Formação do código intermediário:Formação do código intermediário:
int i, j, k, A[6][5];
i = 4; j = 3;
k = A[i][j-2] + 5;
A[10-i][2*j+3] = i+j*k;
:=, 4, ..., i :=, 3, ..., j
IND, i, ..., ... -, j, 2, temp1 IND, temp1, ..., ... INDEX, A, 2, temp2
@, temp2, ..., temp3 +, 5, temp3, k
-, 10, i, temp4 IND, temp4, ..., ... *, 2, j, temp5 +, temp5, 3, temp6 IND, temp6, ..., ... INDEX, A, 2, temp7
*, j, k, temp8 +, i, temp8, temp9
#, temp9, ..., temp7
temp7 tem o endereço do elemento A[10-i][2*j+3]
O valor de temp9 deve ser atribuído ao local apontado por temp7
A quádrupla#, temp9, ..., temp7
atribui o valor de temp9 ao local apontado por temp7
Voltando ao laço do programa anterior:Voltando ao laço do programa anterior:
for (i = 0; i<=p; i++)for (i = 0; i<=p; i++)
if (vetor[i] > vetor[i+1]) {if (vetor[i] > vetor[i+1]) {
aux = vetor[i]; vetor[i] = vetor[i+1];aux = vetor[i]; vetor[i] = vetor[i+1];
vetor[i+1] = aux; trocou = 1;vetor[i+1] = aux; trocou = 1;
}}
Suas Suas quádruplasquádruplas::
Estrutura de dados
São omitidos vários ponteiros
As quádruplas poderiam ser guardadas numa lista encadeada ao invés de num vetor
Desvantagens da interpretação:Desvantagens da interpretação:
A A execuçãoexecução de programas de programas compiladoscompilados é muito é muito mais mais rápidarápida que a de programas que a de programas interpretadosinterpretados
Apesar do Apesar do código intermediáriocódigo intermediário ser ser aperfeiçoadoaperfeiçoado antes da interpretação antes da interpretação propriamente dita, o propriamente dita, o código objetocódigo objeto ainda pode ainda pode ser ser otimizadootimizado
Isso Isso não ocorrenão ocorre em programas em programas interpretadosinterpretados
Um Um interpretadorinterpretador faz por faz por softwaresoftware a a interpretação do interpretação do código da operaçãocódigo da operação; num ; num programa programa compiladocompilado isso ocorre por isso ocorre por hardwarehardware, o que é muito mais , o que é muito mais rápidorápido
Vantagens da interpretação:Vantagens da interpretação:
O código intermediário é O código intermediário é independenteindependente de de máquina, o que lhe confere máquina, o que lhe confere portabilidadeportabilidade
Um programa Um programa compiladocompilado só pode rodar em só pode rodar em máquinas compatíveis com sua máquina alvomáquinas compatíveis com sua máquina alvo
InterpretadoresInterpretadores se mostram adequados para se mostram adequados para as redes de computadores heterogêneos, que é as redes de computadores heterogêneos, que é o caso da o caso da InternetInternet
A elaboração de um módulo A elaboração de um módulo interpretador interpretador propriamente ditopropriamente dito é muito mais simples que é muito mais simples que a de uma a de uma retaguardaretaguarda de compilador de compilador
Os detalhes da Os detalhes da arquiteturaarquitetura da máquina-alvo da máquina-alvo complicam muito o projeto da complicam muito o projeto da retaguardaretaguarda
Para casos em que a Para casos em que a rapidezrapidez de execução de execução não é não é fundamentalfundamental, os interpretadores são preferidos, , os interpretadores são preferidos, em comparação com os compiladores em comparação com os compiladores
A Linguagem Java:A Linguagem Java:
Seu compilador gera código denominado Seu compilador gera código denominado bytecodebytecode, independente de máquina, independente de máquina
BytecodeBytecode é traduzido para linguagem de máquina é traduzido para linguagem de máquina por uma por uma máquina virtualmáquina virtual residente em qualquer residente em qualquer ambiente ambiente JavaJava
Bytecode Bytecode é é portávelportável, porém, para ser , porém, para ser executadoexecutado, , deve ser deve ser traduzidotraduzido, o que torna o processo mais , o que torna o processo mais lentolento
1.4 – Automação da Construção 1.4 – Automação da Construção de Compiladoresde Compiladores
1.4.1 – Bootstrapping e compiladores 1.4.1 – Bootstrapping e compiladores cruzadoscruzados
O O compiladorcompilador para a para a primeiraprimeira linguagem de linguagem de programação só poderia ter sido escrito em programação só poderia ter sido escrito em AssemblyAssembly
Assim foi com Assim foi com FortranFortran e e CobolCobol
Seus projetos demandaram Seus projetos demandaram esforçoesforço de de programação programação descomunaldescomunal
No princípio:No princípio:
Assembler
Máquina M1
Primeiro compilador Fortran, escrito em Primeiro compilador Fortran, escrito em Assembly:Assembly:
Assembler
Máquina M1
Fortran
em Assembly
Fortranem M1
Compilador Algol, escrito em Fortran:Compilador Algol, escrito em Fortran:
Assembler
Máquina M1
Fortran
em Assembly
Fortranem M1
Algolem Fortran
Algolem M1
Compilador Pascal, escrito em Algol:Compilador Pascal, escrito em Algol:
Assembler
Máquina M1
Fortran
em Assembly
Fortranem M1
Algolem Fortran
Algolem M1
Pascal
em Algol
Pascal
em M1
Compilador C, escrito em Pascal:Compilador C, escrito em Pascal:
Assembler
Máquina M1
Fortran
em Assembly
Fortranem M1
Algolem Fortran
Algolem M1
Pascal
em Algol
Pascal
em M1
Cem Pascal
Cem M1
Em UNIX, compiladores L1, L2, ... , escritos Em UNIX, compiladores L1, L2, ... , escritos em C:em C:
Assembler
Máquina M1
Fortran
em Assembly
Fortranem M1
Algolem Fortran
Algolem M1
Pascal
em Algol
Pascal
em M1
Cem Pascal
Cem M1
L1 em C
L2 em C
L1 em M1
L2 em M1
Em UNIX, compiladores C eram escritos em Em UNIX, compiladores C eram escritos em C:C:
Assembler
Máquina M1
Fortran
em Assembly
Fortranem M1
Algolem Fortran
Algolem M1
Pascal
em Algol
Pascal
em M1
Cem Pascal
Cem M1
C1 em C
C2 em C
C1 em
M1
C2 em
M1
Bootstrapping:Bootstrapping: propriedade de uma propriedade de uma linguagem compilar a linguagem compilar a si mesmasi mesma
Compilador cruzado:Compilador cruzado: compilador que roda compilador que roda numa máquina e numa máquina e gera código para outragera código para outra
Para uma máquina Para uma máquina M2M2, seria necessário , seria necessário escrever um programa em escrever um programa em AssemblyAssembly para um para um primeiroprimeiro compilador? compilador?
Com Com bootstrappingbootstrapping e e compiladores compiladores cruzadoscruzados pode-se evitar isso (visto a seguir) pode-se evitar isso (visto a seguir)
Um Um compiladorcompilador é caracterizado por é caracterizado por 3 3 linguagenslinguagens::
A A linguagem-fontelinguagem-fonte ( (FF) que ele compila) que ele compila
A A linguagem-objetolinguagem-objeto ( (OO) para a qual ele ) para a qual ele gera código gera código
A A linguagem de implementaçãolinguagem de implementação ( (II) na ) na qual ele está escritoqual ele está escrito
Simbolicamente, Simbolicamente, FFIIOO
Ou, usando diagrama Ou, usando diagrama TT::F O I
Seja Seja MM usado para denotar a usado para denotar a linguagem de linguagem de máquinamáquina de um computador ou máquina de um computador ou máquina MM
Para um Para um compiladorcompilador rodar na máquina rodar na máquina MM, sua , sua linguagem de linguagem de implementaçãoimplementação deve ser deve ser M M
F O M
Seja um compilador Seja um compilador L1L1MMMM residindo na residindo na máquina máquina MM
Deseja-se em Deseja-se em MM um compilador para uma nova um compilador para uma nova linguagem linguagem L2L2, ou seja, , ou seja, L2L2MMMM
Primeiramente escreve-se um programa Primeiramente escreve-se um programa L2L2L1L1MM
Depois roda-se na máquina Depois roda-se na máquina MM::
L2 M L1
L1 M M
L2 M M
EntradaPrograma em execução
Saída
O compilador de L2 está pronto para rodar em M
Esquema para se obter um Esquema para se obter um compilador compilador cruzadocruzado::
Agora em Agora em M1M1, um compilador de , um compilador de L2L2 para a para a máquina máquina M2M2
Os programas escritos em Os programas escritos em L2L2 são compilados são compilados em em M1M1 e o código objeto é transportado para e o código objeto é transportado para M2M2
L2 M2 L1
L1 M1 M1
L2 M2 M1
Entrada
Compilador residindo em M1, em execução
Saída
Seja então Seja então L L a primeira linguagem a ser a primeira linguagem a ser instalada na máquina instalada na máquina M2M2, mas já instalada na , mas já instalada na máquina máquina M1M1 ( (LLM1M1M1M1))
Primeiramente, Primeiramente, bootstrappingbootstrapping: : LLLLM2M2
Depois, produz-se em Depois, produz-se em M1M1 um compilador um compilador cruzadocruzado
Finalmente, usando em Finalmente, usando em M1M1 o compilador o compilador cruzado produzidocruzado produzido
É só transportar É só transportar LLM2M2M2M2 para a máquina para a máquina M2M2
L M2 L
L M1 M1
L M2 M1
EntradaPrograma em execução
SaídaPrograma
em execução
Entrada
L M2 M2
Saída
Compilador desejado
1.4.2 – Compiladores de compiladores1.4.2 – Compiladores de compiladores
As ferramentas de As ferramentas de automaçãoautomação, logo que , logo que começaram a surgir, receberam alguns nomes começaram a surgir, receberam alguns nomes um tanto um tanto ambiciososambiciosos: :
Geradores de compiladoresGeradores de compiladores
Compiladores de compiladoresCompiladores de compiladores
Sistemas de construção de tradutoresSistemas de construção de tradutores
1.4.2 – Compiladores de compiladores1.4.2 – Compiladores de compiladores
Eram ferramentas de Eram ferramentas de uso limitadouso limitado, pois eram , pois eram orientadas em torno de orientadas em torno de modelos particularesmodelos particulares de linguagens de linguagens
Devido à grande Devido à grande heterogeneidadeheterogeneidade das das linguagens e das arquiteturas, é muito difícil a linguagens e das arquiteturas, é muito difícil a elaboração de um gerador de propósitos gerais elaboração de um gerador de propósitos gerais eficienteeficiente
O que existe hoje são O que existe hoje são ferramentas automáticasferramentas automáticas para o projeto de para o projeto de componentes específicoscomponentes específicos, , relacionados a seguirrelacionados a seguir
1.4.3 – Ferramentas para cada componente1.4.3 – Ferramentas para cada componente
Utilizam Utilizam linguagens especializadaslinguagens especializadas para a para a especificação e implementação do componente e especificação e implementação do componente e algoritmos bem sofisticados algoritmos bem sofisticados
Geradores de analisadores léxicos:Geradores de analisadores léxicos:
Têm como entrada Têm como entrada expressões regularesexpressões regulares e e implementam um implementam um autômato finitoautômato finito reconhecedor e reconhecedor e classificador dos átomos dos programas a serem classificador dos átomos dos programas a serem compiladoscompilados
A mais conhecida entre elas é o A mais conhecida entre elas é o LexLex do sistema do sistema UnixUnix, que possui também versões para o sistema , que possui também versões para o sistema DOSDOS
O programa gerado é escrito em O programa gerado é escrito em Linguagem CLinguagem C
1.4.3 – Ferramentas para cada 1.4.3 – Ferramentas para cada componentecomponente
Geradores de analisadores sintáticos:Geradores de analisadores sintáticos:
Têm como entrada a Têm como entrada a gramática livre de gramática livre de contextocontexto da linguagem-fonte do compilador da linguagem-fonte do compilador
Nos compiladores primitivos, a análise Nos compiladores primitivos, a análise sintática consumia grande fração dosintática consumia grande fração do tempo de tempo de compilação e do esforço intelectualcompilação e do esforço intelectual para para escrever um compilador escrever um compilador
Hoje é considerada uma das fases Hoje é considerada uma das fases mais fáceismais fáceis de serem implementadasde serem implementadas
1.4.3 – Ferramentas para cada 1.4.3 – Ferramentas para cada componentecomponente
Geradores de analisadores sintáticos:Geradores de analisadores sintáticos:
Utilizam algoritmos de analise muitoUtilizam algoritmos de analise muito eficientes eficientes, , porémporém muitomuito complexos complexos para serem para serem implementados implementados à mãoà mão
A mais conhecida: A mais conhecida: YaccYacc ( (Yet Another Yet Another Compiler-CompilerCompiler-Compiler) do sistema UNIX que ) do sistema UNIX que também possui diversas versões para o sistema também possui diversas versões para o sistema DOSDOS
O programa gerado também é escrito em O programa gerado também é escrito em Linguagem CLinguagem C
1.4.3 – Ferramentas para cada 1.4.3 – Ferramentas para cada componentecomponente
Geradores de código intermediário:Geradores de código intermediário:
Produzem uma Produzem uma coleção de rotinascoleção de rotinas que, ao que, ao caminhar pela caminhar pela árvore sintáticaárvore sintática do programa, do programa, já com já com atributos calculadosatributos calculados pelo analisador pelo analisador semântico, produzem o código intermediáriosemântico, produzem o código intermediário
Analisadores de fluxo de dados: Analisadores de fluxo de dados:
Importante ferramenta para a Importante ferramenta para a otimização do otimização do código intermediáriocódigo intermediário
1.4.3 – Ferramentas para cada 1.4.3 – Ferramentas para cada componentecomponente
Geradores de código objeto:Geradores de código objeto:
Recebem como entrada uma Recebem como entrada uma coleção de coleção de regrasregras que definem a que definem a traduçãotradução de cada tipo de cada tipo de comando do de comando do código intermediáriocódigo intermediário em em código de máquina ou código de máquina ou AssemblyAssembly
Essas Essas regrasregras devem incluir devem incluir detalhesdetalhes suficientes para se escolher os locais suficientes para se escolher os locais adequados para adequados para alocação de variáveisalocação de variáveis (registradores, memória, pilha, etc)(registradores, memória, pilha, etc)