Compiladores. versão α 0.002

Tamanho: px
Começar a partir da página:

Download "Compiladores. versão α 0.002"

Transcrição

1 Compiladores Geração de Código Intermédio versão α Simão Melo de Sousa Este documento é a adaptação duma tradução do capítulo Génération de Code Intermédiaire da sebenta Cours de Compilation de Christine Paulin-Morhing ( 1 Introdução Antes de gerar um código/programa particular, é necessário apresentar os problemas que se colocam ao organizar os dados e as instruções dentro dum programa. 1.1 Modelos de execução Aquando da execução de código, uma parte da memória é reservada para as instruções do programa com um apontador para indicar em que ponto (do programa) se encontra a execução. O tamanho do código é conhecido na altura da compilação. Supõe-se que existe um controlo sequencial da execução dum programa. Isto é, que todas as instruções dum programa, excepto instruções de salto, são executadas sequencialmente umas após a outra. Os dados são guardados na memória ou nos registos da máquina (que executa). A memória está organizada em palavras. Esta é acedida via um endereço que é representado por um inteiro. Os valores simples são guardados numa unidade de memória, os valores complexos ou compostos (vectores, estruturas) são guardados em células contíguas da memória ou em estruturas encadeadas (uma lista poderá ser representada por um elementos associado a um apontador contendo o endereço memória do próximo elemento). Os registos permitam o acesso rápido a dados simples. O número de registos depende da arquitectura alvo e é em geral relativamente pequeno. 1.2 Alocação Certos dados são explicitamente manipulados pelo programa fontes pelo intermédio de variáveis. Outro são criados pelo compilador, por exemplo para conservar os valores de cálculos intermédios ou para guardar ambientes associados a valores funcionais. Alguns dados tem uma duração de vida conhecida na altura da compilação. É assim possível, e até desejável, reutilizar o espaço utilizado. A análise da duração de vida 1

2 de variáveis deve pelo menos ter em conta das regras de alcance (variable scope) da linguagem fonte. De facto uma variável que deixa de ser visível corresponde em geral a um espaço memória (um dado) inacessível. Esta análise pode igualmente utilisar técnicas de análise de fluxo de controlo (control flow analysis) que permitam detectar variáveis não utilizadas. As variáveis globais do programa compilado podem ser alocadas para endereços fixos pelo compilador, na condição de conhecer o tamanho de cada uma delas. A gestão das variáveis locais, dos blocos e dos procedimentos, ou ainda do armazenamento dos valores intermédios prestam-se bem a uma gestão de alocação da memória baseada em pilhas. Outros dados, pelo contrário, não tem uma duração de vida conhecida na fase de compilação. É o caso por exemplo quando se manipula apontadores. Alguns objectos alocados não corresponderão directamente a um valor, mas serão acessíveis pelo intermédio do seu endereço, podendo este estar associado a uma variável. Estes dados serão alocados, em geral, numa outra parte da memória, designada de heap. Para não desperdiçar este espaço, o programador necessitará recorrer a (a) comandos que permitam uma gestão explícita da memória (como libertar espaço) ou (b) um programa de recuperação de memória designado geralmente de GC (para Garbage Collector). 1.3 Variáveis Uma variável é um identificador que aparece num programa e que está associada a um objeto manipulado pelo programa, em geral arquivado na memória. Distingue-se o valor esquerdo da variável que representa o endereço memória a partir do qual é arquivada o valor do objecto, do valor direito, que representa o valor do objecto. Algumas linguagens como o ML distiguam explicitamente os dois tipos de objectos. A linguagem PASCAL é a posição sintáctica da variável que determina se deve ser interpretada como um valor esquerdo ou valor direito. A passagem de parâmetro nas funções e procedimentos podem ser feitos com base no valor direito ou esquerdo dos objecto manipulados. Ambiente e estado. É designado por ambiente a associação de nomes a endereços memória. Esta ligação pode ser representada por um conjunto finito de pares formados por um identificador e por um endereço. Um ambiente define uma função parcial que associa um endereço a um identificador. Designa-se por estado uma função parcial dos endereços memória para valores. Quando se atribui um valor a uma variável só o estado se altera. Quando se invoca uma função ou a um procedimento possuindo parâmetros, o ambiente muda. A variável introduzida corresponde a uma noção ligação entre um nome e um endereço. 1.4 Semântica Para construir uma tradução correcta é essencial conhecer as regras de avaliação da linguagem fonte, ou seja a sua semântica. Estas regras são frequentemente apresentadas em termos de transformadores de estado e/ou de ambiente. 2

3 1.5 Procedimentos e funções Um procedimento tem um nome, parâmetros, contêm declarações de variáveis ou de procedimentos locais e possui um corpo. Uma função é um procedimento que retorna um valor. Os parâmetros formais são variáveis locais ao procedimento que serão instanciados pelos parâmetros efectivos quando o procedimento for invocado. O procedimento pode declarar variáveis locais que serão inicializadas no corpo do procedimento. O espaço memória alocado para os parâmetros pode em geral ser libertado quando a execução sai do procedimento. No entanto não se pode, em geral, controlar o número de vezes que um procedimento será invocado nem quando. Por isso não se pode em geral estabelecer estaticamente o endereço das variáveis contidas num procedimento. Estes endereços poderão ser calculadas relativamente ao estado da pilha de operandas na altura da invocação. Por exemplo: program main var j : int; procedure p(i,j:int); {print(i,j);if i+j>0 then j:=j-1; p(i-2,j); print(i,j);p(j,i)} {read(j); p(j,j); print(j)} O número de execução de p depende do valor lido em entrada. Em cada entrada no procedimento p, duas novas variáveis i e j são alocadas. No esquema seguinte representase a execução deste programa tendo em conta a leitura de o valor 1. Os objectos da pilha são representados após cada instrução que modifica o estado. A pilha cresce aqui de cima para baixo, os valores correntes de i e j são separados. A execução realiza-se da esquerda para a direita e de baixo para cima. As pilhas são numeradas seguindo ordem da execução (ver figura 1). 1.6 Organização do Ambiente A organização do ambiente de execução depende do que a linguagem autorisa: procedimentos recursivos processamento de variáveis locais referências para nomes locais modos de passagem de parâmetros existência de dados de tamanhos variáveis capacidade em devolver procedimentos ou aceitar procedimentos como parâmetros alocação/desalocação dinâmica de dados pelo programador 3

4 Figura 1: Chamadas a funções e procedimento, um exemplo. 4

5 2 Tabelas de Activação Um dos aspectos importantes na organização da memória é a gestão das chamadas aos procedimentos (ou funções). Estas são efectuadas pelo intermédio duma tabela de activação (frame ou activation records em inglês). Esta tabela é um pedaço de memória que está atribuida à chamada do procedimento e devolvida à saída deste. A tabela contém toda a informação necessária a execução do programa e arquiva todos os dados que deverão ser restabelecidos a saída do procedimento. Para facilitar a comunicação entre os diferentes tipos de códigos compilados a partir de linguagens fontes diferentes (por exemplo para poder chamar procedimentos de baixo nível a partir de linguagens de alto nível), não é raro que seja recomendado a existência dum formato particular de tabela de activação para uma dada arquitectura. 2.1 Dados por conservar Quando um procedimento é invocado, o fluxo de controlo do código é modificado. No caso de o retorno normal do procedimento (a execução do procedimento não provocou levantamento de excepção, nenhuma instrução de salto (de tipo goto) levou a execução a sair do procedimento), a execução continua na instrução que segue a chamada ao procedimento. O program counter na altura da chamada deve então ser arquivado de forma a que a execução possa continuar normalmente após o retorno. Sabe-se que os dados locais ao procedimento organizam-se na pilha de operandos a partir de um endereço que é determinada na execução e em geral salvaguardado num registo. Quando um novo procedimento é chamado, este valor muda. É assim igualmente necessário guardar este valor que poderá ser restaurado ao fim da execução do procedimento invocado. 2.2 Passagem de parâmetros Os parâmetros formais dum procedimento são variáveis que são inicializadas aquando da chamada ao procedimento. Existem várias maneiras de efectuar esta inicialização. Imaginemos o procedimento p com um parâmetro formal x que é invocado com o parâmetro efectivo e. Vamos explorar aqui as diferentes formas de efectuar esta passagem. Passagem por valor: Neste tipo de passagem, x é uma nova variável alocada localmente pelo procedimento cujo valor é o resultado da avaliação de e. Após o fim do procedimento, as modificações a que x foi submetida deixam de ser visíveis. Na ausência de apontadores, as únicas variáveis modificadas são as variáveis não locais ao procedimento em questão e que constam explicitamente nas instruções deste último. É necessário reservar um espaço proporcional ao tamanho dos parâmetros o que pode ser custoso no caso dos vectores. Passagem por referência: Calcula-se o valor esquerdo da expressão e (se e não tem valor esquerdo, então cria-se uma variável que se inicializa com o valor direito de e e utiliza-se o valor esquerdo desta variável). O procedimento aloca uma variável x que é inicializada pelo valor esquerdo de e. Qualquer referência a x no corpo do procedimento é interpretada como uma operação sobre o objecto situado no 5

6 endereço guardado em x. Este tipo de passagem ocupa um espaço independente do tamanho do parâmetro. Passagem por nome: Trata-se duma substituição textual dentro do corpo do procedimento dos parâmetros formais pelos parâmetros efectivos. Este tipo de passagem, baseado num mecanismo de macro, pode provocar problemas de captura de variáveis. Exemplo: swap(x,y:int) var z:int {z:=x; x:=y; y:=z} Se z e t são variáveis globais do programa, swap(z,t) não tera o comportamento esperado. Pode-se renomear as variáveis locais por forma a não interagir com as variáveis que aparecem nos argumentos. De facto o nome da variável local z, desde que seja diferente de x e de y, não tem influência sobre o código do procedimento. Mas isto não chega, por exemplo a passagem por nome de swap(i,a[i]) não retorna o resultado esperado. Este método é no entanto útil para a compilação de procedimentos de pequeno tamanho onde o custo da gestão de chamadas a procedimentos é importante. Passagem por Copy-Restore Durante a chamada ao procedimento, o valor direito de e serve para inicializar a variável x. À saída do procedimento, o valor direito de x serve para a actualização do valor esquerdo de e. Este método pode ter, em casos particulares, comportamentos diferentes do passagem por referência, como o ilustra o exemplo seguinte: program main; var a : integer; procedure p(x:integer); {x:=2; a:=0} {a:=1;p(a);write(a)} Avaliação pregiçosa (lazy evaluation - call by need) Nas linguagens funcionais, distinguese as linguagens estritas das linguagens ditas preguiçosas. Numa linguagem estrita os valores dos argumentos são avaliados antes de serem passadas em parâmetros duma função. É o caso de linguagens como OCaml e SML. Nas linguagens preguiçosas, a expressão passada em parâmetro à função f só será avaliada se f realmente precisa do valor da expressão (origem do nome call by need). Imaginemos que a função f(x) = t esteja declarada e que se pretende calcular f(e). Desde que se precise do valor de x então o calculo de e é realizado. Apesar de t utilizar várias vezes x, é importante que o cálculo de e se faça uma única vez. A expressão e é passada em parâmetro com o seu ambiente (estrutura arquivando 6

7 todas as variáveis utilizadas por e), o que evita os fenómenos de captura de variáveis. Este mecanismo é assim diferente do mecanismo de substituição textual utilizado no esquema de passagem de parâmetro anteriormente descrito. A linguagem Haskell utiliza a avaliação preguiçosa. Este tem a vantagem de só realizar os cálculos úteis. No entanto, a necessidade de passar ambientes associados aos parâmetros induz um custo. Mais, é difícil neste tipo de linguagem de prever o momento onde efeitos lateral eventuais presentes nas expressões passadas terão lugar (o que induz vários comportamentos possíveis para os programas, o que é indesejável). Por isso Haskell é uma linguagem funcional pura sem efeitos laterais, o que não impede a linguagem de ser eficaz e de utilização a escala industrial. 2.3 Acesso às variáveis locais Um procedimento pode aceder às suas variáveis locais que se encontram na sua tabela de activação, e às variáveis globais que se encontram num endereço conhecido na altura da compilação. Nas linguagens funcionais ou de tipo Pascal, os procedimentos podem ser aninhados e o corpo dum procedimento p pode aceder a variáveis declaradas num procedimento q que englobe p. É assim necessário aceder à tabela de activação de q que adequadamente se encontra na pilha de chamadas por baixo da tabela de activação de p. Infelizmente não é possível determinar estaticamente (sem executar) a posição da tabela de activação de q em relação a de p. É assim necessária a utilização de mecanismos de encadeamentos de tabelas de activação para encontrar a variável adequada. Árvore de nível das declarações Supõe-se que se tem uma linguagem funcional ou imperativo no qual os procedimentos, funções e variáveis podem ser arbitrariamente aninhados. O porte das variáveis (variable scope) pode ser calculada de forma estática seguindo as regras habituais de visibilidade. O nível duma declaração (procedimentos, funções ou variáveis) é o número de procedimentos ou funções debaixo dos quais esta é definida. O programa principal tem um nível 0, as variáveis globais definidas no programa principal terão o nível 1. Por exemplo: program main var t:int procedure p(x,y:int); var z : int procedure q(i:int) var u : int begin u:=z+t+i; if x=u or y=u then x else if u < x then p(u,x) else if y < u then p(y,u) else q(i+1) end begin read(z); q(z) end begin read(t);p(t,t) end 7

8 Podemos calcular de forma estática os níveis de cada identificador. Introduz-se um certo número de definição ligadas às declarações, um identificador designa indiferentemente um procedimento, uma função ou uma variável: dir-se-á que p é o pai dum identificador de y se y é declarada dentro de p. Dir-se-á que p é ancião de y se p é y ou pai dum ancião de y. Dir-se-á de dois identificadores que são irmãos se têm o mesmo pai. Se o corpo dum procedimento p faz referência a um identificador então as regras de porte são tais que este é (a) ou uma declaração local e p (b) ou um ancião de p (por exemplo o próprio p) (c) ou um irmão dum ancião de p. Árvore de Activação Interessamo-nos agora pelas execuções possíveis dum programa. Para tal introduzimos a noção de árvore de activação. Os nodos desta árvore representam as chamadas aos procedimentos p(e 1,, e n ). Um nodo tem k filhos q 1 q k se a execução do procedimento em causa invoca directamente os procedimentos q 1 q k (este procedimentos podem eles próprios chamar outros procedimentos...). A raíz da árvore é a execução do programa principal. Exemplo: Dar as árvores de activação do programa anterior no caso das variáveis lidas valerem sucessivamente 1, 1 e 0. Durante uma execução dir-se-á dum procedimento que este é activo se a execução se encontra entre o início e o fim do corpo do dito procedimento. Nota-se assim que a ordem de chamada não corresponde necessariamente a ordem das declarações. No entanto demonstra-se que quando um procedimento está activo então todos os seus anciões são igualmente activos (demonstração por indução sobre a árvore de activação). A execução do programa principal define a raíz da árvore e este é ancião dele próprio. Seja p um procedimento activo, esta foi activada por um procedimento q na árvore de activação cujo todos os anciões são activos (hipótese de indução). Agora, por razões de visibilidade, sabemos que ou q é o pai de p ou ou p é o irmão dum ancião de q. Nos dois casos todos os anciões de p estão activos. Todos os procedimentos activos têm as suas tabelas de activação reservadas em memória com todas as suas variáveis locais. Se um procedimento activa se refere a uma variável y, esta foi declarada localmente por um dos seus anciões (potencialmente por ele próprio). O grau de parentesco deste ancião é conhecido na altura da compilação. Encadeando cada tabela de activação dum procedimento p com a tabela de activação do seu pai, encontra-se facilmente seguindo o número de vezes adequadas de indirecções o local onde a variável se encontra arquivada. Exemplo: No exemplo anterior o programa pode chamar p mas não q. p pode invocar q mas q não pode invocar p. 2.4 Organização da tabela de activação Se, por suposição, o endereço do bloco de activação local é dado por um registo fp e o contador de instrução (program counter) é designado por pc então uma organização possível da tabela de activação pode ser a seguinte: 8

9 valores intermédios. var. loc. k fp + k 1. } Variáveis locais fp var. loc. 1 fp + 0 fp do procedimento pai fp-1 fp do procedimento invocador fp-2 pc na altura da chamada fp 3 param n fp 4. } Argumentos param 1 fp n 3 val. retorno fp n 4. De facto, certos valores como o valor de retorno (no caso de funções), ou até mesmo os parâmetros, são frequentemente arquivados nos registos. Passagem de parâmetros de tamanho variável Algumas linguagens, como o Pascal, autorizam a passagem por valor d argumentos de tipo vector cujo tamanho é igualmente um parâmetro. O tamanho não é então conhecido na altura da compilação. Para compilar o corpo do procedimento, decide-se de arquivar num local particular o endereço do vector. Os dados de tamanho variável podem então ser alocados no topo da pilha. Invocador-Invocado As operações por efectuar durante a invocação dum procedimento estão partilhados entre o procedimento que invoca e o procedimento invocado. O código gerado pelo invocador deve ser escrito para cada invocação enquanto o código escrito no invocado só aparece uma só vez. O invocador efectua a reserva para o valor de retorno no caso das funções e avalia os parâmetros efectivos do procedimento. Também pode se encarregar de salvaguardar o valor dos registos correntes (program counter, endereço do bloco de activação) e de calcular o endereço do bloco de activação do pai do procedimento invocador. O invocado inicializa os seus dados locais e começa a execução. Na altura do retorno, o invocado pode eventualmente colocar o resultado da avaliação num local reservado pelo invocador e restaura os registos. 3 Código Intermédio 3.1 Introdução Utiliza-se frequentemente um código intermédio independente da máquina/arquitectura alvo. Isto permite factorizar grande parte da tarefa de compilação e de tornar o compilador mais facilmente adaptável. A escolha duma linguagem intermédia é muito importante. Este deve ser suficientemente rico para permitir uma codificação confortável das operações da linguagem fonte 9

