# Conjunto de instruções

Conjunto de instruções (tradução de instruction set) são as operações que um processador, microprocessador, microcontrolador, CPU ou outros periféricos programáveis suporta, fornece ou disponibiliza para o programador, ou seja, é a representação em mnemônicos do código de máquina, com a finalidade de facilitar o acesso ao componente.

## Componentes

Cada componente possui o seu próprio conjunto de instruções, que é fornecido pelo fabricante, que também costuma fornecer ou disponibilizar um montador assembly, que transforma o conjunto de instruções em código de máquina para ser utilizado pelo componente.
No caso dos processadores, quando o conjunto de instruções for reduzido leva-o a ter o nome de RISC; e se forem complexas, o nome de CISC.
● “Fronteira” entre o projectista e o programador de uma máquina:
– Projectista: fornece os requisitos funcionais de uma CPU
● quantos e quais registadores? quais operações na ULA? qual organização da Unidade de Controle?
– Programador: fornece o modo mais básico de interagir com o hardware do computador
● Nesse nível de programação, é necessário conhecer alguns detalhes internos da máquina: conjunto de registadores, estrutura da memória, tipos de dados disponíveis directam
Projeto do conjunto de instruções:
O projeto de um conjunto de instruções é muito complexo, uma vez que ele afeta muitos aspectos do sistema computacional
Os elementos mais usados no projeto de instruções são :
· Repertório de operações
· Tipos de dados
· Formato das instruções
· Registradores
· Modos de endereçamento
Repertório de operações - quantas e quais as operações que são necessárias e quão complexas elas podem ser
Tipos de dados – quais os tipos de dados sobre os quais as operações são efetuadas
Formato das instruções - comprimento das instruções em bits, número de endereços, tamanho dos vários campos
Registradores - nº e tamanho dos registradores da CPU que podem ser usados e o propósito de cada um
Modos de endereçamento – de que modo o endereço de um operando pode ser especificado

## Sobre

Arquitetura do conjunto de instruções (instruction set architecture - ISA) se distingue da microarquitetura, que é o conjunto de técnicas de design de processadores usado ​​para implementar o conjunto de instruções. Computadores com diferentes microarquiteturas podem compartilhar um conjunto de instruções comum. Por exemplo, o Intel Pentium e o AMD Athlon implementam versões quase idênticas do conjunto de instruções x86, mas com diferentes projetos internos.
O conceito de uma arquitetura distinta do projeto de uma máquina específica, foi desenvolvido por Fred Brooks na IBM durante a fase de projeto do System/360.

## Classificação dos conjuntos de instruções

Um conjunto de instruções complexo (Complex Instruction Set Computer - CISC) tem muitas instruções especializadas, algumas das quais raramente serão usadas ​em programas práticos. Um conjunto reduzido de instruções (Reduced Instruction Set Computer - RISC) simplifica o processador implementando somente as instruções que são frequentemente utilizadas; operações não usuais são implementadas como sub-rotinas, onde o tempo de execução extra é compensado pela sua utilização rara. Teoricamente tipos importantes são o Minimal Instruction Set Computer e o One Instruction Set Computer, mas estes não são implementados em processadores comerciais. Outra variação é o Very Long Instruction Word (VLIW) onde o processador recebe muitas instruções codificadas em uma única palavra de instrução.

## Linguagem de Máquina

A linguagem de máquina é feita a partir de declarações ou instruções simples, é uma representação para instruções em um nível mais baixo. Todo programa é traduzido por uma linguagem de nível mais alto (como Java e C++) para a linguagem de máquina.
Na arquitetura de processamento, uma determinada instrução pode especificar:
* Registradores especiais para aritmética, endereçamento, ou funções de controle;
* Posições de memória específicas ou deslocamentos;
* Modos de endereçamento específico utilizado para interpretar os operandos;
Operações mais complexas são construídas combinando estas instruções simples, que são executadas sequencialmente, ou de outra forma, dirigidas por instruções de controle de fluxo.

### Exemplos de operações primitivas

