Como as instruções escritas em linguagem assembly são transformadas em linguagem de máquina?

O objetivo desta aula é dar uma breve introdução à história da computação e passar algumas noções de como funciona um computador moderno. Espera-se que ao fim desta aula você:

  • tenha uma idéia geral da história da computação e dos computadores;
  • tenha uma idéia de como funciona um computador digital;
  • tenha uma noção superficial do que é um programa de computador e de como o computador executa um programa.

Arquitetura de um computador¶

Computadores modernos seguem a chamada arquitetura de von Neumann, segundo a qual um computador é composto de três partes principais, interligadas pelo barramento (bus):

  • Dispositivos periféricos (de entrada/saída, input/output). São dispositivos como teclados, monitores, impressoras, etc., que permitem a entrada e visualização de dados.

  • Memória. Usada para armazenar os dados processados pelo computador. Os dados guardados por um dispositivo de memória são sempre seqüências de bits, isto é, digitos binários 0-1. Assim, podemos pensar que todo dispositivo de memória guarda um número (pequeno ou imenso, a depender da capacidade do dispositivo) escrito em base 2.

    Como as instruções escritas em linguagem assembly são transformadas em linguagem de máquina?
    Tipos de memória

    Existem diversos tipos de memória num computador moderno. O principal tipo de memória utilizada durante a execução de um programa é a memória RAM (random access memory). Um computador moderno possui alguns gigabytes de memória RAM. A memória RAM é uma memória volátil: quando o computador é desligado, os dados nela contidos são perdidos.

    A memória RAM é formada por uma seqüência de células numeradas. Cada célula guarda uma certa quantidade de bits. O conteúdo de uma célula pode ser acessado através do número da célula, seu endereço. O tempo gasto para acessar uma célula não depende de seu endereço, por isso dizemos memória de acesso aleatório (random access).

  • Unidade central de processamento (CPU de central processing unit). Também chamada de processador. A CPU é responsável por executar instruções. Instruções permitem manipular dados na memória do computador através de operações aritméticas e lógicas, como somas, subtrações, comparações entre números, etc. A CPU lê as instruções da memória do computador e pula de uma instrução para a seguinte. Também há instruções que podem mudar qual será a próxima instrução a ser lida pelo processador; tais instruções permitem alterar o fluxo do processamento.

Um exemplo de programa¶

Vejamos um exemplo de programa de computador e de como ele é executado por um processador. Nosso computador imaginário possui uma memória que consiste de células numeradas; a primeira célula é a de índice 0, a segunda a de índice 1, e assim por diante. Cada célula pode guardar 32 bits de informação. Portanto, em cada célula podemos guardar cada um dos números inteiros de 0 a \(2^{32} - 1\).

Nosso processador imaginário pode executar as seguintes instruções:

InstruçãoEfeito
mov num $pos coloca o número num na célula de índice pos
add $pos1 $pos2 soma o número na posição pos2 ao número na posição pos1 e guarda o resultado na posição pos1
dec $pos subtrai 1 do número na posição pos
jz $pos ip pula para a instrução ip se o número na posição de memória pos é zero
jmp ip pula para a instrução ip
nop no operation: não faz nada!

O problema que queremos resolver é o seguinte: somar os números de 1 a 5 e guardar o resultado na posição de memória 500. A seguinte seqüência de instruções (um programa) resolve este problema; note que cada instrução possui um número de 0 a 6:

0:   mov 5     $40     ; Colocamos 100 na célula 40
1:   mov 0     $500    ; Colocamos 0 na célula 500
2:   add $500  $40     ; Somamos o conteúdo da célula 40 à célula 500
3:   dec $40           ; Subtraimos 1 da célula 40
4:   jz  $40   6       ; Se $40 = 0, pulamos para instrução 6
5:   jmp 2             ; Se $40 não é zero, pulamos para 2
6:   nop               ; Neste ponto, $500 = 1 + 2 + 3 + 4 + 5

Note que usamos a célula de memória 40 em nosso programa. Essa escolha foi arbitrária. Cabe ao programador ter certeza de que a célula 40 não guarda nada importante para outros programas rodando no nosso computador.