10 sem criar demasiadas longas sequências de código. Este deve ser igualmente relativamente limitado para que a implementação final não seja demasiada custosa. Vamos descrever agora as operações duma máquina com pilhas (stack based machine) particular e explicaremos a seguir como gerar o código associado a construções particulares da linguagens em questão. Notação: Descreveremos a linguagem a partir de regras gramaticais. Especificaremos uma função code que aceita como parâmetro uma árvore de sintaxe abstracta da linguagem e devolve uma sequência de instruções de código intermédio (da máquina de pilhas). Para clarificar a apresentação utilizaremos notações em sintaxe concreta para representar a sintaxe abstracta. Por exemplo se E ::= E 1 + E 2 é uma regra gramatical, escreveremos code(e1 + E2) = code(e 1 ) code(e 2 ) para especificar o valor da função code sobre a árvore de sintaxe abstracta que corresponde a soma de duas expressões. Se C 1 e C 2 representam duas sequências de instruções então C 1 C 2 representam a sequência de instrução obtida concatenando C 2 no fim de C 1. A lista vazia de instruções é representada por []. 3.2 Princípios de base duma máquina de pilhas particular Dispomos duma máquina que contém uma zona de código C, um registo pc (program counter) que contém o endereço da próxima instrução por executar. as instruções têm um nome seguido eventualmente de um ou dois argumentos. Estes argumentos serão em geral inteiros ou etiquetas (label) simbólicas indicando as instruções do código que serão traduzidas em inteiros numa fase de pre-análise. A máquina contém uma pilha P que permite arquivar valores, um registo sp (stack pointer) que aponta para para a primeira célula livre da pilha. Um outro registo gp (global pointer) aponta para para a base da pilha (local onde serão arquivados as variáveis globais). Esta pilha pode conter inteiros, flutuantes, ou endereços. Por convenção guardaremos dados de grande tamanho como as strings ou vectores num espaço suplementar. Neste caso a pilha só arquivará o endereço destes dados no referido espaço. Apresentamos, para cada instrução da máquina, as modificações por considerar no estado da pilha e dos diferentes registos. Por exemplo: Código Pilha sp pc Condição PUSHI n P [sp] := n sp + 1 pc + 1 n inteiro Significa que a linguagem intermédia possui um comando PUSHI que espera um argumento inteiro n. Se a execução deste comando tem lugar num estado em que a pilha vale P, em que o registo que aponta para o topo da pilha vale sp e o contador de instrução vale pc então a execução do referido comando resulta num estado em que o endereço sp da pilha tem o valor n e os contadores sp e pc foram incrementados de um. Esta instrução só se executa correctamente se a condições anunciadas são verificadas. No caso contrário verifica-se o despoletar de um erro de execução. 10

11 3.3 Expressões aritméticas A máquina só permite a execução de uma operação aritmética sobre os dois valores presentes no topo da pilha. Estes dois valores são, durante a execução, retiradas da pilha e o resultado da operação é colocado no topo da pilha. Código Pilha sp pc Condição ADD P [sp 2] := P [sp 2] + P [sp 1] sp 1 pc + 1 P [sp 2], P [sp 1] inteiros SUB P [sp 2] := P [sp 2] P [sp 1] sp 1 pc + 1 P [sp 2], P [sp 1] inteiros MUL P [sp 2] := P [sp 2] P [sp 1] sp 1 pc + 1 P [sp 2], P [sp 1] inteiros DIV P [sp 2] := P [sp 2]/P [sp 1] sp 1 pc + 1 P [sp 2], P [sp 1] inteiros, se divisor nulo então erro De forma similar existe um conjunto de instruções dedicadas à aritmética de flutuantes: FADD, FSUB, FMUL, FDIV e PUSHF. Comparações O valores booleanos para o resultado de comparações podem ser representados por inteiros. O inteiro 1 representará o valor verdade e 0 o falso. A igualdade corresponderá a mesma instrução, quer se fale de comparar inteiros, flutuantes ou endereços. Código Pilha sp pc Condição INF P [sp 2] := (P [sp 2] < P [sp 1])?1 : 0 sp 1 pc + 1 P [sp 2], P [sp 1] inteiros INFEQ P [sp 2] := (P [sp 2] P [sp 1])?1 : 0 sp 1 pc + 1 P [sp 2], P [sp 1] inteiros SUP P [sp 2] := (P [sp 2] > P [sp 1])?1 : 0) sp 1 pc + 1 P [sp 2], P [sp 1] inteiros SUPEQ (P [sp 2] := (P [sp 2] P [sp 1])?1 : 0) sp 1 pc + 1 P [sp 2], P [sp 1] inteiros EQUAL P [sp 2] := (P [sp 2] = P [sp 1])?1 : 0) sp 1 pc + 1 P [sp 2], P [sp 1] simultaneamente inteiros, flutuantes, endereços De forma similar a máquina disponibiliza um conjunto de instruções para flutuantes: FINF, FINFEQ, FSUP, FSUPEQ. Geração de código A representação de expressões aritméticas sob a forma binária permite gerar de forma simples código permitindo o cálculo de expressões aritméticas. O invariante por preservar descreve-se da seguinte forma: após a execução de code(e) (E expressão aritmética) a partir dum estado onde sp = n, os valores de P [m] onde m < n não foram modificados, o valor da expressão E é calculada e encontra-se em P [n] e sp = n + 1. Se supomos que as expressões aritméticas são geradas pela gramática: 11

