Sei sulla pagina 1di 11

CONCEITOS BÁSICOS SOBRE PROGRAMAÇÃO

Programação Orientada a Objetos (POO)


Profa. Vania V. Estrela, Profa. Albany E. Herrmann

1. Programação

Programação requer o uso de uma linguagem, cuja sintaxe geralmente é mais restrita do
que a de uma linguagem natural como o Português. Apesar disso, uma linguagem de
programação é poderosa o suficiente para resolver qualquer problema, que envolva
computação e flexível o bastante para permitir resolver um mesmo problema por
programas diferentes. O leitor interessado em aprender mais sobre os tópicos abordados
nesta apostila deve consultar as referências bibliográficas [1-4].
O sistema operacional (SO) cria um ambiente onde usuários podem
confeccionar programas e executá-los sem se preocupar com detalhes de hardware.
Podemos imaginar o SO como um intermediário entre o programador e o hardware, o
qual oferece bibliotecas com funções de alto nível para ler e escrever dados nestes
dispositivos. Exemplos de SOs são o Linux, o Windows, e o MS-DOS.
Na hipótese de existir mais de um programa para solucionar um problema, uns
podem ser mais eficientes do que outros. Esta eficiência está relacionada
principalmente ao tempo de CPU e à quantidade de memória necessários a execução do
programa. Logo, espaço de memória e tempo de execução precisam ser conciliados em
computação.
A correção dos códigos é muito importante e o ideal é que um programa
funcione corretamente para qualquer dado de entrada válido. A correção e a eficiência
são objetivos fundamentais de qualquer programa, porém é impossível testar um com
todas as entradas possíveis. Provar matematicamente a correção de um programa é
difícil. Outro fator complicador é que não são conhecidos algoritmos eficientes para
resolver vários problemas importantes.
O primeiro passo, em se tratando de programação, inicia-se com a confecção de
um programa ou código fonte (PF) e termina com a geração de um programa
executável (PE) ou código executável .
Normalmente, o PF é formado por uma sequência de instruções, cujo formato é
especificado por alguma linguagem de programação e deve ser criado num editor de
textos (com ou sem formatação, dependendo do ambiente de desenvolvimento). Depois,
o PF é submetido a um compilador, para ser analisado e convertido num código-
objeto (ou programa-objeto; PO). O PO é a versão em linguagem de
máquina (números binários) do PF.
Caso o programa contenha chamadas a funções das libraries ou bibliotecas
(função cosseno, por exemplo), o linker ou ligador combina o PO com a(s)
respectiva(s) biblioteca(s) e gera um PE.

1.1 Geração do Código Executável

Para cada linguagem de programação, a máquina pode ser vista como um sistema
dedicado à execução de programas. Diferentes linguagens fazem com que
aparentemente tenhamos diferentes máquinas virtuais, cuja implementação não interessa
ao usuário, na maioria dos casos. Em princípio, pelo menos, para quem executa um
programa escrito em FORTRAN não faz diferença se o hardware da máquina executa o
código FORTRAN diretamente, ou se uma tradução é feita para o código que é
finalmente executado (a linguagem da máquina), possivelmente em vários passos.
A máquina virtual de uma linguagem de programação pode sempre ser vista
como a implementação de uma interface entre o usuário e a máquina. Essa
implementação pode ser, até certo ponto, estendida ou modificada pelo usuário.
Na prática, a implementação de uma máquina virtual nunca é totalmente
transparente (invisível): alguns aspectos da forma pela qual foi feita podem ficar
aparentes para seus usuários, através do tempo gasto para a execução, ou de mensagens
provenientes de etapas intermediárias da implementação, aspectos esses que deveriam
ser invisíveis.
Montador: Assembly
Compilador: Ling. de
Programação

Figura 1 – Etapas para a geração de um código executável.

Para implementar uma linguagem de programação numa máquina, esta deve


dispor de circuitos que, para cada instrução da linguagem, se encarregam das ações
correspondentes à mesma. Um PE pode ser gerado, a grosso modo, por um dos três
tipos de programas auxiliares.

