SISTEMAS OPERATIVOS I



Documentos relacionados
Usando emacs, vim e gdb. Um guia BEM básico

O Processo de Programação

1 Code::Blocks Criação de projetos

Um compilador é um programa que lê um programa escrito numa dada linguagem, a linguagem objecto (fonte), e a traduz num programa equivalente

Trabalhos Práticos. Programação II Curso: Engª Electrotécnica - Electrónica e Computadores

INTRODUÇÃO À PROGRAMAÇÃO BCC 201 TURMAS 31, 32 E AULA TEÓRICA 2 PROF. MARCELO LUIZ SILVA (R E D)

LP II Estrutura de Dados. Introdução e Linguagem C. Prof. José Honorato F. Nunes honorato.nunes@ifbaiano.bonfim.edu.br

LINGUAGEM C UMA INTRODUÇÃO

Nota de Aula: Utilização da IDE Code::Blocks

Algoritmos e Programação Estruturada

Introdução à Programação

A Linguagem Pascal e o Ambiente de Programação Dev-Pascal. Introdução à Ciência da Computação I

ESCOLA SUPERIOR DE TECNOLOGIA DE TOMAR DEPARTAMENTO DE ENGENHARIA INFORMÁTICA 2005/ Valores

Guião de Introdução ao Eclipse IDE Índice

Manual de instalação e utilização do software de decriptografia GnuPG (Gnu Pricavy Guard)

AMBIENTE DE PROGRAMAÇÃO PYTHON

3. O NIVEL DA LINGUAGEM DE MONTAGEM

Curso de Eng. Informática Linguagens de Programação. C Sharp University Data Processing. (C Sharp Universidade de Processamento de Dados) Docente:

Algoritmos e Programação (Prática) Profa. Andreza Leite andreza.leite@univasf.edu.br

ARQUITETURA DE COMPUTADORES. Rogério Spindula Rosa

ALP Algoritmos e Programação. . Linguagens para Computadores

Introdução. Capítulo Breve sinopse

Introdução aos Algoritmos e Estruturas de Dados 2011/2012

Módulo 3936 ASP.NET. Financiado pelo FSE

Hardware (Nível 0) Organização. Interface de Máquina (IM) Interface Interna de Microprogramação (IIMP)

O que é o JavaScript?

Um sistema SMS 1 simplificado

Linguagem e Técnicas de Programação I Programação estruturada e fundamentos da linguagem C

UNIVERSIDADE FEDERAL DO RIO GRANDE DO SUL INSTITUTO DE INFORMÁTICA INFORMÁTICA APLICADA

Metodos de Programação

TIC Unidade 2 Base de Dados. Informação é todo o conjunto de dados devidamente ordenados e organizados de forma a terem significado.

COMPILADORES E INTERPRETADORES

Relatório de Instalação do Windows 2003 Server

5. Métodos ágeis de desenvolvimento de software

CAPÍTULO 7 NÍVEL DE LINGUAGEM DE MONTAGEM

Module Introduction. Programação. Cap. 4 Algoritmos e Programação Estruturada

Informática II Cap. 3

Instituto Superior Politécnico de VISEU. Escola Superior de Tecnologia

Programação de Computadores I. Conhecendo a IDE Code::Blocks

Transição de POC para SNC

Bases de Dados. Lab 1: Introdução ao ambiente

Os objetivos indicados aplicam-se a duas linguagens de programação: C e PHP

PROGRAMAÇÃO DE MICROPROCESSADORES 2011 / 2012

Curso de Programação Computadores

MICROSOFT POWERPOINT

Laboratório 3 Compilador e IDE. Departamento de Sistemas e Informática. Disciplina de Introdução à Programação Ano Lectivo 2006/2007

INTRODUÇÃO ÀS LINGUAGENS DE PROGRAMAÇÃO

3 Revisão de Software

LEI Sistemas de Computação 2011/12. Níveis de Abstração. TPC4 e Guião laboratorial. Luís Paulo Santos e Alberto José Proença

Tarefa Orientada 16 Vistas

O que é um programa? Programa é uma lista de instruções que descrevem uma tarefa a ser realizada pelo computador.

Universidade Federal de Minas Gerais Escola de Engenharia Departamento de Engenharia Eletrônica