12 E ::= inteiro E 1 + E 2 E 1 E 2 E 1 E 2 E 1 /E 2 O código correspondente é dado por: code(inteiro) code(e 1 + E 2 ) code(e 1 E 2 ) code(e 1 E 2 ) code(e 1 /E 2 ) = P U SHI inteiro = code(e 1 ) code(e 2 ) ADD = code(e 1 ) code(e 2 ) SUB = code(e 1 ) code(e 2 ) MUL = code(e 1 ) code(e 2 ) DIV 3.4 Variáveis Variáveis globais Se a linguagem fonte permite a memorisação determinados valores em variáveis então será necessário recorrer mecanismos que permitam, na máquina, o arquivo e o acesso a valores. Estes mecanismso assentam em duas instruções que permitam (a) a atribuição dum valor calculado na pilha para um espaço reservado para as variáveis globais; (b) colocar no topo da pilha de operandos um valor contida numa variável global. Se a é um endereço na pilha e n um inteiro então a + n designa o endereço localizado n céliulas acima de a. Estes dois comandos são: Código Pilha sp pc Condição PUSHG n P [sp] := P [gp + n] sp + 1 pc + 1 n inteiro, gp + n < sp STOREG n P [gp + n] := P [sp 1] sp 1 pc + 1 n inteiro, gp + n < sp O inteiro associado a cada variável id atribuído será calculado na altura da análise sintáctica ou semântica e associada ao identificador, por exemplo, dentro da tabela de símbolos e designada por adr(id). É preciso cuidar que os cálculos intermédios não removam os valores arquivados. É assim importante reservar atempadamente o espaço para todas as variáveis globais antes de iniciar os primeiros cálculos. O apontador de topo de pilha deverá inicialmente apontar para a primeira célula livre que está a seguir ao espaço reservado para as variáveis globais. Para este efeito utilizaremos uma instrução que arquiva n valores nulos (iguais a 0) na pilha. Introduz-se igualmente a instrução dual que permite fazer recuar o apontador para a pilha de n espaços para baixo, o que equivale de facto em apagar n valores da pilha. Código Pilha sp pc Condição PUSHN n P [sp + i] := 0, i.sp i < sp + n sp + n pc + 1 n inteiro POPN n sp n pc + 1 n inteiro Admitimos agora que a nossa gramática de expressões é enriquecida da seguinte forma para poder acceder às variáveis globais: O código correspondente é definido por: E ::= id code(id) = PUSHG adr(id) no caso de uma variável de tamanho unitário. Senão, se representa uma dado arquivado sobre k palavras, por: 12

13 code(id) = PUSHG adr(id) PUSHG adr(id) + 1 PUSHG adr(id) + (k 1) Consideremos agora uma linguagem cujas únicas instruções são sequências de atribuições. A análise semântica deve determinar para cada variável global id um espaço (relativamente a gp) designado por adr(id) onde o valor correspondente será arquivado. Acrescentamos um símbolo não-terminal à gramática para representar as instruções da linguagem. Extendemos a seguir a função code em conformidade. Assim, temos a gramática: e a geração de código seguinte: I ::= ɛ I ::= I 1 A; A ::= id := E code(ɛ) = [] code(i 1 A; ) = code(i 1 ) code(a) code(id := E) = code(e) STOREG adr(id) No caso dum dado codificado sobre k palavras, utilizaremos para codificar id := E as instrucções: code(e) STOREG adr(id) + (k 1) STOREG adr(id) O invariante por conservar é que o código associado a uma sequência de instruções começa e termina com um apontador de pilha por cima do conjunto dos valores globais. Vectores Em geral, o número de células da pilha nos quais um dado é representado depende do tipo do dado ( inteiro, real, vector, estrutura). Supõe-se que este tamanho é conhecido na fase de compilação e é designada por tamanho(id). Os vectores são representados por sequências de células adjacentes na pilha. Se o vector t tem índices entre m e M, começa no endereço a e contém valores de tamanho k, então este ocupa um espaço de tamanho (M m + 1) k. Para calcular o endereço correspondente a uma expressão t[e] é necessário calcular o valor de n de E e aceder ao endereço a + (n m) k. Se conhecemos o valor de m na fase de compilação então podemos avaliar parcialmente esta expressão pre-calculando a m k e arquivar este valor em t.val. Precisar-se-á posterior e simplesmente calcular t.val + n k. Os comandos PUSHG, STOREG não permitam aceder a um endereço conhecida na altura da compilação. Assim para aceder a vectores precisaremos de um acesso parametrizado por um valor calculada durante a execução. Em regra geral, o endereço ao qual precisamos de aceder depende dum endereço de base a que não é necessariamente conhecido estaticamente (caso dos vectores de tamanho variável) e dum salto (offset) n que é igualmente calculado durante a execução. Extendemos assim os comandos PUSHG, STOREG, que operavam a partir dum endereço fixo gp e dum salto estático n em argumento, em comandos LOADN e STOREN que procuram estas informações dinamicamente na pilha. 13