Principais Termos:

 Código-Fonte: Criado via editor de textos, contém os comandos da linguagem


de programação (C++, Pascal...) e serve como entrada para o compilador.
 Código-Objeto (PO) ou Arquivo Objeto: Criado pela conversão do PF em
linguagem de máquina. É gerado pelo montador, compilador ou interpretador,
quando não há erros no PF (extensões do código-objeto mais comuns: .OBJ, .o)
 Ligador ou Linkeditor: Combina o PO com as bibliotecas necessárias a
geração do PE (por exemplo, extensões das bibliotecas .DLL ou .LIB).
 Programa Executável: Código passível de execução pelo SO (extensão do PE:
.EXE)
 Tempo de Compilação: Intervalo de tempo decorrido para conversão do PF em
PO.
 Tempo de Execução: Começa após a ativação do PE.

Para cada arquivo de PF, é gerado um arquivo com um PO, o qual é ligado a
outros, através de um ligador, resultando num PE ou biblioteca. Um PO não só contém
código objeto, mas também informações sobre alocação de memória, os símbolos do
programa e também informações sobre depuração ou debug.
Há vários formatos de PO. Originalmente, cada computador possuía formato
próprio, mas com o advento de SOs portáveis (como por exemplo o UNIX), outros
formatos, foram padronizados e utilizados em diferentes sistemas. É comum o mesmo
formato de PO servir tanto para entrada, quanto para saída do ligador, sendo portanto
utilizado no PE ou biblioteca gerada.
O formato dos POs é parte importante no projeto de um SO: uma vez que afeta o
tempo que os programas levam para serem acionados e, assim, afeta o tempo de
desenvolvimento dos sistemas. Além disso, se o formato também é utilizado para os
PEs, ele influi no tempo que o programa leva para começar a executar (responsividade
do programa sob o ponto de vista do usuário final). A maioria dos formatos é
estruturada como blocos do mesmo tipo, podendo ser mapeados conforme necessário
pelo sistema de gerenciamento de memória virtual do SO, sem necessidade de mais
processamento antes de serem utilizados.
O tipo mais simples de código objeto executável é o .COM do DOS, que contém
apenas bytes, sempre carregados no mesmo endereço da memória. Outros formatos,
cuja especificação abrange várias páginas, contém várias estruturas e sub-estruturas. Os
programas cuja extensão é .EXE também contem código em linguagem de máquina
executável.

1.2 Geração de Código Objeto

Os tradutores dividem-se em tradutores de linguagem fonte e a linguagem simbólica


para uma linguagem de máquina (numérica). O tradutor é chamado de montador,
quando processa uma linguagem de baixo nível ou Assembly ou linguagem de
montagem. Já o compilador traduz de uma linguagem de nível médio ou de alto nível
para o código executável. Outra opção é usar um interpretador.

1.2.1 Montador

Traduz literalmente os mnemônicos do Assembly, implementado-os em linguagem de


montagem para todas as instruções da máquina e modos de endereçamento, além de
traduzir comandos em linguagem de montagem válidos (pseudo-instruções ou diretivas
de execução) para seus equivalentes em linguagem de máquina. Por exemplo, programa
fonte sob a forma de menemônicos (linguagem de máquina simplificada), cuja extensão
é .asm pode ser traduzido para um programa em binário pronto para a execução na
RAM (linguagem de máquina).
A montagem é um processo simples, porém tedioso e propenso a erros quando
feito manualmente. Montadores comerciais geralmente possuem as seguintes
características:

 O programador pode especificar explicitamente as posições de dados e programas


durante a execução.
 Valores de dados na memória podem ser inicializados antes da execução do
programa.
 Rótulos simbólicos (labels) podem ser usados para representar endereços e
constantes.
 Variáveis podem ser definidas num programa em linguagem de montagem e
usadas posterioriormente em outros programas.
 Subrotinas (semelhantes às funções em linguagem de alto nível) podem ser
definidas uma vez e serem chamadas onde e quantas vezes for necessário.
 Permitem a definição de macros, ou seja, trechos em código de máquina, que
