Estudando o processo de compilação e interpretação

Esse post faz parte das minhas anotações de estudo, estou postando para poder conversar sobre o tema com pessoas mais experientes e observar o que eu entendi de forma correta e os conceitos que devo rever.

O processo de "tradução" de código de uma linguagem de programação de alto nível (como C#, Java, C, etc...) para a linguagem de máquina pode ser realizado de diferentes formas. A que estarei abordando mais a fundo é feita através de um software chamado compilador.

Compilando em C

O compilador é responsável por fazer o meio de campo entre o código que escrevemos e as instruções que a máquina realmente entende. Ele está em umas fases de transformação de um arquivo texto para um executável em uma máquina. Na linguagem C (segundo o livro "C: Como Programar"), existem 6 fases:

Fase 1: Criação de um programa

Essa é a fase de escrita do código em um editor de texto. O código é escrito e salvo em um dispositivo de armazenamento com nome terminando com a extensão .c.

Fase 2: Pré-processamento

O pré-processamento é feito pelo programa pré-processador C, que faz algumas manipulações necessárias antes de compilar o programa, geralmente consiste na inclusão de outros arquivos de texto. O pré-processador é executado automaticamente ao ser enviado o comando para compilar.

Fase 3: Compilação

Depois do pré-processamento, é realizada a compilação do programa, que consiste em traduzir o programa em C para um código objeto.

O termo "código objeto" aqui é importante. Diferentes linguagens possuem implementações diferentes do que é esse código objeto. Em C, o código objeto é em linguagem de máquina. No entanto, em C# ou em Java, o código objeto é em uma linguagem intermediária.

Fase 4: Link

Nessa fase, um linker faz a ligação entre o código objeto gerado pela compilação e as bibliotecas utilizadas no programa. Em um sistema linux, o comando para compilar e linkar o programa é chamado de cc.


cc index.c 

Esse comando irá compilar e linkar o programa e como retorno é produzido um arquivo chamado a.out, que é a imagem executável do programa "index.c".

Para compilar o arquivo ".c" no Windows, baixei o MinGW, que tem compiladores para várias linguagens. Segui o seguinte tutorial:

Compilando e executando C e C++ no Windows

Fase 5: Carregamento

O loader pega a imagem executável e a transfere para a memória, junto com componentes de bibliotecas compartilhadas.

Fase 6: Execução

O computador executa o programa, uma instrução por vez.

Aqui, a informação importante desse processo é que a compilação é realizada por completo antes da execução do programa. Isso garante que grande parte dos possíveis erros na escrita ou na lógica de um programa sejam identificados antes da execução.

Interpretação

Uma outra abordagem para esse processo de "tradução" é a interpretação. Ele é famoso atualmente, por ser comumente usado em linguagens de script, como Python ou JavaScript.

O interpretador é um software que traduz as instruções em linguagem de alto nível para código de máquina durante a execução de um programa. Ele pega pequenas partes de código e as traduz e executa diretamente.

Nesse caso, os erros são identificados durante a execução do programa.

Comumente, linguagens que têm a sua implementação mais comum de forma interpretada tendem a ter a sua execução mais lenta do que as compiladas. A linguagem de código alto pode ser código de máquina ou outro tipo de linguagem intermediária.

Agradecimento e comentário

Quero estudar mais a fundo a Just In Time Compilation (JIT), pois ainda me deixa um pouco confuso. Espero ter contribuído e ouvir feedbacks para esse ainda estagiário tentando se encontrar.

Há controvérias: https://www.tabnews.com.br/maniero/67b181b2-065d-4553-8505-babac914f06f

O kht tem uma ideias sobre isto e já postou aqui antes.

Observou? Faz sentido para você?

Espero ter ajudado. Em geral estou à disposição na plataforma (sem abusos :D)


Farei algo que muitos pedem para aprender a programar corretamente, gratuitamente. Para saber quando, me segue nas suas plataformas preferidas. Quase não as uso, não terá infindas notificações (links aqui).

Vou deixar aqui alguns recursos para estudar sobre JIT mais a fundo, o primeiro usa o Lua como exemplo, a primeira linguagem a usar um JIT, bastante simples. Os outros dois são sobre o interpretador de JS do Firefox, uma das implementaçoes de JIT, mais complexas (e eficientes) já feitas.

https://www.researchgate.net/publication/220799122_Dynamic_interpretation_for_dynamic_scripting_languages

https://www.cs.cornell.edu/courses/cs6120/2020fa/blog/tracemonkey/

https://static.aminer.org/pdf/PDF/000/286/022/profile_driven_generation_of_trace_samples.pdf

Se quiser se aprofundar e até praticar tem esse canal aqui sobre NASM, você vai fazer tudo isso aí, linkar, compilar, etc. Entender instrução de máquina, entender assembler (montador), entender assembly (a linguagem)... https://www.youtube.com/playlist?list=PLXoSGejyuQGohd0arC7jRBqVdQqf5GqKJ