14 Figura 2: LOADN e STOREN Código Pilha sp pc Condição LOADN P [sp 1] := P [P [sp 2] + P [sp 1]] sp 1 pc + 1 STOREN P [P [sp 3] + P [sp 2]] := P [sp 1] sp 3 pc + 1 Podemos representar graficamente o comportamento destes dois comandos concretizando a pilha e numerando as células por inteiros k, k + 1, : ver figura 2 Podemos notar que estas instruções poderiam ser decompostas num comando que permita o acesso a um elemento da pilha via um endereço arquivado na pilha, e num comando que permita realizar cálculos sobre os endereços. Acrescentamos à nossa linguagem os vectores que supomos serem de uma só dimensão. Temos assim as duas novas produções seguintes: E ::= id[e] I ::= id[e 1 ] := E 2 Para gerar código, devemos poder colocar na pilha um endereço. Definimos assim a instrucção PUSHGP que permite arquivar o endereço do apontador global na pilha. Código Pilha sp pc Condição PUSHGP P [sp] := gp sp + 1 pc + 1 Supondo que o endereço de base onde é arquivado cada vector é conhecido, o código gerado é: code(id[e]) code(id[e 1 ] := E 2 ) = PUSHGP PUSHI adr(id) code(e) ADD LOADN = PUSHGP PUSHI adr(id) code(e 1 ) ADD code(e 2 ) STOREN Os vectores bi-dimensionais podem ser arquivados via linearização em linha ou ainda em coluna. Se cada dimensão tem por índice minimal m i, índice maximal M i e por tamanho n i = M i m i + 1, então se o arquivo é realizado em linha então teremos em primeiro o vector t[1, i] seguido de t[2, i],... O elemento t[i 1, i 2 ] é arquivado no endereço a + ((i 1 m 1 ) n 2 + (i 2 m 2 )) k Aqui também podemos pre-calcular parte da expressão re-escrevendo-a em: ((i 1 n 2 + i 2 ) k + a (m 1 n 2 + m 2 ) k 14

15 Quando encontramos uma expressão id[e 1, E 2 ] será necessário calcular o offset por aplicar a partir da base onde está arquivado id para poder aceder ao elemento designado. Podemos generalizar este processo aos vectores de dimensão p. No caso de vectores cujo tamanho não é conhecido na altura da compilação, não será possível realizar este processo de pre-compilação. Outros comandos de acesso Podemos igualmente precisar de ter acesso a um dado na pilha referenciado de forma estática, a partir dum endereço arquivado na pilha. Tal processo é possível com os comandos LOAD e STORE seguintes: Código Pilha sp pc Condição LOAD n P [sp 1] := P [P [sp 1] + n] sp pc + 1 n inteiro STORE n P [P [sp 2] + n] := P [sp 1] sp 2 pc + 1 n inteiro 3.5 Instrucções condicionais Para compilar expressões condicionais e ciclos iremos precisar de comandos de salto na zona de instrucções. As instrucções serão designadas por endereços simbólicos inseridos no código. Código Pilha sp pc Condição JUMP label sp label JZ label sp 1 (P [sp 1] = 0)?label : pc + 1 Para compilar expressões, é necessário adoptar uma convenção para a representação dos boleanos. Existem diferentes opções, podemos representar o falso por 0 e o valor verdade por qualquer inteiro positivo ou utilizar somente o valor 1. Vamos a seguir ver como gerar código para expressões condicionais e ciclos: I I I ::= if E then I endif ::= if E then I 1 else I 2 endif ::= while E do I done Introduz-se um comando suplementar na linguagem intermédio LABEL label que introduz um endereço simbólico label correspondente ao número da instrução, sem modificar o estado da pilha. Só o program counter é incrementado. Exercício: Dar um sistema de atributo para a linguagem intermédia que permite a remoção das instruções LABEL e de substituir os endereços simbólicos por endereços inteiros. code(if E then I endif) = code(e) JZ new next code(i) LABEL new next code(if E then I 1 else I 2 endif) = code(e) JZ new false code(i 1 ) JUMP new next LABEL new false code(i 2 ) LABEL new next code(while E do I done) = LABEL new loop code(e) JZ new next code(i) JUMP new loop LABEL new next Para esta compilação, é necessário criar de cada vez novas etiquetas new f alse, new next e new loop. 15

16 Compilação de expressões boleanas As expressões booleanas, digamos por exemplo E, servem frequentemente para operações de controlo. Podemos assim considerar sistematicamente duas etiquetas E true e E false e compilar a expressão boleana E sem calcular o seu valor mas decidindo que o resultado da execução de E deve se concluir em pc = E true quando E é verdade, ou em pc = E false caso contrário. Definimos então uma função code bool que aceita em parâmetro uma expressão boleana e duas etiquetas e que devolve o código de controlo. Começemos por uma gramática de expressões booleanas: O código gerado correspondente é: B ::= B 1 or B 2 B ::= B 1 and B 2 B ::= not B 1 B ::= verdade B ::= falso B ::= E 1 relop E 2 code bool(b 1 or B 2, e v, e f ) = code bool(b 1, e v, new e) LABEL new e code bool(b 2, e v, e f ) code bool(b 1 and B 2, e v, e f ) = code bool(b 1, new e, e f ) LABEL new e code bool(b 2, e v, e f ) code bool(not B 1, e v, e f ) = code bool(b 1, e f, e v ) code bool(verdade, e v, e f ) = JUMP e v code bool(falso, e v, e f ) = JUMP e f code bool(e 1 relope 2, e v, e f ) = code(e 1 ) code(e 2 ) code(relop) JZ e f JUMP e v Neste código, new e representa uma etiqueta criada para o efeito. code(relop) representa o operador relacional utilizado. Nota: Numa linguagem que possibilita os efeitos laterais nas expressões, calcular ou não as sub-expressões duma expressão booleana pode resultar em comportamentos radicalmente diferentes. Compilação de expressões com branching múltiplo Tratam-se de expressões de tipo switch, case ou match que permitam o branching múltiplo consoante os diferentes valores duma expressão parâmetro. Estes valores são geralmente de tipo numérico e conhecidos na fase de compilação. switch E begin case V 1 : S 1 case V 2 : S 2 end. case V n : S n Antes de mais devemos nos assegurar da semântica duma tal expressão. Uma semân- 16

17 tica natural é: if E = V 1 then S 1 else if E = V 2 then S 2. else if E = V n then S n Não é, no entanto, a semântica da instrução switch da linguagem C. Nesta linguagem executa-se todas as instruções S i ;... ; S n a partir do primeiro i tal que E = V i. É a presença duma instrução break num S i que permite a saída do switch. if E = V 1 then goto l 1 elseif E = V 2 then goto l 2. elseif E = V n then goto l n l 1 : S 1. l n : break : Podemos optimizar a compilação se os valores dos v i são todos distintos num intervalo [k + 1, k + n]. Cria-se então no código uma tabela de branching que se inicia por LABEL inicio e que integra sucessivamente as instruções JUMP l 1,..., JUMP l n. Seguem-se então o código de cada ramo da estrutura condicional LABEL l i code(s i ), seguida eventualmente duma instrucção JUMP f im. É desta forma necessário dispor duma instrução de salto indexado que notaremos JUMPI. Esta instrução aceita uma etiqueta e devolve o controlo à instrução cujo número é o valor numérico da etiqueta mais o valor do topo da pilha. Código Pilha sp pc Condição JUMPI label sp 1 label + P [sp 1] Insere-se então o código de E : code(e) do qual é necessário subtrair a constante k : PUSHI k SUB. Testa-se se o valor obtido está entre 1 e n e efectua-se o branching indexado correspondente, senão a instrução é ignorada. Como o valor no topo da pilha deve ser utilizada para duas comparações e o salto indexado, é preciso utilizá-la 3 vezes e, por isso, duplicá-lo deu as vezes com a ajuda da instrução DUP. Obtém-se o código seguinte: S n DUP DUP PUSHI n INFEQ JZ f im PUSHI 1 SUPEQ JZ f im JUMPI inicio LABEL fim Exercício: Modificar o esquema para o caso em que a intrucção switch inclua um caso por defeito. 3.6 Invocar procedimentos A invocação de procedimentos tem dois efeitos. O primeiro é de modificar o decorrer sequencial da execução, o segundo é de criar um espaço para os dados locais. 17

18 Sub-rotinas Imaginemos que queremos reutilizar em vários locais a mesma porção de código I. Para tal isola-se I e atribuimo-lhe uma etiqueta. Podemos então substituir todas as cópias de I por uma instrução de salto para I. O problema é conseguir voltar de I para o bom local (a instrução que segue o salto para I) e proceder ao resto da execução. Se temos várias utilizações da rotina então não podemos colocar simplesmente uma instrução de salto estático. É assim necessário, antes do salto para I, arquivar o valor do apontador de programa ( o valor do registo pc, program counter) e restaura-lo no fim da execução de I. Como as chamadas a sub-rotinas podem ser aninhadas, é necessário tornar possível o arquivo dum número arbitrário de tais valores. Esta informação poderia ser guardada na pilha de operandos, mas a máquina que utilizamos aqui tem uma pilha especialmente dirigida ao processamento deste tipo de informação. As instruções CALL e RETURN permitam o correcto processamento do apontador de programa. A instrução CALL toma em parâmetro um endereço no código. O contador de instrução coloca-se então na posição especificada sendo o seu antigo valor arquivado. A instrução RETURN descobre o antigo valor do apontador de programa e atribuí-lhe o valor seguinte (isto é, aponta agora para a instrucção que segue). Acrescenta-se então à linguagem definições e invocação de sub-rotinas: D ::= proc p; begin I end I ::= call p code(proc p; begin I end) = LABEL label p code(i) RETURNcode(call p) = CALL label p label p é uma etiqueta única associada ao pocedimento p. Procedimentos com parâmetros Se o procedimento tem parâmetros então o papel deste procedimento é permitir a gestão na pilha do espaço necessário para estes parâmetros (reserva e acesso). Como só se consegue fazer referência a células da pilha a partir do endereço de base, é necessário dispor dum registo suplementar f p que será actualizado ao início da invocação do procedimento e que permitirá referenciar os valores locais. Na saída do procedimento este espaço deverá ser liberto. A chamada e o retorno dos procedimentos pode ser percebido como uma modificação do valor de pc e da atribuição dum endereço de base para as variáveis locais. No momento do retorno do procedimento, o valor de pc deve ser incrementado de 1 e o valor de fp restituída ao valor que tinha antes da invocação, visto as chamadas poderem ser aninhadas. A pilha ficará truncada de toda a parte alocada a seguir à chamada do procedimento. O papel dos comandos CALL e RETURN será exactamente assegurar o correcto arquivo de fp e pc. Instrucções de manipulação de dados locais A linguagem contém instruções para manipular dados referenciadas a partir do apontador f p. Às instruções PUSHGP, STOREG, PUSHG correspondem as instruções PUSHFP, STOREL, PUSHL que têm o mesmo comportamento só que sobre fp e não sobre gp. 18

19 Tabela de activação No caso de uma alocação estática, a tabela de activação será constituído (a) dos parâmetros do procedimento que serão instanciados no momento da chamada (b) do endereço da tabela de activação do procedimento chamadora (c) do local para as variáveis locais. A gramática para as declarações tem a forma seguinte: D s ::= D s D; ɛ D ::= var id : T proc id(d s ) D s begin I end fun id(ds) : T D s E Podemos calcular, por exemplo, por atributos, o nível de cada símbolos de procedimentos, função ou variável, que é o número de procedimentos ou funções sob o qual este se encontra definido. Este valor corresponde a profundidade do símbolo na árvore de declarações. O programa principal tem um nível igual a 0. O offset associada a uma variável é o inteiro que se deve adicionar a fp para obter o endereço de base da variável. Exercício: Definir um sistema de atributos para calcular os níveis e offset das declarações. No momento duma chamada por valor de q(e 1,..., e n ), temos de calcular o código de e 1,..., e n que serão empilhados, como também temos de calcular o endereço da tabela de activação do invocador. Para tal olhamos para os níveis respectivos de q e do procedimento p que chamou q. O dado importante aqui é o nível relativo n que é igual ao nível de p menos o nível de q e que é sempre maior ou igual a 1 (= 1 quando q é declarado dentro de p). Calculo do endereço do vector de activação pai Quando p chama q então o cálculo do endereço do pai de q faz-se pela sequencial de instrução seguinte: PUSHFP LOAD 1 } {{ } n+1 vezes Podemos notar que a sequência de instrução PUSHFP LOAD n é equivalente a PUSHL n Quando este registo é actualizado, podemos executar a invocação com o comando CALL q. O início deste procedimento deve reservar o espaço para as variáveis locais seguida da execução do código. No fim da execução do procedimento, o comando RETURN é invocada. Esta removerá da pilha os valores locais mas não os parâmetros. O invocador poderá então retirar da pilha os parâmetros assim como o endereço do pai. Se o procedimento é uma função que retorna um valor, então a localização deste último deverá ser devidamente reservado antes da chamada do procedimento. Escolhe-se normalmente a utilização do primeiro espaço livre da pilha. Cálculo do acesso a uma variável Se dentro dum procedimento p se pretende aceder a uma variável x calcula-se ainda uma diferença n entre o nível np de p e nx, o nível de x, que é superior a 1. Conhece-se a offset dx de x. O código para aceder ao valor direito de x é assim parametrizado pelo nível np do procedimento dentro do qual se está: code var(x, np) = PUSHFP } LOAD {{ 1 } LOAD dx np nx+1 vezes 19

20 Passagem de parâmetros por valor No modo de passagem por valor teremos a compilação de corpos de procedimentos seguinte: code(proc id(d s1 ) D s2 begin I end) = LABEL label id PUSHN tamanho(d s2 ) code(i) RETURN A invocação faz-se pelos comandos seguintes: LE ::= E LE, E A ::= call id(le) A geração de código duma sequência de expressão é assim somente a concatenação dos diferentes códigos. O código associado à invocação dum procedimento q de nível pq é parametrizada pelo nível np do procedimento invocador: code call(call q(le), np) = code(le) PUSHFP LOAD } {{ 1 } np nq+1 vezes CALL label id POP tamanho(le) + 1 Exercício: Escrever o código de compilação e de invocação duma função. Passagem de parâmetros por referência No lugar de empilhar os valores das expressões, empilha-se os seus valores esquerdos (isto é endereços). Os acessos às variáveis fazem-se então via uma indirecção. Passagem duma função em parâmetro Para compilar um procedimento que aceita uma função em parâmetro, são necessários duas informações: o endereço da função e o endereço do vector de activação do pai do procedimento. Exemplo program main procedure b(function h(n:int):inte); begin print(h(2)) end procedure c; var m:int; function f(n:int) : int; begin f:=m+n end begin m:=0; b(f) end begin c end Para executar o código do procedimento é necessário conhecer o endereço do código deste procedimento assim como o endereço da tabela de activação do procedimento. Quando c deve executar b(f), este calcula a ligação de activação du pai estático de f (aqui c) como se este o chamasse e passa-o a b que poderá o utilizar na altura da invocação de f. 20

21 Retornar uma função como valor Algumas linguagens permitam devolver funções como valores. No entanto se a linguagem autoriza o acesso a variáveis não locais, o problema que se coloca é o da persistência dos valores assim manipulados. Exemplo let f(x) = let g(y) = x+y in g let h = f(3) let j = f(4) h(5)+j(7) O valor duma função é designado de fecho (closure) e é formada por um apontador para o seu código assim como por um ambiente que associa valores a todas as variáveis utilizadas no corpo da função e que não são locais na altura da definição da função. 4 Utilização de registos Os registos permitan arquivar informações e manipula-las de forma rápida. No entanto estes registos existam normalmente em número pequeno. Convêm assim geri-los da melhor forma. Uma forma de o fazer é de introduzir para cada valor intermédio uma nova variável e de construir um grafo de interferência: os nodos são as variáveis e temos um arco entre x e y se x e y não podem ser arquivados no mesmo registo (i.e. as duas variáveis estão vivas na mesma altura). Podemos igualmente considerar os registos como os nodos deste grafo e ligar a existência dos arcos como o facto de certos valores não poderem ser arquivados no registo particular. Assim, determinar uma repartição das variáveis sobre k registos resume-se em encontrar uma k-coloração do grafo. Visto este problema ser NP-Completo em geral, utiliza-se uma aproximação. Se este grafo é vazio, então a coloração é evidente. Se o grafo contempla um nodo x de grau estritamente inferior a k então constroi-se um novo grafo G removendo este nodo e as arestas correspondentes. Se G pode ser colorido então podemos encontrar uma cor para x, diferente de todos os seus vizinhos e acrescenta-lo. Nota-se que remover x de G pode diminuir o grau de outros nodos e tornar assim a coloração possível. Se o grafo só comporta nodos de grau superior a k então escolhe-se e remove-se um nodo x e procura-se colorir o grafo resultante. Se for possível, olha-se para o número de cores utilizadas para colorir os vizinhos de x. Se existe uma cor disponível então é possível colorir x e este é de novo acrescentado ao grafo, senão a coloração não é possível e x tem de ser arquivado na memória. Para tal escolhe-se um espaço m x para arquivar x e introduz-se para cada utilização de x uma nova variável x i. Se o valor de x é utilizado numa expressão, começamos por colocar em x i o valor arquivado no endereço m x da memória. Se x é actualizada então substitua-se x por x i e propaga-se esta instrução de actualização de m x na memória pelo valor de x i. A duração de vida das variáveis x i é pequena, estas não interfiram com as outras variáveis. É necessário modificar o grafo de interferência e recomeçar a coloração. O grafo de interferência pode igualmente ser utilizado para remover as instruções move entre registos 21

22 associadas a instruções x := y. Podemos identificar x e y desde que x e y não são vivas simultaneamente. No entanto, esta identificação terá como resultados o aumento do grau do nodo xy (resultado da identificação entre x e y), o que poderá fazer com que a colorização falhe. Efectuar uma deslocação nos registos é menos custoso do que um acesso à memória. Assim far-se-á a identificação só em alturas em que se consegue guarantir a preservação da colorização. É o caso quando o conjunto de vizinhos de xy contempla têm estritamente menos de k nodos de grau inferior a k. Exemplo (A. Appel) Considere-se o programa seguinte formado de atribuições simples e de acessos à memória. Indicamos na segunda coluna o conjunto de variáveis simultaneamente vivas no ponto de programa anterior, sabendo que após a execução deste código as variáveis d, k e j são vivas. Instrucções Variáveis Vivas g := mem [j+12] k, j h := k - 1 j, g, k f := g * h j, g, h e := mem[j+8] j, f m := mem[j+16] j, f, e b := mem[f] m, f, e c := e+8 m, b, e d := c m, b, c k := m+4 m, b, d j := b b, d, k d, k, j Podemos olhar para os nodos do grafo nesta ordem: m, c, b, f, e, j, d, k, h e g. e constatamos que em cada instante cada nodo tem um grau inferior ou igual a 3. Podemos assim realizar uma colorização com 4 cores e obtemos por exemplo a atribuição de cores seguintes: m = 1, c = 2, b = 34,f = 24, e = 4, j = 3, d = 4, k = 1, h = 1 e g = 2. Se dispúnhamos só de 3 registos, poderíamos recomeçar a análise com os nodos na ordem seguinte (os nodos em negrito são os que tem um grau superior a 3 e que podem assim colocar problemas): b, d, j, e, f, m, k, g, c e h. Uma tentativa ed coloração pode ser: b = 1, d = 2, j = 1, e = 2, f = 3, m, k, g, c e h não permitam a coloração de m. Podemos então escolher arquivar m na memória no endereço M. Devemos assim transformar o programa: 22

23 Instrucções Variáveis Vivas g := mem [j+12] k, j h := k - 1 j, g, k f := g * h j, g, h e := mem[j+8] j, f m 1 := mem[j+16] j, f, e mem[m] := m 1 m 1, f, e b := mem[f] f, e c := e+8 b, e d := c b, c m 2 := mem[m] b, d k := m 2 +4 m 2, b, d j := b b, d, k d, k, j O nodo m de grau 5 transformou-se em dois nodos m 1 e m 2 de grau 2. Podemos examinar de novo os nodos do novo grafo na ordem seguinte: h, c, m 2, m 1, f, e, b, d, k, ge j e não permanecem mais dificuldades. Este tipo de mecanismo de colorização pode igualmente ser utilizado para minimizar o número de espaços memória utilizados no arquivo em memória das variáveis. O objectivo será assim a minimização do número de move mesmo se isto aumente o número de células memória utilizada. 5 Alocação na Heap Na codificação que acabamos de abordar, os novos valores por calcular ao longo da execução são alocados na pilha. Este princípio funciona porque o que é alocado durante a invocação deixa de ser acessível no fim do procedimento. Este princípio não consegue cobrir todos os casos possíveis. Por exemplo, se a linguagem permite retornar valores funcionais, então vimos que o valor devolvido deve conter uma representação do ambiente no qual a função se encontra definida. Este ambiente que deve sobreviver ao fim do procedimento que a define incluí no entanto valores alocados na tabela de activação do procedimento definidor. 5.1 Representação de Dados Estruturados No exemplos anteriores, alocamos para cada variável um espaço correspondente ao tamanho do referido dado. Assim a passagem de vectores em parâmetros necessita que sejam alvos de cópia. Seria mais eficiente manipular os objectos de tamanho importante pelo intermédio dos seus endereços. No caso dos vectores em OCaml, por exemplo, existe um momento em que o vector é criado (por exemplo, explicitamente por [ 1; 2; 3 ] ou via o comando Array.create) e um valor do tipo vector é simplesmente o endereço dum vector. Naturalmente o vector pode ser alocado no corpo duma função e ser devolvido como resultado da função. Neste caso é necessário que este seja alocado numa zona de dados persistente. Alocar tais dados na zona das variáveis globais não é de todo uma boa ideia. 23

Programação Estruturada. Programação Estruturada. Idéias Básicas da Programação Estruturada

Programação Estruturada. Programação Estruturada. Idéias Básicas da Programação Estruturada Programação Estruturada Programação Estruturada Paradigmas de Linguagens de Programação As linguagens desse paradigma são muitas vezes chamadas de linguagens convencionais, procedurais ou imperativas.

Leia mais

Máquina virtual para o projecto da disciplina de compiladores. 1 Descrição. 1.1 Organização da máquina. 11 de Setembro de 2006

Máquina virtual para o projecto da disciplina de compiladores. 1 Descrição. 1.1 Organização da máquina. 11 de Setembro de 2006 Máquina virtual para o projecto da disciplina de compiladores 11 de Setembro de 2006 Este documento é a tradução da documentação original fornecida com as fontes da máquina virtual aqui descrita. 1 1.1

Leia mais

CAPÍTULO 2. Grafos e Redes

CAPÍTULO 2. Grafos e Redes CAPÍTULO 2 1. Introdução Um grafo é uma representação visual de um determinado conjunto de dados e da ligação existente entre alguns dos elementos desse conjunto. Desta forma, em muitos dos problemas que

Leia mais

INTRODUÇÃO À LINGUAGEM C++

INTRODUÇÃO À LINGUAGEM C++ INTRODUÇÃO À LINGUAGEM C++ 1 - VARIÁVEIS Variáveis espaço de memória reservado para armazenar tipos de dados, com um nome para referenciar seu conteúdo. Observações importantes Todas as variáveis devem

Leia mais

TÉCNICAS DE PROGRAMAÇÃO

TÉCNICAS DE PROGRAMAÇÃO TÉCNICAS DE PROGRAMAÇÃO (Adaptado do texto do prof. Adair Santa Catarina) ALGORITMOS COM QUALIDADE MÁXIMAS DE PROGRAMAÇÃO 1) Algoritmos devem ser feitos para serem lidos por seres humanos: Tenha em mente