Figura 1 - O computador

O protocolo MODBUS define também o tipo diálogo entre os equipamentos, define por exemplo quem pode enviar dados e em que altura.

Engenharia de Software Sistemas Distribuídos

Licenciatura em Engenharia Informática Departamento de Engenharia Informática Instituto Superior de Engenharia do Porto

Instalação do software cygwin

Processamento de dados XML

IFTO LÓGICA DE PROGRAMAÇÃO AULA 01

Programação 2ºSemestre MEEC /2011. Programação 2º Semestre 2010/2011 Enunciado do projecto

UFSM Introdução ao Dev-C++ Profa. Patrícia Pitthan. Introdução ao Dev-C++

Editor Eclipse para Programas F

Manual de backup do banco de dados PostgreSQL - Versão 2. Setembro-2011

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

Hugo Pedro Proença, 2007

Software Básico (INF1018)

LEI Sistemas de Computação 2014/15. Níveis de Abstração. TPC4 e Guião laboratorial. Luís Paulo Santos e Alberto José Proença

MC-102 Aula 01. Instituto de Computação Unicamp

Linguagem de Programação I

Construção Páginas de Internet

Tarefa Orientada 2 Visual Studio 2005 e Visual C#

Engenharia de Software

MC102 Algoritmos e Programação de Computadores 1ª Aula Introdução à Programação de Computadores

Introdução às Linguagens de Programação

Introdução ao PHP. Prof. Késsia Marchi

Conceitos básicos da linguagem C

Aula teórica 3. Tema 3.Computadores e linguagens Linguagens de Programação Compilação e linkagem LP Java. Preparado por eng.

Usando o simulador MIPS

Conceitos básicos de programação

Tarefa Orientada 15 Manipulação de dados

Aplicações de Escritório Electrónico

OPERADORES E ESTRUTURAS DE CONTROLE

Sistemas Operacionais

Capítulo 2: Introdução à Linguagem C

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

Interrupções. As interrupções são casos especiais de chamadas de procedimentos.

Java. Marcio de Carvalho Victorino

Aula 2. Objetivos Conceitos; Instalação do Text Pad; Entendendo o código java do AloMundo1 Codificação do AloMundo2,AloMundo3 e AloMundo4.

Manual de Utilizador. CNCVisual. Julho de Âmbito do Projecto de 5º Ano de Engenharia Mecânica. Autor: Bruno Lameiro

TECNOLOGIAS DA INFORMAÇÃO E COMUNICAÇÃO - TIC 10º C. Planificação de. Curso Profissional de Técnico de Secretariado

Professora Martha Spalenza Professora de Informática da Faetec

Transcrição:

Instituto Superior de Engenharia do Porto Departamento de Engenharia Informática SISTEMAS OPERATIVOS I Textos de Apoio às Aulas Práticas Pré-processador, compilador e debugger 2004 Jorge Pinto Leite Sugestões e participações de erros para jpl@dei.isep.ipp.pt

Índice Introdução...1 Programa fonte...1 O processo de compilação...2 Pré-processador... 2 Compilador propriamente dito... 2 Assemblador... 3 Linker... 3 Opções do compilador... 4 Debugger...5 Exercício proposto...8 Jorge Pinto Leite i