* Transferência de uma palavra de dados de uma célula para outra;
* Soma de dois operandos, guardando o resultado em um deles ou em um terceiro operando;
* Desvio para outro endereço fora da sequência;
* Teste de condição. Se o teste resultar em true(verdadeiro), desvia para outro endereço;
* Realizar operação lógica “AND” entre dois valores;
* Parar a execução de um programa;
* Transferência de byte da porta de E/S para a MP e vice-versa;
* Substituição do operando por seu valor absoluto.

### Partes de uma instrução

Em arquiteturas tradicionais, uma instrução inclui um código de operação que especifica a operação a ser executada, como adicionar conteúdo da memória para um registrador, tendo zero ou mais operandos especificados, que podem referenciar registradores, posições de memória ou dados literais. Os operandos especificados podem ter modos de endereçamento que determinam o seu significado. Existem arquiteturas com palavra de instrução muito longa(VLIW), que incluem muitos microcódigos, onde múltiplos opcodes e operandos são especificados em uma única instrução.
Alguns conjuntos de instruções não tem um campo de opcode (como Transport Triggered Architectures (TTA) ou a Forth virtual machine), só operando(s). Alguns conjuntos de instruções não têm nenhum campo de operando especificado, como algumas máquinas de pilha.

#### OPCODE

Operation Code: indica ao processador o que fazer e como fazer(qual é a operação a ser executada), é o nome da instrução propriamente dito. Ele indica ao processador quais dados e onde a operação se realizará. Suas especificações e formatos são definidos no conjunto de instruções da arquitetura do processador em questão (que pode ser um processador geral ou uma unidade de tratamento mais especializado).
O tamanho ou comprimento de uma instrução varia muito, de menos de quatro bits em alguns micro controladores a muitas centenas de bits em alguns sistemas VLIW. Processadores usados ​​em computadores pessoais, mainframes e supercomputadores têm tamanhos de instrução entre 8 e 64 bits. A mais longa instrução disponível no x86 é de 15 bytes (120 bits).
Instruções RISC normalmente tem uma largura de instrução fixa (geralmente 4 bytes = 32 bits), enquanto que um conjunto típico de instruções CISC pode ter instruções de comprimento muito variável (1-15 bytes para x86). Instruções de largura fixa são menos complicadas de lidar do que instruções de largura variável, por várias razões (não precisa verificar se uma instrução atravessa uma linha de cache ou o limite virtual da página deb memória, por exemplo), e são, portanto, um pouco mais fácil de otimizar a velocidade.
As instruções que constituem um programa raramente são especificados usando a sua forma numérica (código de máquina), podem ser especificados por programadores que utilizam uma linguagem de montagem, ou, mais comumente, podem ser gerados por compiladores a partir de linguagens de programação.

##### Projeto

O projeto de conjuntos de instruções é uma questão complexa. Houve duas fases da história para o microprocessador. O primeiro foi o CISC (Complex Instruction Set Computer), que teve muitas instruções diferentes. Na década de 1970, no entanto, a IBM fez uma pesquisa e descobriu que muitas instruções poderiam ser eliminadas. O resultado foi o RISC (Reduced Instruction Set Computer), uma arquitetura que utiliza um conjunto menor de instruções. Um conjunto de instruções mais simples pode oferecer o potencial para velocidades mais elevadas, redução do tamanho do processador, e reduzido consumo de energia. No entanto, um conjunto mais complexo pode otimizar as operações comuns, melhorar a eficiência da memória/cache e simplificar a programação.

#### Operando

É o dado que se deseja manipular.
Adicionalmente, em código de máquina, um operando é um valor (um argumento) no qual a instrução, nomeada por um mnemônico, opera. O operando pode ser um registrador, um endereço de memória, uma constante literal, ou um rótulo. Um exemplo simples é:
* MOV DS, AX;
Onde o valor no operando registrador AX deve ser movido para o registrador DS.
Dependendo da instrução, pode haver zero, um, dois ou mais operandos.

##### Instruções com quatro operandos