Leia mais

ARQUITECTURA DE COMPUTADORES CAPÍTULO II AULA X

ARQUITECTURA DE COMPUTADORES CAPÍTULO II AULA X ARQUITECTURA DE COMPUTADORES CAPÍTULO II AULA X Índice Traduzindo e iniciando uma aplicação Compiladores Assembladores Linkers Loaders DLLs Iniciando um programa em Java Após toda a matéria abordada nesta

Leia mais

9 Comandos condicionais

9 Comandos condicionais 9 Comandos condicionais Um comando condicional é uma instrução empregada quando se deseja criar um desvio, isto é, a opção de executar-se ou não um determinado trecho de código, segundo uma condição. Em

Leia mais

Algoritmos e Estruturas de Dados I 01/2013. Estruturas Condicionais e de Repetição (parte 2) Pedro O.S. Vaz de Melo

Algoritmos e Estruturas de Dados I 01/2013. Estruturas Condicionais e de Repetição (parte 2) Pedro O.S. Vaz de Melo Algoritmos e Estruturas de Dados I 01/2013 Estruturas Condicionais e de Repetição (parte 2) Pedro O.S. Vaz de Melo Problema 1 Suponha que soma (+) e subtração (-) são as únicas operações disponíveis em

Leia mais

5 - Vetores e Matrizes Linguagem C CAPÍTULO 5 VETORES E MATRIZES

5 - Vetores e Matrizes Linguagem C CAPÍTULO 5 VETORES E MATRIZES CAPÍTULO 5 5 VETORES E MATRIZES 5.1 Vetores Um vetor armazena uma determinada quantidade de dados de mesmo tipo. Vamos supor o problema de encontrar a média de idade de 4 pessoas. O programa poderia ser:

Leia mais

1. SINTAXE DA LINGUAGEM ASSEMBLY

1. SINTAXE DA LINGUAGEM ASSEMBLY 1. SINTAXE DA LINGUAGEM ASSEMBLY Antes de se escrever em assembly, é conveniente construir um fluxograma do programa. Um fluxograma não faz referência à linguagem a utilizar, pelo que pode ser utilizado

Leia mais

Filas. A ordem de saída corresponde diretamente à ordem de entrada dos elementos. Fila de caixa bancário

Filas. A ordem de saída corresponde diretamente à ordem de entrada dos elementos. Fila de caixa bancário Filas Fila é um tipo de lista linear onde as inserções são realizadas num extremo (final da Fila) e as remoções restritas ao outro (começo da Fila). O primeiro a entrar é o primeiro a sair e último a entrar

Leia mais

4.1. UML Diagramas de casos de uso

4.1. UML Diagramas de casos de uso Engenharia de Software 4.1. UML Diagramas de casos de uso Nuno Miguel Gil Fonseca nuno.fonseca@estgoh.ipc.pt Utilizados para ajudar na análise de requisitos Através da forma como o utilizador usa o sistema

Leia mais

Programação. MEAer. Bertinho Andrade da Costa. Instituto Superior Técnico. Introdução ao Pré-Processador. 2011/2012 1º Semestre

