Sítio do Piropo

B. Piropo

< Coluna em Fórum PCs >
Volte
20/02/2006

< Computadores XXV: O conjunto de instruções, >
<
primeira parte
>


Agora que conhecemos a arquitetura interna de nossa UCP elementar e o formato de suas instruções, poderemos criar seu conjunto de instruções. Será um modestíssimo conjunto, pois como na coluna anterior “Instruções” decidimos que o código da instrução terá apenas quatro bits, o numero total de instruções não poderá exceder em mais de uma unidade o maior número que “cabe” em quatro bits. Esse número é “1111b” (o “b” do final indicando “binário”), que corresponde a “15d” (“d” de decimal). Portanto nosso conjunto de instruções não poderá ter mais de dezesseis membros.
Porém, para que nosso conjunto de instruções seja funcional (ou seja, para que se possa fazer com ele “alguma coisa que preste”, um programa que execute algo útil) estes dezesseis membros deverão obrigatoriamente conter as instruções essenciais.
Pois aqui estão, agrupadas por tipo, as especificações das dez primeiras instruções de nosso modesto conjunto de instruções, um “instruction set” de apenas dezesseis instruções.
A lista exibe o número da instrução em decimal seguido de seu “formato”, ou seja, do código de quatro bits (o mesmo número, porém expresso em binário) e do operando ou parâmetro (que obrigatoriamente terá oito bits e será um valor, um endereço ou um conjunto de “zeros” nas instruções que não admitem parâmetro) e de uma breve descrição da instrução e uma figura, mostrando a alteração dos registros e conteúdo das posições de memória eventualmente afetados pela execução da instrução.
Quanto à figura, uma observação importante: até agora vínhamos numerando os endereços das posições da memória principal em ordem crescente de baixo para cima. Esta é a ordem natural em que se numeram “pilhas” de coisas, como por exemplo os andares de um edifício. Mas, como logo veremos, a listagem de um programa em linguagem de máquina nada mais é que uma sucessão de conteúdos de posições de memória ordenados. E estamos acostumados a ler e analisar listagens ordenadas “de cima para baixo”. Por esta razão, enquanto estivermos abordando o assunto “linguagens de máquina e assembly”, nossas figuras exibirão as posições de memória principal com os endereços ordenados crescentemente de cima para baixo. No princípio talvez nos pareça um tanto estranho, mas logo veremos como isso facilita acompanhar e analisar um programa.
Isto posto, vamos às instruções.

INSTRUÇÕES DE CONTROLE DE FLUXO: Instruções que interrompem o programa (e nesse caso não tem operando) ou alteram seu fluxo (e nesse caso o operando é um endereço a ser escrito no registrador denominado Ponteiro de Instruções que contém o endereço da próxima instrução a ser executada).

Instrução 00; Formato: {[0000 00000000]}; Descrição: Interrompe o processamento e devolve o controle ao sistema operacional. Esta instrução não tem operando. Os oito bits correspondentes ao operando são preenchidos com zeros.

Figura 1: Instrução [0000]

Instrução 01; Formato {[0001] [endereço]}; Descrição: Executa um salto incondicional no fluxo do programa escrevendo o número de oito bits [endereço] no Ponteiro de Instruções, o que faz com que a próxima instrução a ser executada seja aquela contida na posição de memória cujo endereço é [endereço].

Figura 2: Instrução [0001]

Instrução 02; Formato: {[0010] [endereço]}; Descrição: Executa um salto no fluxo do programa se o conteúdo do ACC for igual a zero escrevendo o número de oito bits [endereço] no Ponteiro de Instruções, o que faz com que a próxima instrução a ser executada seja aquela contida na posição de memória cujo endereço é [endereço]. Se o conteúdo do ACC não for igual a zero a instrução é ignorada e o fluxo do programa não será alterado.

Figura 3: Instrução [0010]

Instrução 03; Formato: {[0011] [endereço]}; Descrição: Executa um salto no fluxo do programa se o conteúdo do ACC for maior que zero (positivo) escrevendo o número de oito bits [endereço] no Ponteiro de Instruções, o que faz com que a próxima instrução a ser executada seja aquela contida na posição de memória cujo endereço é [endereço]. Se o conteúdo do ACC não for positivo (ou seja, se for igual a zero ou negativo) a instrução é ignorada e o fluxo do programa não será alterado.

Figura 4: Instrução [0011]

Instrução 04; Formato: {[0100] [endereço]};  Descrição: Executa um salto no fluxo do programa se o conteúdo do ACC for menor que zero (negativo) escrevendo o número de oito bits [endereço] no Ponteiro de Instruções, o que faz com que a próxima instrução a ser executada seja aquela contida na posição de memória cujo endereço é [endereço]. Se o conteúdo do ACC não for negativo (ou seja, se for igual a zero ou positivo) a instrução é ignorada e o fluxo do programa não será alterado.

Figura 5: Instrução [0100]