OPCODE Operando1 Operando2 Operando3 Endereço da próxima instrução.
Exemplo:
* ADD A, B, C, P
C=A+B, onde soma-se A com B e o resultado é guardado em C, e P guarda o endereço da próxima instrução. Uma vantagem é que a instrução é complexa e tem a desvantagem de ocupar muito espaço na MP.

##### Instruções com três operandos

OPCODE Operando1 Operando2 Operando3.
Exemplo:
* ADD A, B, C
C = A + B, onde soma-se A com B e o resultado é guardado em C.
Em CISC torna-se uma única instrução: ADD A, B, C.
Em RISC as instruções aritméticas usam apenas registradores, são necessários 2 operandos explícitos e instruções de load/store.
C = A + B tem quatro instruções.
Ao contrário de 2-operandos ou 1-operando, ele deixa todos os três valores (A, B e C) nos registradores para posterior reutilização.

##### Instruções com dois operandos

OPCODE Operando1 Operando2.
Exemplo:
* ADD A, B
A = A + B, onde soma-se A com B e o resultado é guardado em A.
Muitas máquinas CISC e RISC se enquadram nesta categoria.
CISC - Muitas vezes as máquinas estão limitadas a um operando de memória por instrução, isto requer load/store para qualquer movimento de memória, independentemente se o resultado é armazenado em um local diferente (C = A + B) ou a mesma localização de memória (A = A + B).
C = A + B tem três instruções.
RISC - Exige cargas de memória de forma explícita, as instruções seriam:
* LOAD A, Reg1
* LOAD B, Reg2
* ADD Reg1, Reg2
* STORE Reg2, C
C = A + B tem quatro instruções.

##### Instruções com 1 operando

OPCODE Op1
Chamadas de máquinas de acumulador, pertence aos primeiros computadores e muitos microcontroladores. Um registrador específico é utilizado para essa instrução: ACC, ele é um operando implícito.
Exemplo:
* ADD Op → ACC = ACC + Op.
C = A + B tem três instruções:
* LOAD A
* ADD B
* STORE C

##### Instruções com zero operando

Não possui operandos, utiliza PILHA.
Todas as operações aritméticas ocorrer usando o topo ou duas posições na pilha (topo e segunda posição).
Exemplo:
* C = A + B
Tem quatro instruções:
* PUSH A
* PUSH B
* ADD
* POP C

#### Modo de Endereçamento

Os vários modos de endereçamento que são definidos em um conjunto de instruções definem como a linguagem de máquina identifica o operando (ou operandos) de cada instrução. Um modo de endereçamento especifica a forma de calcular o endereço de memória de um operando.
Arquiteturas de computadores diferentes variam muito quanto ao número de modos de endereçamento. Existem alguns benefícios ao se utilizar modos de endereçamentos mais simples, um deles é a maior facilidade de implementar pipelines.
Alguns exemplos de modos de endereçamento:

##### Modo Imediato

Método simples e rápido, o valor do campo operando é o próprio dado.
Intel Pentium e AMD Athlon usam algumas instruções de modo imediato: desvio, movimentação, operações aritméticas com constantes, etc.
Exemplo:
* MOV AX, 14H
Copiar o valor hexadecimal 14 para o registrador AX.

##### Modo Direto

O valor do campo operando indica o endereço do dado. Requer apenas uma referência à memória principal para busca-lo.
Exemplo:
* MOV AY,[8077h]
É movido o valor do campo de endereço [8077h] para AY, apenas o valor da memória pode ser alterado mas não o endereço.

##### Endereçamento por Registrador

O operando aponta para um registrador, o qual contém o dado ou pode apontar para um registrador no qual contém um endereço de memória (ponteiro) onde está o dado.
Exemplo:
* MOV AL,BX
É movido o registrador BX para o registrador AL.

##### Endereçamento por Registrador Indireto

Permite acessar a memória indiretamente através de um registrador.
Exemplo:
* MOV AX,[BP]
É movido o endereço da memória [BP] para o registrador AX.

##### Modo Indexado

Os deslocamentos gerados por este modos de endereçamento é a soma da constante e do registrador especificado.
Exemplo:
* MOV AL,[BX+015]
É movido a soma do registrador com a constante [BX+015] para o registrador AL.