O programa acima está descrito numa linguagem de programação, uma notação para a descrição de programas de computador que pode ser mais facilmente compreendida por seres humanos.

Simulação do programa¶

Para que nosso programa seja executado ele deve ser carregado na memória do computador. Nosso programa tem 6 instruções, numeradas de 0 a 6. Para iniciar a execução, o processador é instruído (pelo sistema operacional, por exemplo) a ler a instrução de número 0. A partir daí o programa é executado.

Célula 40  Célula 500  Instrução
        ?           ?  mov 5     $40
        5           ?  mov 0     $500
        5           0  add $500  $40
        5           5  dec $40
        4           5  jz  $40   6
        4           5  jmp 2
        4           5  add $500  $40
        4           9  dec $40
        3           9  jz  $40   6
        3           9  jmp 2
        3           9  add $500  $40
        3          12  dec $40
        2          12  jz  $40   6
        2          12  jmp 2
        2          12  add $500  $40
        2          14  dec $40
        1          14  jz  $40   6
        1          14  jmp 2
        1          14  add $500  $40
        1          15  dec $40
        0          15  jz  $40   6
        0          15  nop

Cada linha acima mostra a instrução executada e o conteúdo das células 40 e 500 antes da execução da instrução. Assim, no início, o conteúdo das células é qualquer número que nelas estava contido. Após a execução da primeira instrução, o conteúdo da célula 40 torna-se 5, e assim por diante. Quando chegamos à instrução 6 do programa, a célula 500 contém a soma dos números de 1 a 5.

Desafio

Usando apenas as instruções descritas acima, escreva um programa para o nosso computador fictício que armazena na célula de memória 1 o fatorial do número na célula de memória 0.

Montadores e linguagem de máquina¶

Computadores modernos executam programas em linguagem de máquina (machine code). Cada processador possui uma linguagem de máquina diferente. Nosso programa foi descrito numa linguagem de montagem (assembly language). Para que possa ser executado pelo computador, ele deve ser primeiro transformado para linguagem de máquina. Esse processo de tradução é feito por um montador (assembler).

A linguagem de montagem é muito próxima da linguagem de máquina. Cada instrução que descrevemos é transformada pelo montador numa seqüência de bits diferente que a representa e que pode ser processada pelo processador. Essa tradução é quase direta.

Cada instrução portanto ocupa algumas células de memória. Digamos, por conveniência, que cada instrução de nosso computador simples possa ser expressa com 32 bits. Então cada instrução ocupa uma célula de memória.

Nos computadores modernos (e essa foi também uma idéia de von Neumann) os programas também residem na memória RAM, dividindo lugar com os dados que são processados. Para que um programa seja executado, ele deve ser carregado na memória RAM pelo sistema operacional, que então dirige o processador para a primeira instrução do programa. A partir daí, o processador pula de uma instrução para a seguinte (a não ser quando é desviado por instruções como jmp).

Como ocorre a mudança de um código Assembly para o código de máquina?

A tradução do código Assembly para o código de máquina é feita pelo montador ou assembler. Ele converte os mnemónicos em seus respectivos opcodes, calcula os endereços de referências de memória e faz algumas outras operações para gerar o código de máquina que será executado pelo computador.

Qual programa converte um programa em linguagem assembly para um programa em linguagem de máquina?

Assembler é o montador, um programa que lê o arquivo contendo os mnemônicos da linguagem Assembly e transforma em linguagem de maquina.

Qual a diferença entre Assembly é linguagem de máquina?

A linguagem assembly só é compreendida por seres humanos, não por computadores. Em linguagem de máquina os dados são representados apenas com o auxílio do formato binário (0s e 1s), hexadecimal e octadecimal. Em linguagem assembly, os dados podem ser representados com a ajuda de mnemônicos como Mov, Add, Sub, End etc.

Quem faz a conversão de linguagem de montagem para linguagem de máquina?

A conversão da linguagem simbólica para a linguagem de máquina se chama montagem, e é feito por um programa chamado montador (ou assembler).