Programação. MEAer. Bertinho Andrade da Costa. Instituto Superior Técnico. Introdução ao Pré-Processador. 2011/2012 1º Semestre Programação MEAer Bertinho Andrade da Costa 2011/2012 1º Semestre Instituto Superior Técnico Introdução ao Pré-Processador Programação 2011/2012 DEEC-IST Introdução ao Pré-Processador 1 Sumário Introdução

Leia mais

Informática de Gestão 1º ano / 1º semestre Ano letivo: 2014/2015. Visual Basic VBA

Informática de Gestão 1º ano / 1º semestre Ano letivo: 2014/2015. Visual Basic VBA Informática de Gestão 1º ano / 1º semestre Ano letivo: 2014/2015 Visual Basic VBA Macros Funções Conjunto de instruções que são executadas sempre que se desejar e pela ordem apresentada As funções são

Leia mais

Regras Métodos Identificadores Variáveis Constantes Tipos de dados Comandos de atribuição Operadores aritméticos, relacionais e lógicos

Regras Métodos Identificadores Variáveis Constantes Tipos de dados Comandos de atribuição Operadores aritméticos, relacionais e lógicos Lógica Aula 2 Técnicas de Programação Criando algoritmos Regras Métodos Identificadores Variáveis Constantes Tipos de dados Comandos de atribuição Operadores aritméticos, relacionais e lógicos Criando

Leia mais

Capítulo SETE Números em Ponto Fixo e Ponto Flutuante

Capítulo SETE Números em Ponto Fixo e Ponto Flutuante Capítulo SETE Números em Ponto Fixo e Ponto Flutuante 7.1 Números em ponto fixo Observação inicial: os termos ponto fixo e ponto flutuante são traduções diretas dos termos ingleses fixed point e floating

Leia mais

Tabela de Símbolos. Análise Semântica A Tabela de Símbolos. Principais Operações. Estrutura da Tabela de Símbolos. Declarações 11/6/2008

Tabela de Símbolos. Análise Semântica A Tabela de Símbolos. Principais Operações. Estrutura da Tabela de Símbolos. Declarações 11/6/2008 Tabela de Símbolos Análise Semântica A Tabela de Símbolos Fabiano Baldo Após a árvore de derivação, a tabela de símbolos é o principal atributo herdado em um compilador. É possível, mas não necessário,

Leia mais

Laboratório de Banco de Dados II Aula 1. Stored Procedures

Laboratório de Banco de Dados II Aula 1. Stored Procedures Laboratório de Banco de Dados II Aula 1 Stored Procedures Stored procedures Uma seqüência de comandos SQL pode ser agrupada, formando uma stored procedure A sua execução é comandada, invocando-se o nome

Leia mais

Tarefa Orientada 18 Procedimentos armazenados

Tarefa Orientada 18 Procedimentos armazenados Tarefa Orientada 18 Procedimentos armazenados Objectivos: Criar Procedimentos armazenados Chamar procedimentos armazenados Utilizar parâmetros de entrada e de saída Um procedimento armazenado representa

Leia mais

Aula 14: Instruções e Seus Tipos

Aula 14: Instruções e Seus Tipos Aula 14: Instruções e Seus Tipos Diego Passos Universidade Federal Fluminense Fundamentos de Arquiteturas de Computadores Diego Passos (UFF) Instruções e Seus Tipos FAC 1 / 35 Conceitos Básicos Diego Passos

Leia mais

Linguagem de Montagem 2. Operações e Operandos

Linguagem de Montagem 2. Operações e Operandos Linguagem de Montagem 2 Operações e Operandos Revisão Para executar uma tarefa qualquer, um computador precisa receber instruções precisas sobre o que fazer Esse conjunto de instruções chamamos de algoritmo

Leia mais

4.4. UML Diagramas de interacção

4.4. UML Diagramas de interacção Engenharia de Software 4.4. UML Diagramas de interacção Nuno Miguel Gil Fonseca nuno.fonseca@estgoh.ipc.pt Um diagrama de interacção mostra um padrão de interacção entre vários objectos, com objectos e

Leia mais

Implementando uma Classe e Criando Objetos a partir dela

Implementando uma Classe e Criando Objetos a partir dela Análise e Desenvolvimento de Sistemas ADS Programação Orientada a Obejeto POO 3º Semestre AULA 04 - INTRODUÇÃO À PROGRAMAÇÃO ORIENTADA A OBJETO (POO) Parte: 2 Prof. Cristóvão Cunha Implementando uma Classe

Leia mais

CONCEITOS BÁSICOS PARA A CONSTRUÇÃO DE ALGORITMOS PARA COMPUTADORES. Isac Aguiar isacaguiar.com.br isacaguiar@gmail.com

CONCEITOS BÁSICOS PARA A CONSTRUÇÃO DE ALGORITMOS PARA COMPUTADORES. Isac Aguiar isacaguiar.com.br isacaguiar@gmail.com CONCEITOS BÁSICOS PARA A CONSTRUÇÃO DE ALGORITMOS PARA COMPUTADORES Isac Aguiar isacaguiar.com.br isacaguiar@gmail.com Objetivos Compreender os conceitos de lógica de programação e de algoritmos. Conhecer

Leia mais

Estrutura de Dados Básica

Estrutura de Dados Básica Estrutura de Dados Básica Professor: Osvaldo Kotaro Takai. Aula 4: Tipos de Dados O objetivo desta aula é apresentar os tipos de dados manipulados pela linguagem C, tais como vetores e matrizes, bem como

Leia mais

Notas de Cálculo Numérico

Notas de Cálculo Numérico Notas de Cálculo Numérico Túlio Carvalho 6 de novembro de 2002 2 Cálculo Numérico Capítulo 1 Elementos sobre erros numéricos Neste primeiro capítulo, vamos falar de uma limitação importante do cálculo

Leia mais

Especificação Operacional.

Especificação Operacional. Especificação Operacional. Para muitos sistemas, a incerteza acerca dos requisitos leva a mudanças e problemas mais tarde no desenvolvimento de software. Zave (1984) sugere um modelo de processo que permite

Leia mais

Técnicas de Computação Paralela Capítulo III Design de Algoritmos Paralelos

Técnicas de Computação Paralela Capítulo III Design de Algoritmos Paralelos Técnicas de Computação Paralela Capítulo III Design de Algoritmos Paralelos José Rogado jose.rogado@ulusofona.pt Universidade Lusófona Mestrado Eng.ª Informática e Sistemas de Informação 2013/14 Resumo

Leia mais

Folha de Cálculo TECNOLOGIAS DA T IINF CO RM 1 A 0 ÇÃO E COMUNICAÇÃO TIC 10

Folha de Cálculo TECNOLOGIAS DA T IINF CO RM 1 A 0 ÇÃO E COMUNICAÇÃO TIC 10 Folha de CálculoC TECNOLOGIAS DA TIC INFORMAÇÃO 10 E COMUNICAÇÃO TECNOLOGIAS DA INFORMAÇÃO E COMUNICAÇÃO INTRODUÇÃO À Exemplo Era uma vez um profissional de saúde que tinha 20 doentes de quem recolhia

Leia mais

Capítulo 7 Nível da Linguagem Assembly

Capítulo 7 Nível da Linguagem Assembly Capítulo 7 Nível da Linguagem Assembly Presente em quase todos os computadores modernos. Implementado por tradução. Linguagem fonte => Linguagem alvo. O programa no arquivo fonte não é executado diretamente

Leia mais

Linguagem e Técnicas de Programação I Tipos de dados, variáveis e constantes. Prof. MSc. Hugo Souza Material desenvolvido por: Profa.

Linguagem e Técnicas de Programação I Tipos de dados, variáveis e constantes. Prof. MSc. Hugo Souza Material desenvolvido por: Profa. Linguagem e Técnicas de Programação I Tipos de dados, variáveis e constantes Prof. MSc. Hugo Souza Material desenvolvido por: Profa. Ameliara Freire Tipos de dados Os programas manipulam dados, armazenando-os

Leia mais

Programação I. Departamento de Engenharia Rural Centro de Ciências Agrárias

Programação I. Departamento de Engenharia Rural Centro de Ciências Agrárias Departamento de Engenharia Rural Centro de Ciências Agrárias Programação I Prof. Bruno Vilela Oliveira bruno@cca.ufes.br http://www.brunovilela.webnode.com.br Aulas 2-3-4-5-6-7-8 Lógica Algoritmos Portugol

Leia mais

UNIDADE 6 - PROGRAMAÇÃO MODULAR

UNIDADE 6 - PROGRAMAÇÃO MODULAR UNIDADE 6 - PROGRAMAÇÃO MODULAR Até o momento as estruturas de controle (seqüência, seleção e repetição) de um algoritmo definia-o como um bloco lógico (início e fim). À medida que os problemas a serem

Leia mais

Manual do Gestor da Informação do Sistema

Manual do Gestor da Informação do Sistema Faculdade de Engenharia da Universidade do Porto Licenciatura Informática e Computação Laboratório de Informática Avançada Automatização de Horários Manual do Gestor da Informação do Sistema João Braga

Leia mais

Conjunto de instruções e modos de. aula 4. Profa. Débora Matos

Conjunto de instruções e modos de. aula 4. Profa. Débora Matos Conjunto de instruções e modos de endereçamento aula 4 Profa. Débora Matos Conjunto de Instruções A = ((B + C) x D + E F)/(G x H) A H denotam posições da memória endereços As arquiteturas possuem as seguintes

Leia mais

c. Técnica de Estrutura de Controle Teste do Caminho Básico

c. Técnica de Estrutura de Controle Teste do Caminho Básico 1) Defina: a. Fluxo de controle A análise de fluxo de controle é a técnica estática em que o fluxo de controle através de um programa é analisado, quer com um gráfico, quer com uma ferramenta de fluxo

Leia mais

Capítulo 7. Topologia Digital. 7.1 Conexidade

Capítulo 7. Topologia Digital. 7.1 Conexidade Capítulo 7 Topologia Digital A Topologia Digital estuda a aplicação das noções definidas em Topologia sobre imagens binárias. Neste capítulo vamos introduzir algumas noções básicas de Topologia Digital,

Leia mais

Nível da Arquitetura do Conjunto das Instruções

Nível da Arquitetura do Conjunto das Instruções Nível da Arquitetura do Conjunto das Instruções (Aula 13) Fluxo de Controle Fluxo Seqüencial de Controle e Desvios (1) Fluxo de Controle: É a seqüência na qual instruções são dinamicamente executadas Isto

Leia mais

Complexidade de Algoritmos

Complexidade de Algoritmos Complexidade de Algoritmos Complexidade de Algoritmos Envolvendo Estruturas de Dados Elementares Prof. Osvaldo Luiz de Oliveira Estas anotações devem ser complementadas por apontamentos em aula. Vetor

Leia mais

UML (Unified Modelling Language) Diagrama de Classes

UML (Unified Modelling Language) Diagrama de Classes UML (Unified Modelling Language) Diagrama de Classes I Classes... 2 II Relações... 3 II. Associações... 3 II.2 Generalização... 9 III Exemplos de Modelos... III. Tabelas de IRS... III.2 Exames...3 III.3

Leia mais

Possui como idéia central a divisão de um universo de dados a ser organizado em subconjuntos mais gerenciáveis.