Introdução A compilação é o processo que permite traduzir em linguagem perceptível pelo computador as instruções que queremos que este execute. Neste capítulo iremos analisar este processo, descrevendo cada uma das suas fases e tomando como base o gcc (GNU C Compiler), um compilador multifacetado que permite a compilação de programas fontes escritos em várias linguagens, nomeadamente C, C++, Objective C, Fortran, etc, estando em desenvolvimento extensões para outras linguagens. Programa fonte O tipo de instrução que um equipamento entende é em linguagem binária, dita executável, a qual não é fácil nem lógica de programar. Uma primeira abordagem foi efectuada com linguagens perceptíveis pelo processador (Assembler), que mau grado ter já um certo interface com o utilizador, continuam a ser pouco intuitivas e complexas, quer de programar, quer de manter. A evolução técnica e as necessidades dos utilizadores levou a sucessivas gerações de linguagens, tendo cada geração mais características avançadas de manipulação de dados e de manuseamento de objectos. Dividem-se assim as linguagens em baixo (as primeiras) ou alto (as últimas) nível. Independentemente do nível de uma determinada linguagem, o que é garantido é que contêm um conjunto de instruções que por si só não são perceptíveis por um equipamento. Duas famílias de linguagens impuseram-se: as interpretadas e as compiladas. As primeiras são traduzidas em linguagem máquina em tempo real, ou seja, cada instrução é traduzida à medida que é executada. Sendo um processo fácil para escrita e validação de um programa, torna-se necessariamente mais lenta na sua execução, pelo que representa actualmente uma menor fatia de mercado. Um exemplo de linguagem interpretada é o Visual-Basic, mas este tipo de linguagens é muito usado em aplicações web (linguagens de scripting em servidores). As segundas são escritas em linguagem perceptível pelo programador, sendo necessário traduzi-las para linguagem máquina, as quais são por sua vez executáveis. Um eventual erro implica a alteração do programa, (re)compilação do mesmo e posterior execução. Um exemplo de linguagem compilada é o C. O programa escrito numa linguagem perceptível pelo utilizador denomina-se por programa fonte. Nos capítulos seguintes usaremos como exemplo o seguinte programa fonte escrito em linguagem C. /* teste.c */ #include <stdio.h> main(void) { int i ; for(i=1 ;i<10 ;i++) Jorge Pinto Leite Página 1 de 8

} printf( Valor de i: %i\n,i); exit(0); O processo de compilação Tipicamente há bibliotecas auxiliares das diversas linguagem que, através da sua inclusão num programa fonte, permitem e facilitam o acesso a constantes standard, estruturas, valores pré-definidos, etc. (por exemplo, em C, a instrução para incluir estas bibliotecas é #include <nome-da-biblioteca>). Esta facilidade implica que o compilador deverá, ao encontrar estas instruções especiais, substituí-las pelo conjunto de linhas que compõem cada uma das bibliotecas referidas. Além disso, e principalmente a nível de grandes projectos, há conjuntos de instruções que se repetem, sendo habitual a criação de macros que as contêm, e que serão também chamadas repetidamente no programa fonte. O processo completo de compilação é pois responsável pela tradução destas e doutras ocorrências, pelo que se encontra dividido por várias fases: o Pré-processador o Compilador propriamente dito o Assemblador o Linker Pré-processador O pré-processador tem por função: 1. Detectar qualquer instrução de inclusão e substituí-la pela correspondente biblioteca. 2. Detectar macros utilizadas e expandi-las para o conjunto de tarefas associadas. Podemos analisar esta função recorrendo à opção E do gcc (ver Opções do compilador para algumas das opções do compilador). Para analisarmos o resultado da aplicação do pré-processador no programa teste.c executamos o comando: $ gcc E teste.c o teste.cpp Podemos editar e analisar o conteúdo de teste.cpp, no qual veremos que a alteração consiste na substituição do parágrafo #include <stdio.h> pelo conteúdo desta biblioteca, além doutros caracteres específicos do pré-processador. Compilador propriamente dito O compilador propriamente dito tem por missão ler a saída do pré-processador e criar um programa em código assembler. Este código assembler gerado é o apropriado para o processador do equipamento utilizado. Podemos analisar esta função recorrendo à opção S do gcc (ver Opções do compilador para algumas das opções do compilador): $ gcc S teste.c o teste.asm Jorge Pinto Leite Página 2 de 8

Assemblador O assemblador tem por função traduzir o código assembler gerado pelo seu correspondente binário, não executável. Este código binário gerado é o apropriado para o processador do equipamento utilizado. Podemos analisar esta função recorrendo à opção c do gcc (ver Opções do compilador para algumas das opções do compilador): Linker $ gcc c teste.c o teste.bin O linker realiza a concatenação do código binário gerado com as bibliotecas específicas do sistema, a fim de criar um código já executável. Todos os passos anteriormente descriminados são executados sempre que compilamos um programa fonte, só que essa execução é efectuada sem que o utilizador se aperceba. Para compilar um programa e obter o respectivo executável, introduz-se uma linha de comando simples, tal como: $ gcc teste.c o teste.exe Convém ter em conta que o executável pode ser obtido a partir de um qualquer passo intermédio do processo de compilação, através de uma das opções existentes, a x. Esta opção permite indicar ao compilador que tipo de fonte vai encontrar. Como exemplo, poderíamos dar os seguintes comandos, todos com o mesmo resultado final: $ gcc x cpp-output teste.cpp o teste.exe $ gcc x assembler teste.asm o teste.exe Para o passo final, isto é, para efectuar a linkagem, não é necessário indicar ao compilador qual o tipo de ficheiro de input, já que ele o reconhece automaticamente: $ gcc teste.bin o teste.exe Em suma, o processo desencadeado pela linha de comando $ gcc teste.c o teste.exe pode ser efectuado passo a passo e a partir do output anterior através da sequência de comandos: $ gcc E teste.c o teste.cpp $ gcc S x cpp-output teste.cpp o teste.asm $ gcc c x assembler teste.asm o teste.bin $ gcc teste.bin o teste.exe Jorge Pinto Leite Página 3 de 8

Opções do compilador Sintaxe: gcc [opções] programa-fonte Opções: -include <ficheiro> Inclui o conteúdo de <ficheiro> antes de outros ficheiro. -imacros <ficheiro> Aceita a definição de macros de <ficheiro>. -iprefix <path> Especifica o caminho para as opções: -iwithprefix <dir> Adiciona <dir> ao final do caminho de inclusão de sistema. -iwithprefixbefore <dir> Adiciona <dir> ao início do caminho de inclusão. -isystem <dir> Adiciona <dir> ao início do caminho de inclusão de sistema. -idirafter <dir> Adiciona <dir> ao final do caminho de inclusão de sistema. -I <dir> Adiciona <dir> ao final do caminho de inclusão. -nostdinc Não procura no caminho de inclusão de sistema. -o Ficheiro de output. Se não for indicado assume a.out. -lang-c Assume que o ficheiro de input é em C. -w Inibe mensagens de warning. -Werror Trata as mensagens de warning como erros. -M Mostra as dependências de make. -MM Como M, mas ignora os system headers. -MD Como M, mas escreve o output num ficheiro.d. -v Mostra a versão. -H Mostra o nome dos header files à medida que são usados. -E Só executa o pré-processador. -S Executa pré-processador e compilador. -c Executa pré-processador, compilador e assembler. -x Altera tipo de ficheiro origem algumas das opções possíveis são cpp-output e assembler. --help Mostra o ficheiro de help. -g Compila para debbuging. Jorge Pinto Leite Página 4 de 8

Debugger O processo de debugging, permitindo a execução de um programa de forma controlada, é um processo muitas vezes fundamental para detecção e correcção de falhas de funcionamento. O debugger do GNU é o gdb. Para o poder utilizar é necessário instruir o sistema que pretendemos fazer o debug do programa através da instrução: $ gcc g teste.c o teste.exe que criará, como já se explicou, um ficheiro executável com o nome teste.exe, mas com informação extra através da opção g (função de debbuging). A sua execução é efectuada com o comando: $ gdb teste.exe que iniciará o interface para o utilizador como se observa na Figura 1. picasso.dei.isep.ipp.pt> gcc g o teste teste.c picasso.dei.isep.ipp.pt> gdb teste GNU gdb Rad Hat Linux (5.2-2) Copyright 2002 Free Software Foundation, Inc. GDB is free software, covered by the GNU Ge neral Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type show copying to see the conditions. There is absolutely no warranty for GDB. Type show warranty for details. This GDB was configured as i386-redhat-linux (gdb) Figura 1 A partir deste ponto há um conjunto de comandos passíveis de dar ao gdb que possibilitam a execução do modo pretendido. Alguns dos comandos são: run [argumentos] break ponto delete N info break help comando step next finish Inicia a execução como se tivesse passado os argumentos na linha de comando. Cria um breakpoint no ponto indicado. Ponto pode ser o nome de uma função ou um número de linha. Cada breakpoint é associado a um número identificativo. O comando break main interrompe no início da execução. Quando o programa está em execução e chega a um breakpoint dá-nos uma mensagem. Elimina o breakpoint com o número N. Se este número for omitido elimina todos os breakpoint activos. Mostra todos os breakpoint activos. Dá informação sobre o comando indicado. Executa uma linha do comando e pára na linha Seguinte. Se a linha contiver uma chamada de função, a linha seguinte é a primeira instrução dessa chamada. Igual ao step mas se a linha corrente contiver uma chamada de função executa-a sem mostrar cada uma das suas instruções. Equivalente a uma sucessão de next s até chegar ao final da Jorge Pinto Leite Página 5 de 8

continue where print variável display variável quit list função corrente. Executa o programa sem debbuging até ao próximo breakpoint. Faz uma lista das funções que trouxeram o programa até ao ponto em que está actualmente. Mostra o valor actual da variável, actualizando-a à medida que o programa vai decorrendo. Mostra o valor actual da variável, mas não o actualiza à medida que o programa vai decorrendo. Abandona o gdb. Mostra a rotina em execução. É necessário ter em mente que a utilização do debbuging só terá sentido se ao iniciarmos declararmos pelo menos um ponto de suspensão através da instrução break. Sem isto a sua execução, se bem que acompanhada pelo debbuger, será exactamente igual à obtida sem o recurso ao gdb, operação que se observa na Figura 2. (gdb) list 1 #include <stdio.h> 2 main(void) 3 { 4 int i; 5 for(i=1;i<10;i++) 7 exit(0); 8 } (gdb) break main Breakpoint 1 at 0x8048496: file teste.c, line5. <gdb> run Starting program: /users/2/jpl/so1/teste Breakpoint 1, main () at teste.c: 5 for(i=1;i<10;i++) (gdb) Figura 2 Também se deve ter em mente que a utilização do comando step deverá ser evitada, pois devido às bibliotecas de sistema que são implicitamente incluídas pelo linker poderemos ter um vasto conjunto de mensagens de erro se não tivermos acesso às mesmas. Por esse motivo a instrução preferível para analisar e acompanhar o desempenho da rotina é a instrução next, demonstrada na Figura 3. Na mesma figura chama-se ainda a atenção para a instrução display utilizada para acompanharmos a variação de uma variável, no caso, a variável i. Jorge Pinto Leite Página 6 de 8

3 { 4 int i; 5 for(i=1;i<10;i++) 7 exit(0); 8 } (gdb) break main Breakpoint 1 at 0x8048496: file teste.c, line5. <gdb> run Starting program: /users/2/jpl/so1/teste Breakpoint 1, main () at teste.c: 5 for(i=1;i<10;i++) (gdb) next (gdb) display i 1: i = 1 (gdb) next Valor de i: 1 5 for(i=1;i<10;i++) 1: i = 1 (gdb) n 1: i = 2 (gdb) Figura 3 Assumindo que o objectivo de execução com o debbuger já tinha sido obtido, poderíamos abandonar a sua execução ou instruir o debbuger para executar até ao fim, como se vê na Figura 4. 1: i = 6 (gdb) r The program beeing debugged has been started already. Start it from the beginning? (y or n) n Program not restarted (gdb) continue Continuing. Valor de i: 7 Valor de i: 8 Valor de i: 9 Program exited normally. (g db) Figura 4 Convém ainda ter em mente que em qualquer altura se pode instruir o debbuger para recomeçar a execução a partir do seu início, como se mostra na Figura 4. Um outro ponto que igualmente se observa nessa figura é que os comandos podem ser abreviados (note-se o comando r que é reconhecido como run). Jorge Pinto Leite Página 7 de 8

1: i = 6 (gdb) r The program beeing debugged has been started already. Start it from the beginning? (y or n) n Program not restarted (gdb) continue Continuing. Valor de i: 7 Valor de i: 8 Valor de i: 9 Program exited normally. (gdb) quit picasso.dei.isep.ipp.pt> Figura 5 Finalmente, e como visualizado na Figura 5, abandonaríamos o debbuger através do comando quit. Exercício proposto Escreva o programa seguinte: #include <stdio.h> main(void) { int i, j; for(i=1;i<=10;i++) for(j=i+1;j<=i+10;j++) printf( Valor de i: %i Valor de j: %i\n,i,j); } a) Compile o programa utilizando as várias opções de criação de código intermédio do compilador, e observe o output gerado. b) Compile o programa por forma a poder executá-lo com o debbuger c) Execute o programa com o debugger e analise a variação das variáveis i e j Jorge Pinto Leite Página 8 de 8