Observação: Sim, eu sei que o conteúdo do ACC não parece negativo. Mas pense um pouco: em um sistema numérico onde somente existem “zeros” e “uns” e não há vírgulas, pontos ou sinais, como exprimir um número relativo, ou seja, com “sinal”? Faça uma experiência com valores de quatro bits. Pegue como minuendo (aquilo de onde se vai diminuir) o valor zero (0000b) e como subtraendo (aquilo que será subtraído) o valor um (0001b), ambos expressos em quatro bits. Ora, subtrair “um” de “zero” resulta em “menos um” seja qual for o sistema numérico empregado.
Se você fizer a subtração em binário descobrirá que o resultado é (1111b), mas seria um resultado incompleto, já que o último “vem um” não foi feito porque minuendo e subtraendo têm o mesmo número de bits. Então, para exprimir números relativos em apenas quatro bits vamos convencionar que apenas os três de ordem menos significativa (os três da direita) representarão o valor do número (o “módulo”, ou seja, o número sem sinal), reservando o bit de ordem mais significativa (o último da esquerda) para representar o sinal. Quando este bit for “zero”, o número será positivo, quando for “um” o número será negativo.
Usando esta convenção, o maior número positivo que poderemos representar com quatro bits será (0111b) que corresponde a (+7d). Zero, naturalmente, continua a ser zero (0000b). Agora, faça novamente a subtração: (0000b) – (0001b), cujo resultado, como sabemos, qualquer que seja o sistema, será obrigatoriamente “menos um”. O resultado, em binário, será ainda (1111b). Mas agora sabemos que este número é negativo, pois seu bit mais significativo é “um”.
Mas como saber seu módulo (ou seja, o valor do número “sem sinal”)? A regra é simples: basta trocar cada dígito por seu complemento (ou seja, trocar “zero” por “um” e vice-versa) e somar “um” ao resultado. O complemento de (1111b) é (0000b). Somando um, resulta em (0001b). Portanto o número de quatro bits (1111b) é igual a “menos um” (-1d). Como seria de esperar, já que ele é o resultado de “zero” menos “um”.
Agora, observe o valor contido no ACC da Figura 5. Ele tem doze bits. Se representa um número relativo, há de ser negativo, pois seu bit mais significativo (o último da esquerda) vale “um”. Mas quanto valerá o número? Aplique a regra. O valor contido no ACC é (111111100111b). Seu complemento é: (000000011000b). Somando “um” teremos: (000000011001b). Que, convertido para decimal dará vinte e cinco. O valor (111111100111b) contido no ACC vale, portanto, (-25d).
Parece complicado? Lamento, a culpa não é minha, é complicado mesmo e não conheço  jeito de explicar isto de modo mais simples (confesso que eu mesmo “apanhei” muito até entender essa desgraça). Mas uma coisa é certa: seja qual for o número de bits disponíveis para representar o número, se você reservar o bit mais significativo para representar o sinal e aplicar a regra de conversão (calcular o complemento e somar um) seus resultados darão sempre certo. E se ainda assim isso lhe parece difícil de entender, guarde apenas uma regra simples: quando trabalhamos com números inteiros relativos (aquilo que em inglês se chama de “signed integers”), o valor será positivo se o bit mais significativo for zero e será negativo se o bit mais significativo for um.
Simplificando ainda mais: se o número em binário começa com “zero” é positivo, se começa com “um” é negativo. Mais simples, impossível...

INSTRUÇÕES DE ENTRADA/SAÍDA: Instruções que movem dados entre o Acumulador (ACC) e o mundo exterior através das unidades de entrada e saída (não necessitam de operandos).

Instrução 05; Formato: {[0101 00000000]}; Descrição: Lê um valor no dispositivo de entrada padrão (teclado ou qualquer outro dispositivo de entrada) e o escreve no ACC. Qualquer outro valor eventualmente contido no ACC será sobrescrito. Enquanto não houver um valor na entrada padrão o programa permanece aguardando a entrada de dados pelo usuário. Esta instrução não tem operando. Os oito bits correspondentes ao operando são preenchidos com zeros.

Figura 6: Instrução [0101]

Instrução 06; Formato: {[0110 00000000]}; Descrição: Lê o conteúdo do ACC e o envia para a saída padrão (impressora ou vídeo). O conteúdo do ACC permanece inalterado. Esta instrução não tem operando. Os oito bits correspondentes ao operando são preenchidos com zeros.

Figura 7: Instrução [0110]

INSTRUÇÕES DE MOVIMENTAÇÃO DE DADOS: Instruções que movimentam um valor da posição de memória cujo endereço é [endereço] para o Acumulador (ACC) e vice-versa (cujo operando é um ponteiro, ou endereço da posição de memória que contém o valor) ou que carregam um valor constante no acumulador (cujo operando é o valor a ser carregado).

Instrução 07; Formato: {[0111] [valor]}; Descrição: Escreve o número de oito bits [valor] no ACC.  Qualquer outro valor eventualmente contido no ACC será sobrescrito. [valor] será um número expresso em binário de oito bits.

Figura 8: Instrução [0111]

Instrução 08; Formato: {[1000] [endereço]}; Descrição: Lê o valor contido na posição de memória cujo endereço é o número de oito bits [endereço] e o escreve no ACC. O conteúdo da posição de memória cujo endereço é [endereço] permanece inalterado. Qualquer outro valor eventualmente contido no ACC será sobrescrito.

Figura 9: Instrução [1000]

Instrução 09; Formato: {[1001] [endereço]}; Descrição: Lê o valor contido no ACC e o escreve na posição de memória cujo endereço é o número de oito bits [endereço]. O conteúdo de ACC permanece inalterado. Qualquer outro valor eventualmente contido na posição de memória cujo endereço é [endereço] será sobrescrito.

Figura 10: Instrução [1001]

Hoje, paramos por aqui que a coluna já está suficientemente longa. Na próxima completaremos nosso conjunto de instruções (só faltam seis, as matemáticas e lógicas) e veremos como ele pode ser usado para criar um programa que, apesar de limitado, pode fazer algo de útil. Até lá.

B. Piropo