Possui como idéia central a divisão de um universo de dados a ser organizado em subconjuntos mais gerenciáveis. 3. Tabelas de Hash As tabelas de hash são um tipo de estruturação para o armazenamento de informação, de uma forma extremamente simples, fácil de se implementar e intuitiva de se organizar grandes quantidades

Leia mais

Introdução à Programação. Armazenamento de Grande Quantidade de Informação Usando Vetores

Introdução à Programação. Armazenamento de Grande Quantidade de Informação Usando Vetores Introdução à Programação Armazenamento de Grande Quantidade de Informação Usando Vetores Armazenando Grande Quantidade de Informação Como armazenar tanta informação? Vetores! 2 Tópicos da Aula Hoje, aprenderemos

Leia mais

3 Estratégia para o enriquecimento de informações

3 Estratégia para o enriquecimento de informações 34 3 Estratégia para o enriquecimento de informações Podemos resumir o processo de enriquecimento de informações em duas grandes etapas, a saber, busca e incorporação de dados, como ilustrado na Figura

Leia mais

Visão Artificial Para a Indústria. Manual do Utilizador

Visão Artificial Para a Indústria. Manual do Utilizador Visão Artificial Para a Indústria Manual do Utilizador Luis Fonseca Carvalho de Matos ( luis.matos@ua.pt ) Julho de 2007 Índice de conteúdos 1. Apresentação......1 1.Conceito de Funcionamento......1 2.

Leia mais

Hugo Pedro Proença, 2007

Hugo Pedro Proença, 2007 Stored Procedures À medida que a complexidade dos sistemas aumenta, torna-se cada vez mais difícil a tarefa de integrar o SQL com as aplicações cliente. Além disto, é necessário que todas as aplicações

Leia mais

Algoritmos e Programação

Algoritmos e Programação Universidade Federal do Vale do São Francisco Curso de Engenharia da Produção / Elétrica Algoritmos e Programação Parte 05 Prof. Jorge Cavalcanti jorge.cavalcanti@univasf.edu.br www.univasf.edu.br/~jorge.cavalcanti

Leia mais

Classificação e Pesquisa de Dados

Classificação e Pesquisa de Dados Classificação e Pesquisa de Dados Aula 20 Árvores B e B+ B-Trees (Árvores B) [Bayer & McCreight 1970] UFRGS INF01124 B-Trees (Árvores B) Árvores de pesquisa balanceadas, projetadas para minimizar o tempo

Leia mais

Orientação a Objetos

Orientação a Objetos 1. Domínio e Aplicação Orientação a Objetos Um domínio é composto pelas entidades, informações e processos relacionados a um determinado contexto. Uma aplicação pode ser desenvolvida para automatizar ou

Leia mais

Linguagem de Programação JAVA. Técnico em Informática Professora Michelle Nery

Linguagem de Programação JAVA. Técnico em Informática Professora Michelle Nery Linguagem de Programação JAVA Técnico em Informática Professora Michelle Nery Agenda Regras paravariáveis Identificadores Válidos Convenção de Nomenclatura Palavras-chaves em Java Tipos de Variáveis em

Leia mais

Computadores de Programação (MAB353)

Computadores de Programação (MAB353) Computadores de Programação (MAB353) Aula 7: 29 de abril de 2010 1 2 Subrotinas Um procedimento ou função é uma subrotina armazenada que executa uma tarefa específica baseada nos parâmetros de entrada

Leia mais

Base de dados I. Uma base de dados é um simples repositório de informação relacionado com um determinado assunto ou finalidade

Base de dados I. Uma base de dados é um simples repositório de informação relacionado com um determinado assunto ou finalidade Base de dados I O que é? Uma base de dados é um simples repositório de informação relacionado com um determinado assunto ou finalidade Para que serve? Serve para gerir vastos conjuntos de informação de

Leia mais

CAPÍTULO 7 NÍVEL DE LINGUAGEM DE MONTAGEM

CAPÍTULO 7 NÍVEL DE LINGUAGEM DE MONTAGEM CAPÍTULO 7 NÍVEL DE LINGUAGEM DE MONTAGEM 71 Introdução Difere dos níveis inferiores por ser implementado por tradução A tradução é usada quando um processador está disponível para uma mensagem fonte mas

Leia mais

Conceitos básicos da linguagem C

Conceitos básicos da linguagem C Conceitos básicos da linguagem C 2 Em 1969 Ken Thompson cria o Unix. O C nasceu logo depois, na década de 70. Dennis Ritchie, implementou-o pela primeira vez usando o sistema operacional UNIX criado por

Leia mais

APROG - Civil. Excel. Técnicas de pesquisa de informação em tabelas. Instituto Superior de Engenharia do Porto 2000-2007

APROG - Civil. Excel. Técnicas de pesquisa de informação em tabelas. Instituto Superior de Engenharia do Porto 2000-2007 APROG - Civil Excel Técnicas de pesquisa de informação em tabelas Instituto Superior de Engenharia do Porto 2000-2007 Elaborado por: António Silva (DEI-ISEP) Pesquisa de Informação em Tabelas O Excel

Leia mais

E/S CPU. Memória (Instruções e dados) 2 PARADIGMA IMPERATIVO. Instruções e dados. Resultados das operações. Unidade lógica e aritmética

E/S CPU. Memória (Instruções e dados) 2 PARADIGMA IMPERATIVO. Instruções e dados. Resultados das operações. Unidade lógica e aritmética 2 PARADIGMA IMPERATIVO 2.1 CONCEITO As linguagens que pertencem ao paradigma imperativo tomam por base a perspectiva da máquina. Ou seja, no modo como o computador executa programas em linguagem de máquina.

Leia mais

Tarefa 18: Criar Tabelas Dinâmicas a partir de Listas de Excel

Tarefa 18: Criar Tabelas Dinâmicas a partir de Listas de Excel Tarefa 18: Criar Tabelas Dinâmicas a partir de 1. Alguns conceitos sobre Tabelas Dinâmicas Com tabelas dinâmicas podemos criar dinâmica e imediatamente resumos de uma lista Excel ou de uma base de dados

Leia mais

compreender a importância de cada estrutura de controle disponível na Linguagem C;

compreender a importância de cada estrutura de controle disponível na Linguagem C; Aula 3 Estruturas de controle Objetivos Esperamos que, ao final desta aula, você seja capaz de: compreender a importância de cada estrutura de controle disponível na Linguagem C; construir programas em

Leia mais

Descrição do Produto. Altus S. A. 1

Descrição do Produto. Altus S. A. 1 Descrição do Produto O software MasterTool IEC é um ambiente completo de desenvolvimento de aplicações para os controladores programáveis da Série Duo. Esta ferramenta permite a programação e a configuração

Leia mais

Arquitetura de processadores: RISC e CISC

Arquitetura de processadores: RISC e CISC Arquitetura de processadores: RISC e CISC A arquitetura de processador descreve o processador que foi usado em um computador. Grande parte dos computadores vêm com identificação e literatura descrevendo

Leia mais

Resolução eficaz de problemas: quatro exemplos

Resolução eficaz de problemas: quatro exemplos JFF6-0 Resolução eficaz de problemas: quatro exemplos Em Março participarei no evento Que Matemática para a Sociedade de Informação?, organizado pelo grupo FAST da Universidade do Minho, cujo objectivo

Leia mais

Programação Funcional. Aula 5. Funções Recursivas. José Romildo Malaquias. Departamento de Computação Universidade Federal de Ouro Preto 2011.

Programação Funcional. Aula 5. Funções Recursivas. José Romildo Malaquias. Departamento de Computação Universidade Federal de Ouro Preto 2011. Programação Funcional Aula 5 Funções Recursivas José Romildo Malaquias Departamento de Computação Universidade Federal de Ouro Preto 2011.2 1/39 1 Funções recursivas 2 Recursividade mútua 3 Recursividade

Leia mais

P r o g r a m a ç ã o d e C o m p u t a d o r e s 1 o S e m - 2 0 1 3 P r o f. A n d r é A m a r a n t e L u i z L A B 5 tag %2d while printf PE1:

P r o g r a m a ç ã o d e C o m p u t a d o r e s 1 o S e m - 2 0 1 3 P r o f. A n d r é A m a r a n t e L u i z L A B 5 tag %2d while printf PE1: Inteligência É a faculdade de criar objetos artificiais, especialmente ferramentas para fazer ferramentas. Henri Bergson. WHILE Além dos comandos if-else e switch, o controle de fluxo de um programa pode

Leia mais

Java Como Programar, 8/E

Java Como Programar, 8/E Capítulo 5 Instruções de controle: Parte 2 Java Como Programar, 8/E (C) 2010 Pearson Education, Inc. Todos os 5.1 Introdução Instrução de repetição for Instrução de repetição do while Instrução de seleção

Leia mais

Organização de Computadores 1

Organização de Computadores 1 Organização de Computadores 1 5 CONJUNTO DE INSTRUÇÕES Prof. Luiz Gustavo A. Martins Introdução O que é um conjunto de instruções? Coleção completa das instruções que a CPU é capaz de executar (entende).

Leia mais

PROGRAMAÇÃO DE UM MICROPROCESSADOR

PROGRAMAÇÃO DE UM MICROPROCESSADOR Relatório de Microprocessadores 2007/2008 Engenharia Física Tecnológica PROGRAMAÇÃO DE UM MICROPROCESSADOR EM C E ASSEMBLY PARA CONTROLO DE UM LED Laboratório I Trabalho realizado por: André Cunha, nº53757

Leia mais

Criar um formulário do tipo Diálogo modal ; Alterar a cor de fundo de um formulário; Inserir botões de comando e caixas de texto;

Criar um formulário do tipo Diálogo modal ; Alterar a cor de fundo de um formulário; Inserir botões de comando e caixas de texto; FICHA OBJECTIVO Construir Construir formulários na base de dados Diplomas em Diário da República Um formulário é utilizado, em primeiro lugar, para introduzir, eliminar ou apresentar dados numa base de

Leia mais

3.1 Definições Uma classe é a descrição de um tipo de objeto.

3.1 Definições Uma classe é a descrição de um tipo de objeto. Unified Modeling Language (UML) Universidade Federal do Maranhão UFMA Pós Graduação de Engenharia de Eletricidade Grupo de Computação Assunto: Diagrama de Classes Autoria:Aristófanes Corrêa Silva Adaptação:

Leia mais

Como enviar e receber correio eletrónico utilizando o Gmail