podem ser definidas uma vez e, depois, instanciadas quando necessário,
implicando na substituição da chamada a macro por seu código equivalente.
Portanto, trata-se de uma forma resumida de escrever o programa, mas que não
implica num código de máquina menor.
A maioria dos montadores leem os programas fonte duas vezes, e são chamados de
montadores de dois passos (etapas de montagem). O primeiro passo determina o
endereço de todos os itens de dados e instruções de máquina, para selecionar quais
palavras binárias (instruções conforme serão escritas na RAM) serão geradas para cada
linha de código fonte.
Os endereços dos itens de dados e instruções são determinados por meio do uso
de um contador de programa para a montagem, chamado contador de instrução
(program counter ou instruction counter). O contador de instrução gerencia o endereço
da instrução executada e dos itens de dados a ela associados durante a montagem, que
geralmente é inicializada com 0 (zero). No início do primeiro passo, é incrementado de
acordo com o tamanho de cada instrução.
Durante este passo, o montador também efetua quaisquer operações aritméticas
em tempo de montagem, e insere as definições de todos os rótulos de funções e
variáveis e as constantes, em uma tabela chamada Tabela de Símbolos (TS).

Código-fonte Compilador Código Objeto Código de


(Source code) Máquina
(Assembly)

Figura 2. Sequência típica para geração de um programa em linguagem de máquina.

Figura 3 – Etapas envolvidas na geração de um código executável (código de máquina


pronto para carregar).
COMPILADOR
PROGRAMA
FONTE Resultados
(Dados) de
PROGRAMA SISTEMA Saída
OBJETO OPERACIONAL Armazenados
Dados (SO)
de
Entrada
LIGADOR PROGRAMA
(LINKER)/ EM PROGRAMA
CARREGADOR LINGUAGEM EXECUTÁVEL
(LOADER) DE MÁQUINA (.exe)
(ASSEMBLY)

Resultados
(Tela)

Figura 4 – Etapas do processo de compilação/montagem.

A razão principal para exigir uma segunda passagem do montador é permitir que
símbolos possam ser usados no programa antes de serem definidos. Após a primeira
passagem, o montador terá identificado todos os símbolos e os colocado na TS. Na
segunda passagem, gerará código de máquina, inserindo os identificadores dos símbolos
os quais são conhecidos agora.

1.2.2 Interpretador

Programa que lê e executa as tarefas do programa fonte linha a linha, ou seja, cada linha
implica em executar uma ação, sem gerar código-objeto explicitamente. Em geral é
lento devido à execução passo a passo. A grande vantagem de um interpretador é o
maior controle sobre o programa em execução, tornando possível detectar situações de
erro invisíveis ou imprevisíveis. Esse tipo de tradução aparece em linguagens de
comandos (scripts como os do MATLAB); ou em linguagens de programação, que
permitem construções de tamanho não determinado antecipadamente.

1.2.3 Compilador

É um programa que transforma um texto de programa escrito (programa fonte) em uma


linguagem de programação de alto/médio níveis (linguagem fonte), num programa
equivalente (programa objeto) numa linguagem de baixo nível (geralmente chamada de
linguagem objeto). Em geral, o código objeto ainda não está em condições de ser
carregado na memória do computador, pois faz-se necessário o mapeamento do
programa objeto na RAM; inserção de bibliotecas de software; e resolução de
endereços e labels.
Adicionalmente, é possível adaptar o código gerado por um compilador para
cada comando de acordo com seu contexto, aproveitando diferenças, que não podem ser
tratadas com a mesma facilidade pelo interpretador.
Um Compilador C++ é um programa, cuja finalidade é traduzir ou converter um
programa fonte escrito numa linguagem linguagem fonte para um programa objeto
escrito na linguagem objeto; o programa objeto é o resultado da tradução.
A compilação também pode gerar PO, que não será executado diretamente, mas
o qual será usado em conjunto com outros. Estes programas são chamados de
bibliotecas, e fornecem funcionalidades básicas e avançadas. A junção do PO dos
programas com o PO das bibliotecas é realizada pelo ligador.

