Buscar

Introdução à Arquitetura de Computadores

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 21 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 21 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 9, do total de 21 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Prévia do material em texto

Introdução à Arquitetura de Computadores
Conteúdo
1 Capa 1
2 Introdução 2
2.1 O Que é Arquitetura de Computadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
2.2 Computadores e as Várias Camadas de Abstração . . . . . . . . . . . . . . . . . . . . . . . . . . 2
3 Modelo de Von Neumann 4
4 O que é o MIPS? 5
4.1 O Processador MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
4.2 A Filosofia do Projeto do MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
5 Instruções do MIPS 6
5.1 Instruções Aritméticas Simples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
5.2 Instruções de Operadores Lógicos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
5.3 Instruções de Uso de memória . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
5.4 Instruções de Controle de Fluxo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
5.5 Instruções de Comparações . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
5.6 Resumo dos Modos de Endereçamento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
6 Representação das Instruções 9
6.1 As Instruções Tipo R . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
6.2 As Instruções Tipo I . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
6.3 As Instruções Tipo J . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
7 As Pseudo-Instruções 10
7.1 A Pseudo-Instrução move . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
7.2 A Pseudo-Instrução Load Address . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
8 Suporte à Funções 11
8.1 As Etapas Necessárias para Invocar Funções . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
8.2 Instruções de Uso de Funções: jal e jr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
8.3 Funções com Muitas Variáveis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
8.4 Funções Recursivas e Sub-Funções . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
i
ii CONTEÚDO
9 Representação Numérica 13
9.1 Números Naturais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
9.2 Números Inteiros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
9.3 Números Reais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
9.4 Overflow e Underflow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
10 As Operações da Unidade Lógica Aritmética 15
10.1 A Adição e Subtração . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
10.2 A Multiplicação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
10.3 Fontes, contribuidores e licenças de texto e imagem . . . . . . . . . . . . . . . . . . . . . . . . . 18
10.3.1 Texto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
10.3.2 Imagens . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
10.3.3 Licença . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
Capítulo 1
Capa
Introdução à Arquitetura de Computadores
1
Capítulo 2
Introdução
2.1 O Que é Arquitetura de Com-
putadores
A Arquitetura de Computadores é o projeto concei-
tual e fundamental da estrutura operacional de um sis-
tema computacional. Ela é o estudo dos requisitos ne-
cessários para que um computador funcione e de como
organizar os diversos componentes para obter melhores
desempenhos.
Como computador entendemos qualquer tipo de dispo-
sitivo capaz de receber uma entrada e que retorna uma
saída após realizar uma série de operações com base nos
valores recebidos e armazenados. Existem vários tipos
de computadores. Uma das formas de classificá-los é por
meio das seguintes categorias:
• Desktop: Computadores de baixo-custo e com de-
sempenho razoável para um usuário “comum”.
• Servidor: Máquinas projetadas para ter um desem-
penho considerado bom para uma aplicação muito
grande e complexa ou então para um número muito
grande de operações mais simples. Alguns servido-
res são simples computadores de Desktop melhora-
dos. Entretanto, existem também aqueles que pos-
suem arquiteturas muito mais sofisticadas que con-
tam com dezenas ou até mesmo centenas de proces-
sadores.
• Sistemas Embarcados: Possuem um uso dedi-
cado à uma única tarefa e normalmente vem em-
butidos em outros aparelhos como celulares, micro-
ondas, elevadores ou veículos. Possuem uma En-
trada/Saída muito simples.
Os princípios estudados em Arquitetura de Computa-
dores são fundamentais para se projetar máquinas real-
mente eficientes.
2.2 Computadores e as Várias Ca-
madas de Abstração
Computadores são aparelhos extremamente complexos.
Para compreender o seu funcionamento, precisamos en-
tender várias camadas de abstração diferente.
A camada mais baixa de todas é aquela formada por tran-
sistores, tensão e corrente elétrica. Quem costuma li-
dar com esta camada são físicos e engenheiros elétricos.
Nesta camada estuda-se o funcionamento de transistores
e circuitos sempre levando em conta as propriedades fí-
sicas da corrente elétrica. Abaixo vemos um desenho re-
presentando um transistor.
Uma camada acima, estão as portas lógicas - todas elas
compostas por transistores. Neste nível estuda-se como
criar estruturas mais complexas combinando-se as diver-
sas portas como AND, OR e NOT para criar estruturas
como multiplexadores, flip-flops e somadores. Neste es-
tágio pode-se usar linguagens como o Verilog ou VHDL
para programar circuitos. Abaixo vemos desenhos que
representam várias portas lógicas:
2
2.2. COMPUTADORES E AS VÁRIAS CAMADAS DE ABSTRAÇÃO 3
Subindo mais um nível de abstração, começamos a lidar
com estruturas mais complexas como registradores e uni-
dades lógicas aritméticas - todas compostas por muitos
flip-flops, somadores e multiplexadores. Vemos como
todas essas estruturas realmente geram as instruções de
cada máquina e como cada instrução funciona. É neste
nível que costuma trabalhar um Arquiteto. Este será
o nível que será abordado ao longo deste Wiki-livro.
Abaixo mostramos a imagem de uma Unidade Lógica
Aritmética - estrutura usada por computadores para re-
alizar cálculos:
Um nível além, estuda-se como combinar as instruções da
camada anterior para realizar comandos mais sofisticados
como as operações da lingüagem C e como coordenar o
funcionamento de um sistema operacional por meio de
interrupções e outros recursos. A imagem abaixo é um
diagrama que representa o Kernel de um Sistema Opera-
cional sendo usado como um meio de comunicação entre
o Software e o Hardware:
CPU Memory Devices
Kernel
Applications
Acima desta camada, está o estudo do funcionamento de
funções de bibliotecas, APIs e a programação de aplica-
tivos e programas de computador simples.E finalmente,
na camada de abstração mais superior está o funciona-
mento de um programa de computador do ponto de vista
do usuário. Como utilizar um aplicativo já criado.
Capítulo 3
Modelo de Von Neumann
Modelo de Von Neumann
O modelo de arquitetura de computadores conhecido
comoModelo de Von Neumann é uma forma de organi-
zação genérica dos componentes de um sistema computa-
cional digital. Esse modelo de arquitetura de computador
digital proposto por Von Neumann está baseado em três
premissas ou características básicas:
a) os dados e as instruções ficam armazenadas no mesmo
espaço de memória;
b) cada espaço de memória possui um endereço, oqual
será utilizado para identificar a posição de um determi-
nado conteúdo;
c) as instruções são executadas de forma sequencial.
O modelo de arquitetura proposto por Von Neumann foi
amplamente aceito, e o projeto conceitual do seu modelo
é utilizado nos projetos de praticamente todos os com-
putadores modernos atuais. De forma geral, o modelo de
Von Neumann consolidou a divisão entre dois importan-
tes conceitos que são hardware e software. Pois o projeto
conceitual de computador digital proposto por esse mo-
delo utiliza o conceito de programa armazenado na me-
mória, juntamente com os dados que serão manipulados,
ou seja, utiliza uma seqüência ordenada de instruções que
conhecemos como software, independente do hardware.
A arquitetura de Von Neumann é composta por: Memó-
ria; CPU, que contém os registradores, Unidade aritmé-
tica e lógica, e Unidade de Controle (CU); E ainda os
dispositivos de entrada e saída para comunicação com o
meio externo. A figura abaixo ilustra como estão interco-
nectados os componentes do modelo de Von Neumann:
Os componentes do modelo de Von Neumann
comunicam-se através de uma estrutura interna co-
nhecida como barramento, que operam a velocidades
altíssimas interligando os principais componentes do
modelo.
4
Capítulo 4
O que é o MIPS?
4.1 O Processador MIPS
O MIPS é o nome de uma arquitetura de processadores
baseados no uso de registradores. As suas instruções tem
à disposição um conjunto de 32 registradores para rea-
lizar as operações. Entretanto, alguns destes registrado-
res não podem ser usados por programadores, pois são
usados pela própria máquina para armazenar informações
úteis.
Processadores MIPS são do tipo RISC (Reduced Instruc-
tion Set Computer - ou seja, Computadores com Con-
junto de Instruções Reduzidas). Isso significa que existe
um conjunto bastante pequeno de instruções que o pro-
cessador sabe fazer. Combinando este pequeno número,
podemos criar todas as demais operações.
Pela sua elegância e simplicidade, processadores MIPS
são bastante usados em cursos de arquiteturas de muitas
universidades. Ele é considerado um processador bas-
tante didático.
ProjetosMIPS são atualmente bastante usados emmuitos
sistemas embarcados como dispositivos Windows CE,
roteadores Cisco e video-games como o Nintendo 64,
Playstation, Playstation 2 e Playstation Portable.
4.2 A Filosofia do Projeto doMIPS
Quando oMIPS estava sendo desenvolvido, quatro regras
foram definidas para guiar o projeto. Elas são a filosofia
do MIPS:
• A simplicidade favorece a regularidade.
• Omenor é (quase sempre) mais rápido. Levando
em conta que uma corrente elétrica se propaga cerca
de um palmo por nanosegundo, circuitos simples são
menores e portanto, mais rápidos.
• Um bom projeto demanda compromissos.
• O caso comum DEVE ser mais rápido. É muito
melhor tornar uma instrução que é usada 90% do
tempo 10% mais rápida do que fazer com que uma
instrução usada em 10% das vezes torne-se 90%
mais rápida. Esta regra é baseada na “Lei de Am-
dahl”.
Foram estas as regras usadas para decidir vários aspectos
do funcionamento do MIPS - incluindo quais seriam suas
instruções e como elas funcionariam.
5
Capítulo 5
Instruções do MIPS
Vamos começar agora a estudar as instruções que exis-
tem em um computador MIPS. Para praticar e testar as
instruções caso você não tenha umamáquinaMIPS é usar
um simulador como o SPIM. O download do simulador
SPIM para Linux, Mac OS, Unix e Windows pode ser
feito no link: .
O objetivo deste capítulo não é fornecer um guia de refe-
rência exaustivo sobre todas as instruções dos MIPS. Ire-
mos apenas apresentar um sub-conjunto mínimo de todas
as instruções do MIPS que são o mínimo necessário para
termos um computador funcionando.
5.1 Instruções Aritméticas Simples
add $r1, $r2, $r3 # Esta instrução soma o conteúdo dos
registradores # $r2 e $r3 colocando o conteúdo no regis-
trador $r1 addi $r4, $r1, 9 # Agora estamos somando o
conteúdo do registrador # $r1 com o valor imediato 9 e
armazenando o # resultado em $r4. O número imedi-
ato deve ter # 16 bits. addu $r5, $r6, $r4 # Quase igual
ao add. Mas agora assumimos que # todos os valores são
não-negativos. addiu $r7, $r8, 10 # Somamos o conteúdo
de $r8 com o valor imediato # 10 e armazenamos o re-
sultado em $r7. Assume-se # que todos os valores são
não-negativos. sub $r1, $r2, $r3 # Subtrai-se o conteúdo
de $r3 do conteúdo de $r2 # e coloca-se em $r1. Tam-
bém existe subi, subu e # subiu que tem comportamento
semelhante a addi, # addu e addiu, mas para a subtração.
5.2 Instruções de Operadores Ló-
gicos
and $r1, $r2, $r3 # Realiza uma operação AND bit-a-bit
entre $r3 e $r2. # O resultado é armazenado em $r1. andi
$r1, $r2, 42 # Realiza uma operação AND bit-a-bit entre
$r2 e o valor # imediato 42. O resultado é armazenado
em $r1. O número # imediato deve caber em 16 bits. or
$r1, $r2, $r3 # Realiza uma operação OR bit-a-bit entre
$r3 e $r2. # O resultado é armazenado em $r1. ori $r1,
$r2, 42 # Realiza uma operação OR bit-a-bit entre $r2 e
o valor # imediato 42. O resultado é armazenado em $r1.
O número # imediato deve caber em 16 bits.
Podemos notar que as instruções seguem uma lógica
clara. Até agora todas seguem uma mesma lógica. Além
destas, não existem instruções mais complexas como po-
tências ou raízes quadradas.Somente as operações mate-
máticas mais simples são representadas. Podemos ver
aquelas 4 regras que formam a filosofia do projeto do
MIPS em ação.
5.3 Instruções de Uso de memória
As instruções do uso da memória seguem uma lógica di-
ferente das instruções de operações aritméticas. Pra co-
meçar, existem três tipos de instruções capazes de copiar
dados da memória para os registradores.
lw $r1, 4($r2) # Load Word: Esta instrução carrega uma
palavra (estrutura de 4 bytes) # localizada no endereço
representado pela soma do valor # armazenado no regis-
trador $r2 mais 4. O resultado é armazenado em $r1. lh
$r1, 6($r3) # Load Half: Esta instrução carrega uma es-
trutura de 2 bits localizada # no endereço representado
pela soma do valor armazeado no # registrador $r3 mais
o número 6. O resultado é armazenado em $r1. lb $r1,
16($r2)# Load Byte: Esta instrução carrega um byte (8
bits) localizado no # endereço representado pela soma do
valor armazenado em $r2 mais o # número 16. O resul-
tado é armazenado em $r1.
Perceba que desta forma é rápido de carregar o conteúdo
de um valor em um vetor. Basta saber o endereço do va-
lor inicial do vetor e o índice de sua posição. Por exem-
plo, suponha que eu possua um vetor de caracteres char
vetor[5]. Supondo que o registrador $r1 contenha o en-
dereço de vetor[0], para armazenar o valor de vetor[3]
no registrador $r2 e assumindo que cada caractere possui
um byte, basta usar a seguinte instrução:
lb $r2 24($r1)
Colocamos o 24 lá porque cada caractere ocupa 8 bits e
queremos pegar o quarto caractere da seqüência. Logo,
precisamos nos deslocar 24 bits para acharmos o carac-
tere certo. Afinal, a distância entre o primeiro elemento
do vetor armazenado em $r1 e o quarto item do vetor é
6
5.4. INSTRUÇÕES DE CONTROLE DE FLUXO 7
de 24:
[0][ ][ ][ ][ ][ ][ ][ ].[1][ ][ ][ ][ ][ ][ ][ ].[2][ ][ ][ ][ ][ ][
][ ].[3][ ][ ][ ][ ][ ][ ][ ]
Para armazenarmos conteúdo de um registrador na me-
mória também existem 3 comandos:
sw $r1, 4($r2) # Store Word: Esta instrução carrega uma
palavra (estrutura de 4 bytes) # localizada no registrador
$r1 e armazena no endereço representado # pela soma
do valor armazenado no registrador $r2 mais 4. sh $r1,
4($r2) # Store Half: Esta instrução carrega uma estrutura
de 2 bits # localizada no registrador $r1 e armazena no
endereço representado # pela soma do valor armazenado
no registrador $r2 mais 4. sb $r1, 4($r2) # Store Byte:
Esta instrução carrega um byte (8 bits) # localizado no
registrador $r1 e armazena no endereço representado #
pela soma do valorarmazenado no registrador $r2 mais
4.
Vamos ver um exemplo de conversão de um código es-
crito em C para a lingüagem Assembly do MIPS assu-
mindo que um int da lingüagem C tenha 4 bits:
/* CÓDIGO C */ typedef struct A{ int x; int y; int z; int
w; }aType; aType V[16]; (...) aPtr = &(V[3]); m = aPtr
-> y; n = aPtr -> w; aPtr -> x = m + n;
Vamos assumir que o vetor V esteja no endereço
0x0800.0000. A estrutura aType é formada por 4 valo-
res numéricos consecutivos, cada um com 4 bits. Logo,
cada aType ocupa 16 bits (4*4). Ou, em hexadecimal,
0x010 bits. Veja uma representação de um aType como
é armazenado na memória:
[x][x][x][x][y][y][y][y][z][z][z][z][w][w][w][w]
Temos um vetor com 16 estruturas como esta chamado
V. Logo, o vetor ocupa um espaço de 256 bits. Com es-
tas informações, concluímos que o código em Assembly
necessário para fazer a operação mostrada no código em
C mostrado acima é:
la $r1, 0x0800.0030 # A instrução Load Address carrega
em $r1 o endereço de V[3]. Falaremos sobre o la depois.
lw $r2, 4($r1) # Carregamos para $r2 o quarto bit à partir
de V[3]. Ou seja, o valor de y. lw $r3, 12($r1) # Agora
carregamos para $r3 o valor do inteiro w. add $r4, $r2,
$r3 # Somamos os valores de y e w colocando o valor em
$r4. sw $r4, 0($r1) # Colocamos o valor da soma no lugar
do x.
5.4 Instruções de Controle de
Fluxo
Agora veremos instruções capazes de controlar o fluxo de
execução de instruções de um computador. A primeira
delas é a instrução beq, ou Branch if Equal:
beq $r1, $r2, DESTINO
Oque esta instrução faz é verificar se o valor de $r1 é igual
à $r2. Caso isso seja verdadeiro, ela muda o valor do re-
gistrador PC (Program Counter) que guarda o endereço
da próxima instrução a ser executada. Se o valor passado
como destino for 0, nada acontece. Nenhuma instrução
é pulada, o programa executa a próxima instrução nor-
malmente, independente de $r1 == $r2 ser verdadeiro ou
falso. Se o valor passado for “1”, pula-se uma instrução
se $r1 for igual a $r2. Se o valor passado for “2”, pulam-
se duas instruções e assim por diante. Também pode-se
passar valores negativos. Um valor de "−1” faz com que
o programa entre em um loop infinito, nunca mais pas-
sando para a próxima instrução. Uma "−2” faz com que
voltemos uma instrução anterior, e assim por diante.
Entretanto, o valor de DESTINO só pode ser no máximo
um valor com 16 bits. Com um valor destes, só pode-
mos pular no máximo cerca de 32 000 instruções para
frente ou para trás. Isso não é um problema na maio-
ria das vezes é muito raro existir um programa que exija
que você pule uma quantidade tão grande de instruções.
Assumindo que 4 linhas de código e Assembly corres-
pondem a 1 linha em código C, para que pulemos uma
quantidade tão grande de instruções, teríamos que fazer
um if com um bloco com mais de 8.000 linhas de có-
digo. Isso é algo extremamente difícil de ocorrer em um
programa real.
Mas caso você realmente precise pular mais de 32 000
instruções, isso é perfeitamente possível, desde que você
altere antes o valor do registrador PC. Com isso, perde-se
um pouco de desempenho, mas torna desvios de código
extremamente grandes possível. E o importante é que o
caso comum (programas em C com blocos menores de
8.000 linhas) roda mais rápido (regra 4 da Filosofia de
Projeto do MIPS).
Além do beq, temos também o bne, ou Branch if Not
Equal:
bne $r1, $r2, DESTINO
Ele funciona da mesma forma que o beq. A diferença é
que ele pula um determinado número de instruções so-
mente se o valor dos dois registradores for diferente.
E finalmente, temos a instrução j, ou Jump:
j ENDEREÇO
Ele faz com que o programa passe a executar a instrução
que é encontrada no endereço dado. O endereço passado
para a instrução j é sempre um número de 26 bits. Entre-
tanto, os endereços da máquina sempre são números de
32 bits. Então como será possível saber qual o endereço
em que está a instrução desejada?
É muito simples. Instruções sempre estarão em ende-
reços múltiplos de 4. Então sabemos que os dois últi-
mos bits do endereço são sempre 0. Não precisamos
armazená-los. Já os dois primeiros bits, retiramos do
PC, pois é sempre muito mais provável que nós usemos o
controle de fluxo para saltar para uma posição não muito
distante. Caso precisemos saltar para um posição muito
8 CAPÍTULO 5. INSTRUÇÕES DO MIPS
distante, basta alterarmos o valor do PC primeiro. Da
mesma forma que foi visto no beq, o caso comum exe-
cuta mais rápido desta forma. Isso é muito bom, mesmo
que tenhamos mais trabalho e perda de desempenho nas
pouquíssimas vezes nas quais precisamos dar saltos muito
longos.
5.5 Instruções de Comparações
Por fim, precisamos ver ainda instruções de comparação.
Um exemplo é o slt, ou Set Less Than:
slt $r1, $r2, $r3
Ela armazena 1 em $r1 se $r2 < $r3 e 0 caso contrário.
5.6 Resumo dos Modos de Endere-
çamento
Nas instruções do MIPS podemos representar os endere-
ços de dados das seguintes formas:
• A Registrador: Representamos o dado passando o
nome do registrador no qual ele está contido. Ex:
add $r1, $r2, $r2.
• Base-Deslocamento: Representamos o dado pas-
sando o endereço de um vetor no qual ele está e a
quantidade de bits a serem deslocados. Ex: lw $r5,
4($r65).
• Imediato: Passamos o dado escrevendo o seu valor
imediato. Ex: addi $r1, $r2, 456.
• Relativo ao PC: Passamos o dado descrevendo o
seu valor relativo ao endereço da instrução atual. Ex:
beq $r1, $r2, DESTINO.
• Absoluto: passamos o valor informando o seu en-
dereço (pseudo-)absoluto. Ex: j DESTINO.
Existem apenas estas 5 formas de endereçamento no
MIPS. Através delas, efetuamos todas as operações ne-
cessárias.
Capítulo 6
Representação das Instruções
Sabemos que tudo dentro do computador é representado
por meio de bits - que podem ter o valor de 0s e 1s. Até
mesmo as instruções de um processador MIPS. Vamos
estudar agora como uma instrução é representada a ní-
vel de bits. O MIPS reconhece 3 famílias diferentes de
instruções. São elas:
6.1 As Instruções Tipo R
Como exemplo de instruções do tipo R vistas, temos:
add, addu, sub, subu, or e and.
Elas são codificadas da seguinte forma:
[o][o][o][o][o][o] - [u][u][u][u][u] - [t][t][t][t][t] -
[d][d][d][d][d] - [s][s][s][s][s] - [f][f][f][f][f][f]
Onde a letra “o”, representa o opcode, ou Código de Ope-
ração. Ele avisa mais-ou-menos o que a instrução vai fa-
zer. Por exemplo, uma instrução de soma add é muito
semelhante à instrução xor que faz um XOR lógico bit-a-
bit. A única diferença é que na soma, devemos armazenar
um bit a mais para representar o “vai um” quando soma-
mos 1+1. Logo, as duas instruções tem o mesmo opcode.
As letras “u” e “t” representam os operandos das instru-
ções. Ou melhor, os registradores nos quais estão os ope-
randos.
A letra “d” é o registrador de destino onde deve ser arma-
zenado o resultado.
A letra “s” ou Shampt representa o deslocamento de bits,
ou seja um shift que pode se usado após a operação.
Finalmente, a letra “f” é o código de função. É por meio
dela que diferenciamos instruções semelhantes que tem o
mesmo opcode, como add e or.
6.2 As Instruções Tipo I
Como exemplo deste tipo de instrução, podemos citar to-
das aquelas que contam com um valor imediato, como
addi, subi, ori, beq e bnq.
Eles são codificados da seguinte forma:
[o][o][o][o][o][o] - [u][u][u][u][u] - [t][t][t][t][t] -
[i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i]
A letra “o” representa o código da instrução. A letra “u”
represeenta o número do registrador onde a o resultado da
operação é colocado. Já a letra “t” representa o número
do registrador em que está um dos operandos. Já o “i”
representa o número imediato. Agora vemos o porquê do
valor passado como imediato nunca poder exceder os 16
bits.
6.3 As Instruções Tipo J
A única instrução vista no capítulo anterior do tipo J é a
j. Ela é codificada da seguinte forma:
[o][o][o][o][o][o] - [d][d][d][d][d][d][d][d][d][d][d][d][d][d][d][d][d][d][d][d][d][d][d][d][d][d]O “o” representa o código da operação j e d representa o
destino.
9
Capítulo 7
As Pseudo-Instruções
A linguagem Assembly de uma máquina costuma ser um
reflexo direto de como são implementadas as instruções
de um determinado processador. Entretanto, nem to-
das as instruções que temos à disposição quando pro-
gramamos em Assembly são instruções verdadeiras para
o processador. Algumas delas são na verdade pseudo-
instruções.
Pseudo-instruções costumam ser substituídas pelo mon-
tador ao gerar instruções para o computador na forma
de Lingüagem de Máquina. Pseudo-Instruções são na
verdade combinações de mais de uma instrução. Veja-
mos agora alguns exemplos:
7.1 A Pseudo-Instrução move
move $r1, $r2 # Copia o conteúdo do registrador $r2 para
$r1
Ela é na verdade implementada da seguinte forma:
addu $r1, $r0, $r2 # Soma $r2 com zero e coloca o resul-
tado em $r1
O registrador $r0 usado acima não é um registrador co-
mum. Ele sempre possui o valor “0” e é um dos poucos
registradores cujo valor nunca pode ser alterado pelo pro-
gramador.
7.2 A Pseudo-Instrução Load Ad-
dress
la $r1, ENDEREÇO # Coloca o valor numérico de 32
bits “ENDEREÇO” em $r1
Esta instrução é muito útil para fazer registradores rece-
berem o valor de ponteiros para outros locais de memó-
ria. De fato, usamos esta pseudo-instrução no Capítulo
anterior quando convertemos um código em C para o As-
sembly do MIPS. Ela é na verdade implementada desta
forma:
lui $r1, constHI # Carrega-se os 16 bits mais significativos
em $r1 ori $r1, $r0, constLO # Executa-se um OR bit-a-
bit entre o registrador # com os 16 bits mais significativos
e os 16 bits # menos significativos
O que a instrução lui, ou Load Upper Immediate faz é
uma operação shift de 16 bits para a esquerda e coloca
no registrador indicado. Este passo é necessário porque
valores imediatos passados para instruções só podem ter
16 bits por causa da limitação de espaço das instruções
do Tipo I.
Também existe a instrução li, ou Load Immediate que faz
exatamente a mesma coisa que o la.
Note que o montador que remove as pseudo-instruções
e as substitui por instruções que realmente existem no
hardware sempre podem verificar se o valor que quere-
mos carregar no registrador cabe em 16 bits. Neste caso,
a instrução gerada fica bem mais simples e rápida:
addu $r1, $r0, $r2 # Soma $r2 com 0 e coloca em $r1
10
Capítulo 8
Suporte à Funções
Funções são ferramentas muito importantes, pois tornam
código escrito muito mais usável e torna a tarefa de pro-
gramar mais produtiva. Elas permitem que um progra-
mador se concentre em apeenas uma tarefa de cada vez.
Portanto, é essencial que um processador possua suporte
á elas. Veremos como isso ocorre no MIPS.
8.1 As Etapas Necessárias para In-
vocar Funções
Quando queremos chamar uma função, as seguintes eta-
pas devem ser cumpridas:
• O programa principal deve colocar os parâmetros da
função em um local que ela possa acessar.
• O programa principal deve ceder o controle para a
função.
• A função deve coletar todos oos parâmetros deixa-
dos pelo programa principal.
• A função deve executar a tarefa desejada.
• A função deve armazenar seus resultados em um lu-
gar em que o programa principal possa acessar.
• A função deve retornar o fluxo do código para o
ponto imediatamente após ser chamada.
Para que estes requisitos sejam cumpridos, as seguintes
convenções fora criadas:
• Os registradores $r4, $r5, $r6 e $r7 seriam usados
para armazenar parâmetros de funções. Por causa
desta funcionalidade, tais registradores podem ser
chamados pelos seus “apelidos": $a0, $a1, $a2 e
$a3.
• Os registradores $r2 e $r3 seriam usados para as
funções armazenarem seus valores de retorno para
o programa principal. Por isso, eles costumam ser
chamados de $v0 e $v1.
Tais regras são apenas convenções. Nada impede que
um programador as desrespeite e use outros registrado-
res para estabelecer comunicação entre funções e progra-
mas principais. Entretanto, para que um programa funci-
one bem em conjunto com todos os demais, é importante
quee tais convenções sejam seguidas.
Além dos registradores convencionados acima, o regis-
trador $r31 também tem um papel importante. Ele sem-
pre armazena o endereço de retorno para o qual a última
função chamada deve retornar. Por ter uma função tão
importante, este registrador é mais conhecido pelo ape-
lido $ra.
8.2 Instruções de Uso de Funções:
jal e jr
A instrução que usamos para invocar uma função chama-
se jal, ou Jump and Link. Ela é usada da seguinte forma:
jal ENDEREÇO_DA_FUNÇÃO
Entretanto, só devemos chamar esta função depois de já
termos salvo os argumentos nos registradores apropria-
dos.
Depois da função executar todas as operações e salvar
os resultados apropriados em $v0 e $v1, podemos usar
a instrução jr, ou Jump Register. Normalmente usamos
a instrução passando para ela o valor do registrador $ra,
que contém o endereço certo para voltarmos:
jr $ra
Como exemplo de como isso pode ser feito, vamos con-
verter para Assembly o seguinte código em C:
int example(int a, int b, int c, int d){ int f; f = (a + b) - (c
+ d) return f; }
O código no Assembly do MIPS ficaria assim:
example: # Label add $t0, $a0, $a1 # Soma a + b add $t1,
$a2, $a3 # Soma c + d sub $v0, $t0, $t1 # Subtrai os dois
valores e coloca o resultado no registrador de retorno jr
$ra # Retorna o controle para a função principal
Entretanto, observe que para realizarmos os cálculos ne-
cessários, precisamos usar registradores. Ao fazer isso,
11
12 CAPÍTULO 8. SUPORTE À FUNÇÕES
existe o grande risco de apagarmos dados importantes do
programa principal. Para evitar isso, existe uma conven-
ção que diz que os registradores $r8 até $r15, $r24 e $r25
são registradores temporários. Por isso, eles costumam
ser chamados de $t0 até $t9. Após chamar uma função,
o programa principal não deve esperar que os valores des-
tes registradores sejam os mesmos. Somente dados que
estejam nos registradores $r16 até $r23 são sempre pre-
servados entre funções. Por esta razão, tais registradores
permanentes (salvos) são chamados de $s0 até $s7.
8.3 Funções com Muitas Variáveis
Existem funções que podem precisar receber mais do que
4 parâmetros. Entretanto, só temos registradores sufici-
entes para armazenar 4 parâmetros. Nós também pode-
mos querer retornar mais do que os 2 valores permitidos
pelos registradores. Ou então, nossa função pode preci-
sar armazenar mais do que 10 valores temporários. O que
fazer para resolver isso?
Como o espaço dentro de registradores é bastante limi-
tado, só nos resta apelar para a pilha da memória. Por
convenção, o registrador $r29, ou $sp (Stack Pointer) ar-
mazena o endereço na pilha de onde novos valores podem
ser colocados. Acessando seu endereço e alterando-o po-
demos guardar valores na memória. O acesso à pilha da
memória é muito mais lento que o acesso à registradores,
mas este é o único modo de podermos armazenar uma
quantidade muito maior de informação.
Por motivos históricos, a pilha “cresce” sempre dos va-
lores de endereços altos para valores menores. Ou seja,
para alocar espaço para mais valores, precisamos sempre
decrementar o seu valor. Incrementando-o, estamos na
verdade removendo os últimos dados da pilha.
Vamos reescrever agora o código Assembly visto acima,
desta vez preeservando os valores dos registradores $t0 e
$t1 para vermos como ficaria o resultado:
example: # Label addi $sp, $sp, −8 # Alocamos espaço
para dois valores de 4 bits. sw $t1, 4($sp) # Preservamos
o valor de $t1 à partir do 4o bit após o Stack Pointer sw
$t0, 0($sp) # Preservamos o valor de $t0 sobre o Stack
Pointer add $t0, $a0, $a1 # Soma a + b add $t1, $a2,
$a3 # Soma c + d sub $v0, $t0, $t1 # Subtrai os dois
valores e coloca o resultado no registrador de retorno lw
$t0, 0($sp) # Retiramos o valor antigo salvo de $t0 lw $t1,
4($sp) # Retiramosda pilha o valor antigo de $t1 addi $sp,
$sp, 8 # Voltamos o Stack Pointer para a posição original
apagando de vez as variáveis locais jr $ra # Retorna o
controle para a função principal
8.4 Funções Recursivas e Sub-
Funções
Da mesma forma que o programa principal invocou uma
função, uma função também pode invocar outras fun-
ções. Se la for recursiva, ela pode até mesmo invocar clo-
nes de si mesma para realizar uma tarefa. Como imple-
mentar isso sendo que temos apenas um registrador $ra?
Se chamarmos outra função, o $ra original é sobrescrito e
podemos perder a capacidade de voltar ao programa prin-
cipal. Além disso, valores temporários que representam
variáveis locais podem ser perdidos.
A única forma de evitar isso é enviar para a pilha tudo
aquilo que precisa ser salvo - damesma forma que fizemos
com alguns valores no exemplo acima. Para mostrar isso
na prática vamos implementar em Assembly a seguinte
função em C:
/* Calcula Fatorial */ int fat(int n){ if(n < 1) return 1; else
return (n * fat(n - 1)); }
O resultado final é algo como:
fat: # Início da função addi $sp, $sp, −8 # Aloca espaço
na pilha para 2 valores sw $ra, 4($sp) # Guarda valor de
retorno na pilha sw $a0, 0($sp) # Guarda primeiro argu-
mento na pilha slti $t0, $a0, 1 # $t0 = ( $a0 < 1) beq $t0,
$zero, L1 # Se $a0 >= 1, vá para L1 addi $v0, $zero, 1
# Senão, coloque 1 como valor de retorno addi $sp, $sp,
8 # Apague as duas variáveis locais salvas na pilha jr $ra
# Encerra a função L1: addi $a0, $a0, −1 # Se $a >=
1, decremente $a0 jal fat # Chame um clone recursivo
de fat que retorna fat($a0-1) lw $a0, 0($sp) # Recupere
os valores iniciais do parâmetro da função lw $ra, 4($sp)
# Recupere o endereço de retorno antigo addi $sp, $sp,
8 # Apague as duas variáveis locais salvas na pilha mul
$v0, $a0, $v0 # Coloque $a0 * fat($a0 - 1) como valor de
retorno jr $ra # Encerra a função
Por fim, uma última coisa útil que é interessante comentar
é que o Stack Pointer ($sp) pode ser alterado várias vezes
ao longo de uma função. Paramantermemorizado o valor
do endereço da pilha no início da função, costuma-se usar
o registrador $r30 como um Frame Pointer ($fp). Nos
exemplos acima, isso não foi preciso, pois só mudamos o
valor do Stack Pointer no começo e fim de cada função.
Mas em alguns programas utilizar este registrador pode
ser útil.
Capítulo 9
Representação Numérica
Números podem ser representados em qualquer tipo de
base. Humanos costumam representar números na base
decimal. Esta possui este nome por possuir 10 dígitos
diferentes: 0, 1, 2, 3, 4, 5, 6, 7, 8 e 9.
Como computadores só são capazes de reconhecer dois
tipos diferentes de estados, é natural para eles representar
números na base binária. Ou seja, eles só compreendem
os valores “0” e “1”. Vamos ver agora coo podemos re-
presentar diversos tipos de números usando apenas dois
tipos diferentes de sinais.
9.1 Números Naturais
Representar Números Naturais é simples bastante sim-
ples - mesmo quando só podemos usar dois tipos dife-
rentes de sinais. O 0 decimal é representado como 0. O
1 decimal também é representado como 1. Já o 2 deci-
mal é representado com “10”. Enfim, quando contamos
os números naturais na base binária, fazemos da seguinte
forma:
BASE | BINÁRIA | 0 1 10 11 100 101 110 111 1000
1001 1010 | BASE | DECIMAL | 0 1 2 3 4 5 6 7 8 9 10
Quando representamos números desta forma, não temos
números negativos. Logo, nenhum número possui sinal
algum. Por isso, chamamos tais números de unsigned
(sem sinal).
Atualmente, a maioria das máquinas possui representa-
ção numérica 32 bits. Isso significa que seus números
são compostos por 32 dígitos. Com uma representação
destas, o menor número binário sem sinal que podemos
representar é 00000000000000000000000000000000 e
o maior é 1111111111111111111111111111111. Con-
vertemos tais valores para decimal, chegamos à conclu-
são que a maioria dos computadores só lida com números
sem sinal cujo valor esteja entre 0 e 4.294.967.295 - que
são os equivalentes decimais destes números.
Para descobrir qual é o equivalente decimal de um nú-
mero binário de 32 bits, usa-se a fórmula abaixo:
N0 ∗ 232 + N1 ∗ 231 + N2 ∗ 230 + N3 ∗ 229 + (...) +
N29 ∗ 23 +N30 ∗ 22 +N31 ∗ 21 +N32 ∗ 20
ondeN0 é o dígito mais significativo eN32 é o bit menos
significativo.
9.2 Números Inteiros
Nem sempre os números com os quais queremos lidar
são naturais. Pode haver necessidade de realizarmos ope-
rações com números negativos. Para tal, devemos en-
contrar uma forma de representarmos números negati-
vos. Uma das primeiras formas tentadas de fazer isso foi
reservando o primeiro bit de um número para represen-
tar o sinal. Assim, um 0000000 (...) 001 representa +1
e um 10000 (...) 001 representaria um −1. Entretanto,
tal forma de representação já foi abandonada há muito
tempo. Um dos principai motivos para o abandono desta
representação está no fato de sempre termos que verificar
o primeiro bit para descobrir como efetuar uma soma ou
subtração entre dois números. Além disso, tal represen-
tação tornaria possível um "+0” e um "−0”.
A forma de se representar números inteiros em compu-
tadores modernos é chamada de Representação em Com-
plemento de 2. Ela é feita da seguinte forma:
Os 31 bits mais à esquerda representam sempre núme-
ros positivos. Calculamos o que eles representam com a
mesma fórmula vista acima. Entretanto, o primeiro bit
representa sempre “0” se o seu valor for “0” ou "−232 se
o seu valor for “1”. Assim, a fórmula para se calcular o
que representa um número binário inteiro em decimal é:
−N0 ∗ 232 +N1 ∗ 231 +N2 ∗ 230 +N3 ∗ 229 + (...) +
N29 ∗ 23 +N30 ∗ 22 +N31 ∗ 21 +N32 ∗ 20
ondeN0 é o dígito mais significativo eN32 é o bit menos
significativo.
A representação em complemento de 2 é boa pelos se-
guintes motivos:
• Para somar dois números inteiros, usa-se o mesmo
método. Não precisamos verificar o sinal deles.
Com isso, podemos criar um circuito mais rápido.
• Descobrir o inverso de um número também é sim-
ples. Basta invertermos todos os bits e, em seguida,
somarmos 1. Sempre funciona.
13
14 CAPÍTULO 9. REPRESENTAÇÃO NUMÉRICA
• O “0” é sempre “0”. Não existe uma versão negativa
ou positiva deste número.
Por meio desta notação, números tão pequenos como
−4.294.967.296 e tão grandes como 4.294.967.295 po-
dem ser representados.
9.3 Números Reais
Por fim, também é muito útil que computadores possam
representar números reais. Vamos estudar agora como
eles costumam ser representados em computadores.
A forma mais lógica e versátil de representarmos um nú-
mero real é por meio da notação científica. Um número
decimal em notação científica sempre toma a seguinte
forma:
N ∗ 10M
onde N é sempre um número real maior ou igual à 1 e
menor que 10 que pode ser positivo ou negativo enquanto
M é um número inteiro qualquer (que pode ser positivo
ou negativo). Por exemplo:
3, 15756 ∗ 109 representa aproximadamente quantos se-
gundos existe em um século enquanto
1, 00000∗10−9 representa quantos segundos existem em
um nanossegundo.
Alternativamente, podemos representar também núme-
ros em notação científica utilizando uma base binária:
1, 00000 ∗ 10−1 . Lembre-se que aquele “10” significa
na verdadee “2” em representação decimal. Ou seja, o
número representado é na verdade 0,5 e não 0,1.
Enfim, quando temos um número em notação científica
binária, ele sempre tem a seguinte forma:
S ∗ 1, XXXXX ∗ 10Y Y Y Y Y , onde “S” representa o
sinal (que pode ser positivo ou negativo), “XXXXX” são
a parte fracionária do número e “YYYYYY” representa
o expoente.
Então, para representarmos números reais, precisamos
representar no espaço de 32 bits os valores do sinal, fra-
ção e expoente. No MIPS, isso é feito da seguinte forma:
S -- E E E E E E E E -- F F F F F F F F F F F F F F F F
F F F F F F F
O Sinal é representado em um único bit (1 para negativo
e 0 para positivo), o expoente é representado por 8 bitse a fração é representada por 23 bits. Assim, o exemplo
1, 00000 ∗ 10−1 (ou 1/2 em decimal) é representado:
0 -- 1 1 1 1 1 1 1 1 -- 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0
Com esta representação, números quase tão pequenos
como −238 ou quase tão grandes como 238 podem ser
armazenados.
Entretanto, note que a nossa precisão não é perfeita. Exis-
tem muitos números que não podem ser representados
desta forma. Por isso, sempre é preciso realizar arredon-
damentos. E quanto mais operações realizamos, mais er-
ros acabam sendo acumulados. Por essa razão, a mai-
oria dos computadores possui também uma forma mais
precisa de representação de números reais. Essa forma
normalmente ocupa o dobro do espaço do que costuma
ocupar. No MIPS uma representação desti tipo ocupa 64
bits. Ela funciona da seguinte forma:
S -- E E E E E E E E E E E -- F F F F F F F F F F F F F
F F F F F F F F F F F F F F F F F F F F F F F F F F F
F F F F F F F F F F F F
Apesar de gastarmos o dobro do espaço de armazena-
mento desta forma, aumentamos consideravelmente a
faixa de valores representados e a precisão com a qual
podemos representá-los.
9.4 Overflow e Underflow
Overflow é o nome do resultado incorreto ao qual che-
gamos quando tentamos somar números grandes demais
e o resultado não pode ser armazenado e nem represen-
tado em 32 bits. Ele pode ocorrer quando efetuamos as
seguintes operações:
• Somamos dois números positivos
• Somamos dois números negativos
• Subtraímos um número negativo de um positivo.
É de responsabilidade do hardware sempre verificar se
ocorreu um overflow nestes casos. Normalmente, para
fazer a verificação basta conferir os sinais dos números.
Em caso afirmativo, ele deve ativar um sinal de exceção.
O que é feito caso uma excessão seja detectada depende
de cada programa.
O MIPS, por exemplo, sempre armazena o endeereço da
última instrução que gerou excessão em um registrador
especial chamado EPC. A instrução mfc0 (Move from
System Control) é usada para copiar este endereço para
um registrador de propósito geral que pode ser conferido
por algum programa. Cabe ao programador deste pro-
grama decidir o que fazer.
Em lingüagens de alto nível, o comportamento depende
da lingüagem usada. C, por exemplo, ignora todos os
Overflows. Ao contrário de Fortran ou Ada que reque-
rem que o programa sempre seja avisado.
Underflow é o que acontecee quando lidamos com um
número real tão próximo de 0 que o valor do expoente não
pode ser corretamente representado. Quando um pro-
grama requer uma precisão tão grande assim, recomenda-
se o uso de pontos flutuantes de dupla precisão (double)
para evitar este inconveniente.
Capítulo 10
As Operações da Unidade Lógica
Aritmética
Computadores são máquinas de calcular. Logo, é fun-
damental que eles sejam capazes de realizar operações
básicas como adição, subtração, divisão e multiplicação.
Vamos ver agora como tais operações são implementadas
dentro da Unidade Lógica Aritmética de um Processador
(ULA).
10.1 A Adição e Subtração
A Adição é uma das operações mais simples. Um com-
putador realiza ela de uma maneira semelhante à usada
por nós humanos. Ele começa somando os bits menos
significativos. Caso tenha que somar “1” e “1”, o resul-
tado fica sendo “0” e passamos um “vai-um” para o bit à
esquerda. Veja abaixo um desenho de um circuito capaz
de somar dois números de 8 bits:
Embora a imagem mostre apenas um circuito que soma
dois números de 8 bits, não é muito difícil perceber que a
lógica para fazer um somador é a mesma, tanto para nú-
meros com 8 como para 32 bits. Basta adicionar mais so-
madores. Perceba que o circuito também é capaz de de-
tectar a presença de Overflow no caso de operações com
números sem sinal.
Ele pode ser usado tanto para somar números com ou
sem sinal. Graças à representação de números inteiros
por complemento de dois, não é difícil conseguir isso.
O mesmo circuito acima também pode ser reaproveitado
para realizar subtrações. Basta inverter antes todos os bits
do segundo operando e somar 1 à ele. Com isso, estamos
na verdade somando o primeiro operando com o negativo
15
16 CAPÍTULO 10. AS OPERAÇÕES DA UNIDADE LÓGICA ARITMÉTICA
do segundo operando.
10.2 A Multiplicação
Vamos agora estudar como construir um circuito capaz
de realizar multiplicações. Primeiro vamos tentar realizar
umamultiplicação pelo método convencional que usamos
através de papel e caneta. Isso pode nos dar uma pista de
como fazer uma operação de multiplicação. Vamos usar
a base binária:
1000 x1001 ---- 1000 00000 000000 1000000 -------
1001000
Perceba que a multiplicação é um conjunto de somas.
Sempre estamos somando o valor 0 ou o valor do mul-
tiplicador após este passar por uma operação de SHIFT
para a esquerda. O que determina se o que iremos so-
mar é um 0 ou o valor do multiplicador após um SHIFT
são os bits do multiplicando. Se o bit da posição n for
um 0, somamos 0 e se for 1, somamos com o valor do
multiplicando “shiftado” n vezes.
Um exemplo de um circuito seqüencial capaz de somar
dois números de 4 bits é mostrado na imagem abaixo:
Note que multiplicando números de 4 bits, nós precisa-
mos armazenar os 8 bits possíveis para o resultado. Afi-
nal, o resultado de uma multiplicação é capaz de ter o
número de bits igual à soma dos multiplicandos. Máqui-
nas MIPS lidam com o problema dividindo o resultado
pela metade. os bits mais significativos terminam em um
registrador chamadoHi e os menos significativos acabam
em um registrador chamado Lo.
Entretanto, o circuito conformemostrado acima temmui-
tos problemas. O principal é que ele é muito complexo.
Perceba que o circuito para multiplicar número de 4 bits
é pelo menos 3 vezes mais complexo e lento que o usado
para realizar a adição de 8 bits (afinal, o circuito de multi-
plicação precisa realizar a adição de 3 pares de valores de
8 bits). Um circuito destes para calcular a multiplicação
de números com um valor ainda maior de bits seria ainda
mais complexo que isso.
Com isso, chegamos à conclusão que a multiplicação é
uma operação complexa demais para ser efetuada por
meio de uma simples lógica combinacional de portas ló-
gicas. Um circuito de multiplicação combinacional seria
muito caro e esquentaria demais. Por isso, sua velocidade
teria que ser sacrificada aumentando a distância dos tran-
sistores. Por isso, utilizam-se circuitos seqüenciais para
realizar esta operação.
O diagrama abaixo mostra descreve o funcionamento de
um circuito seqüencial capaz de realizar a multiplicação:
O que acontece no diagrama acima no caso de multipli-
carmos dois números de 32 bits é o seguinte:
• 1- O “Produto” é um registrador inicializado em 0.
• 2- O produto e o multiplicando são passados para a
ULA que soma os dois.
• 3- O resultado (o valor do próprio multiplicando)
pode ir para o registrador “Produto” ou não. Quem
toma a decisão é o “Controle”.
• 4- Se o último bit do Multiplicador for “1”, o Con-
10.2. A MULTIPLICAÇÃO 17
trole permite a escrita do registrador “Produto”. Se
for “0”, ele impede.
• 5- OMultiplicando sofre um shift para a esquerda e
o Multiplicador um Shift para a direita.
• 6- Se é a 32a vez que você chega à esta instrução,
encerre. A multiplicação terminou. Caso contrário,
volte ao passo 2.
O diagrama acima já é uma forma bem melhor de multi-
plicarmos. Mas ainda existem otimizaçãoes que podem
ser feitas para acelerarmos ainda mias a multiplicação:
• Podemos utilizar um único registrador de 64 bits
para armazenar tanto o multiplicador como o pro-
duto. O multiplicador vem antes e o produto logo
depois. Assim, cada vez que fazemos um shift para
a direita no multiplicador, aproveitamos o espaço li-
berado mais à esquerda para colocar um novo bit
do produto. Desta forma, não é necessário somar
números de 32 bits, apenas somar o suficiente para
descobrir qual o próximo bit do produto a ser colo-
cado.
• Compiladoressubstituem multiplicação por potên-
cias de 2 por operações de shift que são mais rápi-
das.
Para multiplicações envolvendo números negativos, basta
invetermos os números transformando-os em positivos.
Em seeguida, fazemos a multiplicação normalmente e
observamos os sinais do multiplicador e multiplicando.
Se forem iguais, masntemos os números como positivos.
Caso contrário, convertemos o produto para negativo.
18 CAPÍTULO 10. AS OPERAÇÕES DA UNIDADE LÓGICA ARITMÉTICA
10.3 Fontes, contribuidores e licenças de texto e imagem
10.3.1 Texto
• Introdução à Arquitetura de Computadores/Capa Fonte: http://pt.wikibooks.org/wiki/Introdu%C3%A7%C3%A3o_%C3%A0_
Arquitetura_de_Computadores/Capa?oldid=204857 Contribuidores: Master, Raylton P. Sousa, He7d3r.bot e Anónimo: 1
• Introdução à Arquitetura de Computadores/Introdução Fonte: http://pt.wikibooks.org/wiki/Introdu%C3%A7%C3%A3o_%C3%
A0_Arquitetura_de_Computadores/Introdu%C3%A7%C3%A3o?oldid=276833 Contribuidores: Master, Thiagoharry, Raylton P. Sousa,
He7d3r.bot e Anónimo: 5
• Introdução à Arquitetura de Computadores/Modelo de Von Neumann Fonte: http://pt.wikibooks.org/wiki/Introdu%C3%A7%C3%
A3o_%C3%A0_Arquitetura_de_Computadores/Modelo_de_Von_Neumann?oldid=288328 Contribuidores: Lazarochaves
• Introdução à Arquitetura de Computadores/O que é o MIPS? Fonte: http://pt.wikibooks.org/wiki/Introdu%C3%A7%C3%A3o_
%C3%A0_Arquitetura_de_Computadores/O_que_%C3%A9_o_MIPS%3F?oldid=199789 Contribuidores: Master, Thiagoharry, Raylton
P. Sousa, He7d3r.bot, GrooveDog e Anónimo: 2
• Introdução à Arquitetura de Computadores/Instruções do MIPS Fonte: http://pt.wikibooks.org/wiki/Introdu%C3%A7%C3%A3o_
%C3%A0_Arquitetura_de_Computadores/Instru%C3%A7%C3%B5es_do_MIPS?oldid=275828 Contribuidores: Master, Thiagoharry,
Raylton P. Sousa, He7d3r.bot, Kernelsafe, Syum90 e Anónimo: 5
• Introdução à Arquitetura de Computadores/Representação das Instruções Fonte: http://pt.wikibooks.org/wiki/Introdu%C3%A7%
C3%A3o_%C3%A0_Arquitetura_de_Computadores/Representa%C3%A7%C3%A3o_das_Instru%C3%A7%C3%B5es?oldid=199791
Contribuidores: Master, Thiagoharry, Raylton P. Sousa e He7d3r.bot
• Introdução à Arquitetura de Computadores/As Pseudo-Instruções Fonte: http://pt.wikibooks.org/wiki/Introdu%C3%A7%C3%A3o_
%C3%A0_Arquitetura_de_Computadores/As_Pseudo-Instru%C3%A7%C3%B5es?oldid=281434 Contribuidores: Master, Thiagoharry,
Mike.lifeguard, Raylton P. Sousa, He7d3r.bot e Anónimo: 2
• Introdução à Arquitetura de Computadores/Suporte à Funções Fonte: http://pt.wikibooks.org/wiki/Introdu%C3%A7%C3%A3o_
%C3%A0_Arquitetura_de_Computadores/Suporte_%C3%A0_Fun%C3%A7%C3%B5es?oldid=288544 Contribuidores: Master, Thia-
goharry, Raylton P. Sousa, He7d3r.bot e Anónimo: 3
• Introdução à Arquitetura de Computadores/Representação Numérica Fonte: http://pt.wikibooks.org/wiki/Introdu%C3%A7%
C3%A3o_%C3%A0_Arquitetura_de_Computadores/Representa%C3%A7%C3%A3o_Num%C3%A9rica?oldid=199790 Contribuido-
res: Master, Thiagoharry, Raylton P. Sousa, He7d3r.bot e Anónimo: 2
• Introdução à Arquitetura de Computadores/As Operações da Unidade Lógica Aritmética Fonte: http://pt.wikibooks.org/wiki/
Introdu%C3%A7%C3%A3o_%C3%A0_Arquitetura_de_Computadores/As_Opera%C3%A7%C3%B5es_da_Unidade_L%C3%
B3gica_Aritm%C3%A9tica?oldid=199785 Contribuidores: Master, Thiagoharry, Raylton P. Sousa e He7d3r.bot
10.3.2 Imagens
• Ficheiro:ALU_Block_Diagram.png Fonte: http://upload.wikimedia.org/wikipedia/commons/c/c7/ALU_Block_Diagram.png Licença:
GFDL Contribuidores: Own work created with Xilinx ISE 9.2i Artista original: Tapani Taivalantti
• Ficheiro:Circuito_multiplicacao.png Fonte: http://upload.wikimedia.org/wikibooks/pt/d/da/Circuito_multiplicacao.png Licença: ?
Contribuidores: ? Artista original: ?
• Ficheiro:Circuito_soma.png Fonte: http://upload.wikimedia.org/wikibooks/pt/0/00/Circuito_soma.png Licença: ? Contribuidores: ?
Artista original: ?
• Ficheiro:Cray-1-deutsches-museum.jpg Fonte: http://upload.wikimedia.org/wikipedia/commons/f/f7/Cray-1-deutsches-museum.jpg
Licença: CC BY 2.5 Contribuidores: Obra do próprio Artista original: Clemens PFEIFFER
• Ficheiro:Diagrama_circuito_multiplicacao.png Fonte: http://upload.wikimedia.org/wikibooks/pt/a/a0/Diagrama_circuito_
multiplicacao.png Licença: ? Contribuidores: ? Artista original: ?
• Ficheiro:Logic-gate-index.png Fonte: http://upload.wikimedia.org/wikipedia/commons/9/9f/Logic-gate-index.png Licença: CC-BY-
SA-3.0 Contribuidores: ? Artista original: ?
• Ficheiro:Toshiba_TC86R4400MC-200_9636YJA_top.jpg Fonte: http://upload.wikimedia.org/wikipedia/commons/6/6e/Toshiba_
TC86R4400MC-200_9636YJA_top.jpg Licença: CC-BY-SA-3.0 Contribuidores: ? Artista original: ?
• Ficheiro:Transistor_npn.png Fonte: http://upload.wikimedia.org/wikipedia/commons/2/22/Transistor_npn.png Licença: CC-BY-SA-
3.0 Contribuidores: Transferido de fr.wikipedia para o Commons. Artista original: Este ficheiro foi inicialmente carregado por Pulsar em
Wikipédia em francês
• Ficheiro:_Kernel_Layout.svg Fonte: http://upload.wikimedia.org/wikipedia/commons/8/8f/Kernel_Layout.svg Licença: CC BY-SA 3.0
Contribuidores: Obra do próprio Artista original: Bobbo
10.3.3 Licença
• Creative Commons Attribution-Share Alike 3.0
	Capa
	Introdução
	O Que é Arquitetura de Computadores 
	Computadores e as Várias Camadas de Abstração 
	Modelo de Von Neumann
	O que é o MIPS?
	O Processador MIPS 
	A Filosofia do Projeto do MIPS 
	Instruções do MIPS
	Instruções Aritméticas Simples 
	Instruções de Operadores Lógicos 
	Instruções de Uso de memória 
	Instruções de Controle de Fluxo 
	Instruções de Comparações 
	Resumo dos Modos de Endereçamento 
	Representação das Instruções
	As Instruções Tipo R 
	As Instruções Tipo I 
	As Instruções Tipo J 
	As Pseudo-Instruções
	A Pseudo-Instrução move 
	A Pseudo-Instrução Load Address 
	Suporte à Funções
	As Etapas Necessárias para Invocar Funções 
	Instruções de Uso de Funções: jal e jr 
	Funções com Muitas Variáveis 
	Funções Recursivas e Sub-Funções 
	Representação Numérica
	Números Naturais 
	Números Inteiros 
	Números Reais 
	Overflow e Underflow 
	As Operações da Unidade Lógica Aritmética
	A Adição e Subtração 
	A Multiplicação 
	Fontes, contribuidores e licenças de texto e imagem
	Texto
	Imagens
	Licença

Outros materiais

Perguntas Recentes