Como enviar e receber correio eletrónico utilizando o Gmail Como enviar e receber correio eletrónico utilizando o Gmail Este módulo pressupõe que que já tenha criado uma conta de correio eletrónico no Gmail (caso já não se recorde como deve fazer, consulte o nosso

Leia mais

Organização de Computadores Software

Organização de Computadores Software Organização de Computadores Software Professor Marcus Vinícius Midena Ramos Colegiado de Engenharia de Computação (74)3614.1936 marcus.ramos@univasf.edu.br www.univasf.edu.br/~marcus.ramos Objetivos: Entender

Leia mais

Pedro Ribeiro 2014/2015

Pedro Ribeiro 2014/2015 Programação Dinâmica Pedro Ribeiro DCC/FCUP 2014/2015 Pedro Ribeiro (DCC/FCUP) Programação Dinâmica 2014/2015 1 / 56 Números de Fibonacci Sequência de números muito famosa definida por Leonardo Fibonacci

Leia mais

8. Perguntas e Respostas

8. Perguntas e Respostas Arquimedes Manual do Utilizador 185 8. Perguntas e Respostas 8.1. Aparência Para conservar a disposição na qual estão expostas as B.D. no ecrã e para que em posteriores sessões de trabalho tenham a mesma

Leia mais

AULA 1: PARADIGMAS DE PROGRAMAÇÃO

AULA 1: PARADIGMAS DE PROGRAMAÇÃO 1 AULA 1: PARADIGMAS DE PROGRAMAÇÃO Curso: Ciência da Computação Profª.: Luciana Balieiro Cosme Ementa 2 Programação Imperativa. Programação Paralela e Concorrente. Programação Lógica. Programação Funcional.

Leia mais

INSTITUTO POLITÉCNICO DE BRAGANÇA ESCOLA SUPERIOR DE TECNOLOGIA E DE GESTÃO. Engenharia Electrotécnica. Microprocessadores. 2ºano - 1ºsemestre

INSTITUTO POLITÉCNICO DE BRAGANÇA ESCOLA SUPERIOR DE TECNOLOGIA E DE GESTÃO. Engenharia Electrotécnica. Microprocessadores. 2ºano - 1ºsemestre INSTITUTO POLITÉCNICO DE BRAGANÇA ESCOLA SUPERIOR DE TECNOLOGIA E DE GESTÃO Engenharia Electrotécnica Microprocessadores 2ºano - 1ºsemestre Microprocessador 8085 Exercícios de Programação em Linguagem

Leia mais

Capítulo 4 Gerenciamento de Memória

Capítulo 4 Gerenciamento de Memória Capítulo 4 Gerenciamento de Memória 4.1 Gerenciamento básico de memória 4.2 Troca de processos 4.3 Memória virtual 4.4 Algoritmos de substituição de páginas 4.5 Modelagem de algoritmos de substituição

Leia mais

Representação de Algoritmos - Linguagens de Programação

Representação de Algoritmos - Linguagens de Programação Representação de Algoritmos - Linguagens de Programação A representação de algoritmos em uma pseudo-linguagem mais próxima às pessoas é bastante útil principalmente quando o problema a ser tratado envolve

Leia mais

1. Criar uma nova apresentação

1. Criar uma nova apresentação MANUAL DO Baixa da Banheira, 2006 1. Criar uma nova apresentação Para iniciar uma sessão de trabalho no PowerPoint é necessário criar uma nova apresentação para depois trabalhar a mesma. Ao iniciar uma

Leia mais

Fundamentos de Teste de Software

Fundamentos de Teste de Software Núcleo de Excelência em Testes de Sistemas Fundamentos de Teste de Software Módulo 2- Teste Estático e Teste Dinâmico Aula 6 Teste Dinâmico: Técnicas de Especificação SUMÁRIO INTRODUÇÃO... 3 TÉCNICAS BASEADAS

Leia mais

Microcontroladores e Interfaces 3º Ano Eng. Electrónica Industrial

Microcontroladores e Interfaces 3º Ano Eng. Electrónica Industrial Microcontroladores e Interfaces 3º Ano Eng. Electrónica Industrial Carlos A. Silva 2º Semestre de 2005/2006 http://www.dei.uminho.pt/lic/mint Assunto: Pipeline Aula #5 28 Mar 06 Revisão Na implementação

Leia mais

1.2 Uma linguagem de programação muito simples

1.2 Uma linguagem de programação muito simples 1 Representando programas como dados 1.1 Introdução Os processadores de linguagem sempre fazem alguma manipulação com programas. Normalmente a entrada para o processador é um programa apresentado na forma

Leia mais

LÓGICA DE PROGRAMAÇÃO. Professor Celso Masotti http://ead.celsomasotti.com.br

LÓGICA DE PROGRAMAÇÃO. Professor Celso Masotti http://ead.celsomasotti.com.br LÓGICA DE PROGRAMAÇÃO Professor Celso Masotti http://ead.celsomasotti.com.br Ano: 2015 1 HTML & PHP em Ambiente Web PARTE II Sumário I Decisão... 4 Operadores de Comparação... 6 II IF ELSEIF ELSE... 7

Leia mais

http://www.matematica.br/programas/icg. 5. Uma lousa denominada EPI (registrador de endereço de próxima instrução).

http://www.matematica.br/programas/icg. 5. Uma lousa denominada EPI (registrador de endereço de próxima instrução). Universidade de São Paulo Instituto de Matemática e Estatística DCC Leônidas O. Brandão 1 Computador à Gaveta O objetivo deste texto é introduzir os primeiros conceitos de algoritmos a partir de um modelo

Leia mais

PARLAMENTO EUROPEU. Comissão dos Assuntos Jurídicos. 10.6.2005 PE 360.003v01-00

PARLAMENTO EUROPEU. Comissão dos Assuntos Jurídicos. 10.6.2005 PE 360.003v01-00 PARLAMENTO EUROPEU 2004 ««««««««««««Comissão dos Assuntos Jurídicos 2009 10.6.2005 PE 360.003v01-00 ALTERAÇÕES 1-17 Projecto de recomendação para segunda leitura Michel Rocard Patenteabilidade das invenções

Leia mais

Facturação Guia do Utilizador

Facturação Guia do Utilizador Facturação Guia do Utilizador Facturação Como se utiliza 2 1 Como se utiliza Todas as opções do sistema estão acessíveis através do menu: ou do menu: O Menu caracteriza-se pelas seguintes funcionalidades:

Leia mais

Sistemas Operacionais. Curso Técnico Integrado Profa: Michelle Nery

Sistemas Operacionais. Curso Técnico Integrado Profa: Michelle Nery Sistemas Operacionais Curso Técnico Integrado Profa: Michelle Nery Conteúdo Programático CONTAS DE E GRUPOS DE O Microsoft Management Console - MMC Permissões de Segurança de um Console Contas de Usuários

Leia mais

Programação WEB I Estruturas de controle e repetição

Programação WEB I Estruturas de controle e repetição Programação WEB I Estruturas de controle e repetição Operadores de Incremento Operadores de incremento servem como expressões de atalho para realizar incrementos em variáveis Operadores de Incremento Vamos

Leia mais

Curso de Iniciação ao Access Basic (I) CONTEÚDOS

Curso de Iniciação ao Access Basic (I) CONTEÚDOS Curso de Iniciação ao Access Basic (I) CONTEÚDOS 1. A Linguagem Access Basic. 2. Módulos e Procedimentos. 3. Usar o Access: 3.1. Criar uma Base de Dados: 3.1.1. Criar uma nova Base de Dados. 3.1.2. Criar

Leia mais

Alteração do POC (Decreto de Lei nº. 35/2005) no sispoc

Alteração do POC (Decreto de Lei nº. 35/2005) no sispoc DOSPrinter Manual do Utilizador Alteração do POC (Decreto de Lei nº. 35/2005) no sispoc Data última versão: 20.03.2006 Versão : 1.1 Data criação: 01.03.2006 Faro R. Dr. José Filipe Alvares, 31 8005-220

Leia mais

Linguagem C: variáveis, operadores, entrada/saída. Prof. Críston Algoritmos e Programação

Linguagem C: variáveis, operadores, entrada/saída. Prof. Críston Algoritmos e Programação Linguagem C: variáveis, operadores, entrada/saída Prof. Críston Algoritmos e Programação Linguagem C Linguagem de uso geral (qualquer tipo de aplicação) Uma das linguagens mais utilizadas Foi utilizada

Leia mais

Bases de Dados 2007/2008. Aula 8

Bases de Dados 2007/2008. Aula 8 Bases de Dados 2007/2008 Aula 8 1. T-SQL 2. VARIÁVEIS 3. CURSORES 4. PROCEDIMENTOS 5. EXERCÍCIOS Sumário Referências http://msdn2.microsoft.com/en-us/library/ms189826.aspx (linguagem t-sql) http://www.di.ubi.pt/~pprata/bd/bd0405-proc.sql

Leia mais

Modos de entrada/saída

Modos de entrada/saída Arquitectura de Computadores II Engenharia Informática (11545) Tecnologias e Sistemas de Informação (6621) Modos de entrada/saída Fonte: Arquitectura de Computadores, José Delgado, IST, 2004 Nuno Pombo

Leia mais

ÍNDICE. Delphi... 3 CAPÍTULO 1 INTRODUÇÃO... 06 CAPÍTULO 2 INSTALANDO O DELPHI... 10

ÍNDICE. Delphi... 3 CAPÍTULO 1 INTRODUÇÃO... 06 CAPÍTULO 2 INSTALANDO O DELPHI... 10 Delphi 7 ÍNDICE CAPÍTULO 1 INTRODUÇÃO... 06 CAPÍTULO 2 INSTALANDO O DELPHI... 10 CAPÍTULO 3 INICIANDO O Delphi... 18 FORM DESIGN... 19 CODE EDITOR... 23 OBJECT INSPECTOR... 26 OBJECT TREE VIEW... 29 PALHETA

Leia mais

Aula 4 Estatística Conceitos básicos

Aula 4 Estatística Conceitos básicos Aula 4 Estatística Conceitos básicos Plano de Aula Amostra e universo Média Variância / desvio-padrão / erro-padrão Intervalo de confiança Teste de hipótese Amostra e Universo A estatística nos ajuda a

Leia mais

Aula 12: Funções. Pré-requisitos: Todas as aulas anteriores deste módulo. 1. Aproveitando Códigos no Programa

Aula 12: Funções. Pré-requisitos: Todas as aulas anteriores deste módulo. 1. Aproveitando Códigos no Programa Aula 12: Funções Nesta aula explicaremos o que são e como usar funções nos seus programas em JavaScript. Você aprenderá como elas podem receber e retornar valores à estrutura que as acionou. Entenderá

Leia mais

Aula 4 Conceitos Básicos de Estatística. Aula 4 Conceitos básicos de estatística

Aula 4 Conceitos Básicos de Estatística. Aula 4 Conceitos básicos de estatística Aula 4 Conceitos Básicos de Estatística Aula 4 Conceitos básicos de estatística A Estatística é a ciência de aprendizagem a partir de dados. Trata-se de uma disciplina estratégica, que coleta, analisa

Leia mais

O modelo do computador

O modelo do computador O modelo do computador Objetivos: Mostrar como é o funcionamento dos computadores modernos Mostrar as limitações a que estamos sujeitos quando programamos Histórico Os primeiros computadores são da década

Leia mais

Conjunto de instruções. O Conjunto de Instruções. Conjunto de instruções. Instruções típicas. Instruções típicas. Instruções típicas

Conjunto de instruções. O Conjunto de Instruções. Conjunto de instruções. Instruções típicas. Instruções típicas. Instruções típicas Conjunto de instruções O Conjunto de Instruções ISA Instruction Set Architecture Alguns conceitos... Linguagem máquina Combinação de 0 s e 1 s organizados segundo palavras que são as instruções que o processador

Leia mais