1.3 Ligador (Linker)

O ligador coleta procedimentos traduzidos separadamente, ligando-os uns aos outros


para que eles possam executarum PE.
Se o compilador ou o montador lesse um conjunto de PFs e produzisse
diretamente um PE em linguagem de máquina pronto para ser executado, bastaria que
um único comando fonte fosse alterado, para que todos os PFs tivessem que ser
novamente traduzidos.
Usando módulos objeto separados, o único procedimento a ser traduzido seria
aquele modificado. Havendo a necessidade de realizar apenas a etapa de ligação dos
módulos separados novamente, sendo esta tarefa mais rápida que a tradução.

1.4 Carregadores

São programas que colocam módulos de carregamento na memória principal.


Conceitualmente, a tarefa do carregador não é difícil, pois consiste em carregar os
vários segmentos de memória com seus valores corretos e inicializar certos
registradores, tais como o apontador para pilha do sistema, responsável pelo escopo das
rotinas em execução e o contador de instruções contido no processador, com seus
valores iniciais, indicando assim onde o programa deve ser iniciado.
Em SOs modernos, vários programas estão residentes na memória a todo
instante, e não há como o montador ou o ligador saber em quais endereços os módulos
de um programa irão residir. O carregador deve relocar estes módulos durante o
carregamento adicionando um deslocamento a todos os endereços, permitindo desta
forma acessar cada módulo individualmente na memória.
Esse tipo de carregamento é chamado de carregamento com relocação.
Simplificadamente, o carregador modifica endereços relocáveis, dentro de um único
módulo de carregamento, para que vários programas passem a residir na memória ao
mesmo tempo.

1.5 Ambientes de Desenvolvimento (IDEs)

Em muitos casos, os compiladores ou montadores estão acoplados a ambientes de


desenvolvimento (IDEs), que incluem outras ferramentas, como por exemplo:

Depuradores ou Debuggers visando teste e detecção de erros.


Profilers para medir o tempo gasto pelo programa.
Software para construção de diagramas.
Aplicativo para a edição de programas fontes.
1.6 Sistema Operacional (SO)

No passado, os usuários dos sistemas interagiam muito mais com o hardware.


Atualmente, muitas da funções que eram executadas pelos próprios usuários, são agora
realizadas pelo sistema operacional.
Reúnem programas, quase sempre transparentes ao usuário, que desempenham
rotinas necessárias ao funcionamento do computador:
– gerenciamento da memória;
– administração dos dados;
– acionamento dos dispositivos; e
– execução de programas utilitários.

1.6.1 DOS (Disk Operating System)

O DOS (Disk Operating System) da Microsoft é um dos mais utilizados no mundo. O


MS-DOS trabalha com comandos que informam ao sistema as tarefas a serem
realizadas. Tarefas básicas do DOS:

 gerenciar arquivos e diretórios;


 manutenção de discos (rígidos e flexíveis);
 configurar o hardware;
 otimizar o uso da memória;
 melhorar o desempenho dos programas; e
 personalizar o MS-DOS.

O MS-DOS indica que está preparado para receber comandos através do aviso de
comando ou "prompt". Ex.:
a>
Os comandos digitados a partir de um prompt como o acima especificam as
tarefas a serem realizadas pelo MS-DOS.
Referências
[1] http://producao.virtual.ufpb.br/books/camyle/introducao-a-computacao-
livro/livro/livro.chunked/ch05s03.html

[2] Stroustrup, Bjarne. (2002). Linguagem de Programação C++. Lisboa. 3. ed. Porto
Alegre: Bookman.

[3] Patterson, D.A., Hennessy, J.L. (2008). Computer Organization and Design, Fourth
Edition: The Hardware/Software Interface (The Morgan Kaufmann Series in Computer
Architecture and Design).

[4] Stallings, W. (2009). Computer Organization and Architecture: Designing for


Performance, Prentice Hall, 8 edition, ISBN-13: 978-0136073734

Potrebbero piacerti anche