Escolar Documentos
Profissional Documentos
Cultura Documentos
Arquitetura de
processadores
Mostraremos neste capítulo alguns conceitos importantes sobre o
funcionamento interno dos processadores. Tomaremos como exemplo os
processadores Intel, e com eles você entenderá conceitos como execução
especulativa, pipeline, previsão de desvio, paralelismo, micro-operações,
linguagem assembly, memória virtual, paginação e outros termos complexos.
O assunto é difícil, mas vale a pena, pois o leitor passará a ter um
conhecimento mais profundo sobre o que se passa dentro de um
processador.
Figura 8.1
Registradores internos do
processador 8086.
Por exemplo, a instrução que acabamos de citar, que soma o valor dos
registradores AX e BX e guarda o resultado em AX, é representada por:
ADD AX,BX
01 D8
Figura 8.2
Registradores internos do 8080.
O SP (Stack Pointer) é muito importante. Ele serve para endereçar uma área
de memória chamada stack (pilha). A pilha serve para que os programas
possam usar o que chamamos de subrotinas, que são trechos de programa
que podem ser usados em vários pontos diferentes. Por exemplo, se em um
programa é preciso enviar caracteres para o vídeo, não é preciso usar em
vários pontos deste programa, as diversas instruções que fazem este trabalho.
Basta fazer uma subrotina com essas funções e “chamá-la” onde for
necessária. A subrotina deve terminar com uma instrução RET, que faz o
programa retornar ao ponto no qual a subrotina foi chamada. Para chamar
uma subrotina, basta usar a instrução CALL. Quando esta instrução é
executada, é automaticamente armazenado na pilha, o endereço da instrução
imediatamente posterior à instrução CALL (endereço de retorno). Subrotinas
podem chamar outras subrotinas, permitindo assim criar programas mais
complexos. O Stack Pointer sempre aponta para o topo da pilha, e é
automaticamente corrigido à medida em que são usadas instruções CALL e
RET. A instrução RET consiste em obter o endereço de retorno existente no
topo da pilha e copiá-lo para o PC (Program Counter). Isso fará com que o
programa continue a partir da instrução posterior à instrução CALL.
190
10010111b
325q
8BC3h
Capítulo 8 – Arquitetura de processadores 8-7
Os quatro números acima estão expressos respectivamente em decimal,
binário, octal e hexadecimal.
Outra convenção que vamos introduzir aqui é usar o símbolo [HL] para
indicar a posição de memória cujo endereço é dado por HL. Na linguagem
assembly do 8080, este é o papel do símbolo M. Não usamos [HL], porém
esta convenção foi adotada no assembly do 8086 e outros processadores mais
novos. Da mesma forma vamos usar os símbolos [BC] e [DE] para indicar as
posições de memória apontadas por BC e por DE.
Obseve a instrução LXI H, 35AFh. Este valor 35AF é formado por 16 bits,
sendo que os 8 bits mais significativos têm o valor 35 hex, e os 8 bits menos
significativos têm o valor AF hex. No par HL, o registrador H é o mais
significativo, e o registrador L é o menos significativo. Sendo assim o
registrador H ficará com 35 hex e o registrador L ficará com AF hex.
Figura 8.3
Armazenando HL em [2000h].
LDAX D ; A = [DE]
STAX B ; [BC] = A
LDAX B ; A = [BC]
STAX D ; [DE] = A
Note que estamos usando as notações [BC] e [DE] para indicar as posições
de memória cujos endereços são dados por BC e DE. Observe que as
instruções LDAX H e STAX H não existem, mas em seu lugar temos “MOV
A,M” e “MOV M,A” que fazem a mesma coisa.
Capítulo 8 – Arquitetura de processadores 8-9
XCHG: Troca o valor de HL com o valor de DE. Esta instrução só é usada
na forma:
XCHG ; DE HL
Instruções aritméticas
ADD: Soma com A, o valor do registrador especificado, ou da posição de
memória apontada por HL (M). O resultado da operação é armazenado em
A. Exemplos:
ADD B ; A = A+B
ADD C ; A = A=C
ADD L ; A = A+L
ADD M ; A = A+[HL]
Assim como ocorre com todas as instruções aritméticas e lógicas, os flags (Z,
CY, P, S e AC) são atualizados de acordo com o resultado da operação. Por
exemplo, se somarmos C8h com 72h, o resultado será 13Ah. Este valor não
cabe em 8 bits, portanto o resultado será 3Ah e o bit Carry será ligado para
indicar que ocorreu um “vai 1”.
8-10 Hardware Total
ADI. Soma com A, o valor constante especificado. O resultado fica
armazenado em A. Exemplos:
ADI 90 ; A = A+90
ADI 35 ; A = A+35
ADC L ; A = A+L+carry
ADC D ; A = A+D+carry
ADC M ; A = A+[HL]+carry
ACI 90 ; A = A+90+carry
ACI 84 ; A = A+84+carry
SUB D ; A = A-D
SUB C ; A = A-C
SUB M ; A = A-[HL]
SUI 20 ; A = A-20
SUI 82 ; A = A-82
SUI 0DFh ; A = A-DF (hex)
SBB: Similar à instrução SUB, exceto que leva em conta o valor do carry.
Serve para fazer cálculos com o método de “pedir emprestado”. Exemplos:
SBB C ; A = A-C-carry
SBB L ; A = A-L-carry
SBB M ; A = A-[HL]-carry
Capítulo 8 – Arquitetura de processadores 8-11
SBI: Similar à instrução SUI, exceto que leva em conta o valor do carry.
Serve para fazer cálculos com o método de “pedir emprestado”. Exemplos:
INR A ; A = A+1
INR C ; C = C+1
INR D ; D = D+1
INR L ; L = L+1
INR M ; [HL] = [HL]+1
DCR A ; A = A-1
DCR C ; C = C-1
DCR D ; D = D-1
DCR H ; H = H-1
DCR M ; [HL] = [HL]-1
INX e DCX: Essas instruções são similares às instruções INR e DCR, exceto
que operam com pares de registradores (BC, DE e HL) e com o Stack
Pointer. Não podem ser usadas diretamente para implementar contadores,
pois elas não afetam os valores dos flags, ou seja, não “avisam” se o resultado
foi zero, positivo ou negativo. Essas instruções não tinham objetivo de fazer
contagem, mas sim de usar os registradores como ponteiros para a memória.
Ao lançar o 8086, a Intel corrigiu este “deslize”. As instruções
correspondentes nos processadores de 16 bits afetam os valores dos flags, o
que é importante para tomar decisões posteriores em função do resultado da
contagem. Exemplos:
8-12 Hardware Total
INX H ; HL = HL+1
INX D ; DE = DE+1
DCX B ; BC = BC-1
INX SP ; SP = SP+1
Note que apesar do 8080 ser um processador de 8 bits, INX e DCX são
consideradas instruções de 16 bits.
DAD B ; HL = HL+BC
DAD D ; HL = HL+DE
DAD H ; HL = HL+HL
DAD SP ;HL = HL+SP
Instruções lógicas
As instruções lógicas são necessárias para que os programas possam tomar
decisões em função dos dados. São instruções que realizam operações AND,
OR, XOR (ou exclusivo) e NOT (negação). Existem ainda instruções de
comparação, instruções para manipular o bit carry e instruções para rotação
de bits.
X NOT X X Y X AND Y X Y X OR Y
0 1 0 0 0 0 0 0
1 0 0 1 0 0 1 1
1 0 0 1 0 1
1 1 1 1 1 1
Como vemos na tabela acima, o operador NOT faz a inversão do bit sobre o
qual atua. O operador AND dará resultado 1 apenas quando ambos os bits
forem 1, e dará 0 em caso contrário. O operador OR dará resultado 0
somente quando ambos os bits forem 0. O operador XOR dará resultado 1
se os dois bits forem diferentes, e 0 se ambos os bits forem iguais.
X Y X XOR Y
0 0 0
0 1 1
1 0 1
1 1 0
Essas operações são envolvem apenas um bit, mas nas instruções lógicas dos
processadores, atuam individualmente sobre cada um dos bits. Por exemplo,
se calcularmos 10111110 AND 10010101, teremos o seguinte resultado:
10111110
10010101 AND
------------
10010100
8-14 Hardware Total
Note que o primeiro bit do resultado é obtido fazendo a operação AND com
os primeiros bits das duas parcelas, e assim por diante.
ANA e ANI: Realiza uma operação AND, bit a bit, do acumulador com o
registrador especificado. O resultado da operação fica no acumulador. A
instrução ANI faz o AND do acumulador com um valor constante.
ANA B ; A = A AND B
ANA C ; A = A AND C
ANA A ; A = A AND A
ANA M ; A = A AND [HL]
ANI 3Fh ; A = A AND 3F
Uma das várias aplicações desta instrução é testar se determinados bits são
zero ou 1. Por exemplo, se fizermos ANI 00000100b, podemos usar a seguir
uma instrução JZ ou JNZ que causarão desvio ou não dependendo do fato
do bit 2 estar ligado ou desligado.
XRA B ; A = A XOR B
XRA C ; A = A XOR C
ORA L ; A = A XOR L
ORI 20h ; A = A OR 20h
XRI 04h ; A = A XOR 04h
XRA A ; A = A XOR A
Exemplos:
RLC, RRC: Essas duas instruções são usadas para deslocar os bits do
acumulador. RLC desloca para esquerda e RRC desloca para a direita. A
operação é mostrada na figura 4.
Figura 8.4
Instruções RLC e RRC.
Essas instruções não têm parâmetros. São usadas simplesmente nas formas
RRC e RLC.
Figura 8.5
Instruções RAL e RAR.
Instruções de desvio
As instruções de desvio são importantíssimas, e são executadas o tempo
todo. O processador tende a seguir uma seqüência de instruções, na mesma
ordem na qual são encontradas na memória, ou seja, depois de cada
instrução é executada a instrução seguinte. Um programa que só executa
instruções na sequência não tem muita utilidade. Todos os processadores
precisam de insruções de desvio, que fazem com que a execução seja
continuada a partir de um outro ponto qualquer do programa. Já mostramos
um exemplo de trecho de programa que usa a instrução JNZ (jump if not
zero) para implementar a repetição de um trecho um certo número de vezes.
Um trecho de programa que é executado diversas vezes é chamado de
LOOP.
Figura 8.6
Empilhamento de um endereço de
retorno na stack, feito por uma instrução
CALL.
CALL 0000 / CALL 0008 / CALL 0010 / CALL 0018 / … / CALL 0038
SPHL: Já vimos também a instrução “LXI SP, Valor”, que carrega um valor
fixo no stack pointer. Isto é necessário na inicialização dos programas,
quando temos que definir onde ficará a pilha. A instrução SPHL é mais
flexível. Ela cria a stack em qualquer ponto da memória, bastando indicar
seu endereço em HL.
NOP: No Oparation. Esta instrução não faz nada. É usada quando queremos
fazer uma pausa entre duas instruções seguidas. Normalmente isso é
necessário quando temos um programa que faz controle direto do hardware.
Capítulo 8 – Arquitetura de processadores 8-21
Isto pode ser necessário, por exemplo, para fazer o processador esperar um
pouco mais pela execução das funções de certos circuitos lentos.
Op Op Op Op Op Op
Cod Mnemonic Code Mnemonic Cod Mnemonic Cod Mnemonic Code Mnemonic Code Mnemonic
e e e
00 NOP 2B DCX H 56 MOV D,M 81 ADD C AC XRA H D7 RST 2
01 LXI B,D16 2C INR L 57 MOV D,A 82 ADD D AD XRA L D8 RC
02 STAX B 2D DCR L 58 MOV E,B 83 ADD E AE XRA M D9 -
03 INX B 2E MVI L,D8 59 MOV E,C 84 ADD H AF XRA A DA JC ADDR
04 INR B 2F CMA 5A MOV E,D 85 ADD L B0 ORA B DB IN D8
05 DCR B 30 - 5B MOV E,E 86 ADD M B1 ORA C DC CC ADDR
06 MVI B,D8 31 LXI SP,d16 5C MOV E,H 87 ADD A B2 ORA D DD -
07 RLC 32 STA ADDR 5D MOV E,L 88 ADC B B3 ORA E DE SBI D8
08 - 33 INX SP 5E MOV E,M 89 ADC C B4 ORA H DF RST 3
09 DAD B 34 INR M 5F MOV E,A 8A ADC D B5 ORA L E0 POR
0A LDAX B 35 DCR M 60 MOV H,B 8B ADC E B6 ORA M E1 POP H
0B DCX B 36 MVI M,D8 61 MOV H,C 8C ADC H B7 ORA A E2 JPO ADDR
0C INR C 37 STC 62 MOV H,D 8D ADC L B8 CMP B E3 XTHL
0D DCR C 38 - 63 MOV H,E 8E ADC M B9 CMP C E4 CPO ADDR
0E MVI C,D8 39 DAD SP 64 MOV H,H 8F ADC A BA CMP D E5 PUSH H
0F RRC 3A LDA ADDR 65 MOV H,L 90 SUB B BB CMP E E6 ANI D8
10 - 3B DCX SP 66 MOV H,M 91 SUB C BC CMP H E7 RST 4
11 LXI D,D16 3C INR A 67 MOV H,A 92 SUB D BD CMP L E8 RPE
12 STAX D 3D DCR A 68 MOV L,B 93 SUB E BE CMP M E9 PCHL
13 INX D 3E MVI A,D8 69 MOV L,C 94 SUB H BF CMP A EA JPE ADDR
14 INR D 3F CMC 6A MOV L,D 95 SUB L C0 RNZ EB XCHG
15 DCR D 40 MOV B,B 6B MOV L,E 96 SUB M C1 POP B EC CPE ADDR
16 MVI D,D8 41 MOV B,C 6C MOV L,H 97 SUB A C2 JNZ ADDR ED -
17 RAL 42 MOV B,D 6D MOV L,L 98 SBB B C3 JMP ADDR EE XRI D8
18 - 43 MOV B,E 6E MOV L,M 99 SBB C C4 CNZ ADDR EF RST 5
19 DAD D 44 MOV B,H 6F MOV L,A 9A SBB D C5 PUSH B F0 RP
1A LDAX D 45 MOV B,L 70 MOV M,B 9B SBB E C6 ADI D8 F1 POP PSW
1B DCX D 46 MOV B,M 71 MOV M,C 9C SBB H C7 RST 0 F2 JP ADDR
1C INR E 47 MOV B,A 72 MOV M,D 9D SBB L C8 RZ F3 DI
1D DCR E 48 MOV C,B 73 MOV M,E 9E SBB M C9 RET F4 CP ADDR
1E MVI E,D8 49 MOV C,C 74 MOV M,H 9F SBB A CA JZ ADDR F5 PUSH PSW
1F RAR 4A MOV C,D 75 MOV M,L A0 ANA B CB - F6 ORI D8
20 - 4B MOV C,E 76 HLT A1 ANA C CC CZ ADDR F7 RST 6
21 LXI H,D16 4C MOV C,H 77 MOV M,A A2 ANA D CD CALL Addr F8 RM
22 SHLD ADDR 4D MOV C,L 78 MOV A,B A3 ANA E CE ACI D8 F9 SPHL
23 INX H 4E MOV C,M 79 MOV A,C A4 ANA H CF RST 1 FA JM ADDR
24 INR H 4F MOV C,A 7A MOV A,D A5 ANA L D0 RNC FB EI
25 DCR H 50 MOV D,B 7B MOV A,E A6 ANA M D1 POP D FC CM ADDR
26 MVI H,D8 51 MOV D,C 7C MOV A,H A7 ANA A D2 JNC ADDR FD -
27 DAA 52 MOV D,D 7D MOV A,L A8 XRA B D3 OUT D8 FE CPI D8
Capítulo 8 – Arquitetura de processadores 8-23
28 - 53 MOV D,E 7E MOV A,M A9 XRA C D4 CNC ADDR FF RST 7
29 DAD H 54 MOV D,H 7F MOV A,A AA XRA D D5 PUSH D
2A LHLD ADDR 55 MOV D,L 80 ADD B AB XRA E D6 SUI D8
08, 10, 18, 20, 28, 30, 38, CB, D9, DD, ED e FD.
Ao encontrar uma dessas instruções inválidas, o 8080 não fazia nada. Alguns
ciriosos descobriram que certos códigos inválidos eram na verdade instruções
não documentadas da Intel, porém nenhum programador sério ousava
utilizá-las. Como eram instruções não oficiais, não era garantido que fossem
implementadas em todas as versões do processador. No 8085, uma evolução
do 8080, a Intel utilizou duas novas instruções: RIM (20h) e SIM (30h). A
Zilog utilizou esses códigos para usar com as novas instruções do seu
processador Z80.
Novas instruções
Além de ter todas as instruções do 8080 ou instruções similares, o 8086
trouxe novas instruções bem mais avançadas, com execução mais rápida.
Alguns exemplos:
Capítulo 8 – Arquitetura de processadores 8-25
[BX+valor] [BX+SI+valor]
[BP+valor] [BX+DI+valor]
[SI+valor] [BP+SI+valor]
[DI+valor] [BP+DI+valor]
Exemplos:
Registradores de segmento
O 8086 podia endereçar 1 MB de memória, muito mais que os 64 kB
permitidos pelo 8080. No 8080, toda a memória era tratada como uma única
coleção de bytes, contendo instruções, dados e stack. No 8086, esses
elementos também ficam nesta mesma memória, apesar de maior. Apesar da
memória ser homogênea do ponto de vista físico, seu uso é dividido em
áreas chamados segmentos. Instruções devem ficar no segmento de código,
dados devem ficar no segmento de dados ou no segmento extra, e a stack
deve ficar no segmento de stack. Para manter essas 4 áreas de memória
diferentes, o 8086 possui 4 registradores de segmento, que são:
Figura 8.8
Regitradores de segmento indicam os
inícios dos respectivos segmentos.
Observe que cada posição de memória pode ser endereçada de várias outras
formas. Por exemplo, o mesmo endereço absoluto 926A6H pode ser obtido
fazendo DS=9000h e BX=26A6h.
Modos de endereçamento
O 8086 possui vários modos de endereçamento:
MOV CL,[BX]
MOV DL,[BP]
MOV AX,[SI]
MOV AH,[DI]
MOV CX,[BX+5]
MOV DL,[BP+50]
MOV AL,[SI+100]
MOV AX,[DI+1200]
MOV AX,[BX+SI]
MOV CL,[BX+SI+200]
MOV AH,[BP+DI]
MOV DX,[BP+DI+300]
MOV CX,[DI+4800]
Capítulo 8 – Arquitetura de processadores 8-29
MOV DX,[BP+SI]
MOV AH,[BP+SI+2000]
MOV AL,[BP+DI]
MOV DX,[BP+DI+700]
MOV AX,BX
MOV DI,1000h
MOV [BX+SI],20
MOV CL,19
MOV SI,[BX]
MOV [BP+DI],CX
Note que o 8086 não tem instruções equivalentes a STAX e LDAX do 8080,
que usam pares BC e DE para indexar a memória, já que não existem os
modos de endreçamento [CX] e [DX].
XCHG BX,DX
XCHG AX,SI
XCHG AL,BH
XCHG CX,[BX+SI]
NEG AL
NEG AX
NEG BX
NEG DX
NEG byte ptr [BX+SI]
NEG word ptr [DI+4]
Estamos apresentando agora os prefixos byte ptr e word ptr. Esses prefixos
são utilizados para informar ao assembler a real intenção do programador, se
é acessar um dado de 8 ou de 16 bits. Por exemplo, na instrução MOV AL,
[BX], o assembler sabe que o valor da memória a ser acessado é de 8 bits, já
que o outro operando é AL, que é também de 8 bits. Já em instruções como
NEG [BX], o assembler não saberia se a operação deve ser feita sobre o byte
cujo endereço é dado por BX, ou se deve operar sobre os dois bytes (word)
com este endereço. Usamos então os prefixos byte ptr e word ptr quando
necessário para dar esta informação ao assembler.
ADD BX,SI
ADD AX,[BX+DI]
ADD CL,AH
ADD DX,CX
ADD [SI],DX
ADC CX,[BX+SI]
ADC AH,[BP+SI+3]
ADC DX,BX
ADC [SI],AX
SUB BX,DX
SUB CX,[BP+DI]
SUB CH,DL
SUB CX,AX
SUB [SI],BX
SBB AX,[BX+DI]
SBB CX,[BP+SI+3]
SBB CX,AX
SBB [SI],CX
MUL CL
MUL BX
MUL byte ptr [SI]
IMUL DX
IMUL BX
IMUL CL
Instruções lógicas
NOT: Inverte todos os bits do dado especificado. Cada bit 1 se transforma
em 0, e cada bit 0 se transforma em 1. Exemplos:
NEG AX
NEG SI
NEG DL
NEG byte ptr [BX]
NEG word ptr [BP+DI]
NEG byte ptr [1000h]
AND, OR, XOR: São os tradicionais operadores lógicos “E”, “OU” e “OU
Exclusivo”. Não há necessidade de apresentar novamente a tabela verdade
desses operadores, já mostradas quando apresentamos as instruções do 8080.
A diferença aqui é que essas operações podem ser feitas com 8 ou 16 bits, e
os dois operandos podem ser quaisquer, desde que ambos sejam do mesmo
tipo (ou ambos são byte, ou ambos são word). O resultado da operação
ficará armazenado no primeiro operando.
AND AX,SI
AND CX,[BX+DI]
AND DL,CH
OR [SI],AL
OR AX,1040h
OR byte ptr[SI],20h
XOR BX,DX
XOR [SI+2],AL
XOR AL,AH
Capítulo 8 – Arquitetura de processadores 8-33
Shifts e Rotates
O 8086 tem diversas instruções para deslocar bits para a esquerda e para a
direita. São chamadas de shifts e rotates. As instruções SHL e SHR são
exemplos de shifts. Provocam o deslocamento de todos os bits para a
esquerda e para a direita, respectivamente. Bits 0 são introduzidos à direita e
à esquerda. A operação dessas duas instruções é mostrada na figura 10. Note
que no 8086, qualquer registrador ou posição de memória pode ser usada
com esta instrução. Podemos aplicar um deslocamento de um só bit ou de
múltiplos bits, como mostraremos mais adiante.
Figura 8.10
Instruções SHL e SHR.
Figura 8.11
Instruções ROL e ROR.
8-34 Hardware Total
As instruções RCL e RCR operam de forma similar, exceto pelo fato do bit
Carry fazer parte da rotação, ao invés de simplesmente ficar com uma cópia
do bit realimentado. A figura 12 mostra o funcionamento dessas duas
instruções, que são exemplos de rotates. Este é o mesmo método de rotação
usado pelas instruções RAL e RAR do 8080.
Figura 8.12
Instruções RCL e RCR.
Figura 8.13
Instruções SAL e SAR.
Desvios
As instruções de CALL, RET e JMP presentes no 8080 também estão
presentes no 8086. Também temos as formas condicionais da instrução JMP,
mas não temos formas condicionais das instruções CALL e RET. Por
exemplo, não existe a instrução RC (Return if Carry), como no 8080. No seu
lugar temos que fazer uma combinação das instruções JNC e RET.
Existe ainda a instrução JCXZ (jump if CX=0). Como o nome já diz, esta
instrução executa um desvio caso o valor de CX tenha atingido o valor zero.
Note que esta instrução, a instrução LOOP e suas formas condicionais, e as
instruções de shifts e rotates que podem usar em CL o número de bits a
serem deslocados, dão ao registrador CX uma espécie de “personalidade”.
Este registrador é usado como contador em todas essas instruções citadas, e
em outras que ainda vamos apresentar.
Rotinas e retornos
Como já abordamos, as instruções de chamadas e retornos de rotinas são
CALL e RET, e não possuem formas condicionais. Existem entretanto outras
instruções de chamadas e retornos.
Manipulação da stack
8-38 Hardware Total
As instruções PUSH e POP são utilizadas respectivamente para armazenar e
recuperar valores de 16 bits na pilha. Todos os registradores de 16 bits
podem ser usados com essas instruções, bem como dados de 16 bits da
memória. As instruções PUSHF e POPF são usadas para salvar e recuperar o
registrador de flags. Exemplos:
PUSH BX
PUSH SI
PUSH BP
PUSH DS
POP AX
POP CX
POPF
Interrupções e E/S
Várias instruções são usadas para o processador interagir com o hardware.
As instruções STI e CLI são hadas para habilitar e desabilitar interrupções.
Instruções IN e OUT fazem operações de entrada e saída com 8 ou 16 bits.
Nas instruções de 8 bits é usado o registrador AL, e nas instruções de 16 bits
é usado o registrador AX. Exemplos:
Manipulação de strings
O processador 8086 e seus sucessores têm a capacidade de manipular strings,
que são cadeias de caracteres. Essas funções são importantes em
processadores de texto e compiladores. Em todas as instruções de strings, os
registradores SI e DI apontam para as strings envolvidas. SI aponta para a
origem, localizada no segmento de dados. DI aponta para a string destino,
localizada no segmento Extra. Portanto as strings de origem e destino estão
em CS:SI e ES:DI, respectivamente. O registrador CX é usado como
Capítulo 8 – Arquitetura de processadores 8-39
contador, e AL ou AX são usados para manter o dado nas operações de
busca, leitura e escrita.
MOV dado8,DS:[SI]
MOV ES:[DI],dado8
INC SI
INC DI
MOV dado16,DS:[SI]
MOV ES:[DI],dado16
ADD SI,2
ADD DI,2
REP MOVSB
REP MOVSW
Observe que o prefixo REP faz com a que a instrução seguinte seja
executada CX vezes, mas este prefixo só pode ser usado em operações com
strings.
Outras instruções
O 8086 tem muitas outras instruções. Optamos por não apresentar todas aqui
para não tornar o capítulo muito complexo. Você pode obter no site da Intel
(www.intel.com), o manual completo da linguagem assembly dos
processadores modernos. A diferença é que existem novas instruções,
sobretudo aquelas para manipular valores de 32 bits. Mesmo não sendo
totalmente completa, esta apresentação resumida atendeu ao nosso objetivo
de mostrar como o processador opera internamente e como os programas
são executados.
Arquitetura do 80286
O 80286 também é um processador de 16 bits. Possui os mesmos
registradores internos existentes no 8086. Entretanto possui algumas novas
instruções, bem como um novo modo de endereçamento capaz de operar
com 16 MB de memória, o que era uma quantidade espantosa para a época
do seu lançamento (1982), quando a maioria dos computadores tinha 64 kB
de memória. O 80286 podia operar em duas modalidades. O chamado
modo real (8086 real address mode) permite endereçar até 1 MB de
memória. Nesse caso o processador comporta-se como um 8086, apenas
acrescido de algumas novas instruções. Para uso em sistemas operacionais
mais avançados, o 80286 podia operar no modo protegido (protected virtual
address mode). Neste modo, o processador pode operar com 16 MB de
memória física e até 1 GB de memória virtual por tarefa.
Multitarefa
O 80286 foi criado visando facilitar a multiprogramação ou multitarefa, na
qual vários programas podem ser executados “simultaneamente”. O que
Capítulo 8 – Arquitetura de processadores 8-41
ocorre é uma divisão do tempo entre os vários processos que estão sendo
executados. Uma forma simples de dividir o tempo é alocar períodos iguais
(10 milésismos de segundo, por exemplo), e distrubuir esses períodos entre
os processos. Quando um processo começa a ser executado, será
interrompido 10 ms depois, e o sistema operacional deve fazer com que o
processador dê atenção ao processo seguinte. Desta forma usando um
esquema de “rodízio”, todos os processos são executados ao mesmo tempo,
porém em cada instante um só está efetivamente em execução, e os demais
estão aguardando. O período no qual o processador está dedicado a um
processo é chamado time slice.
Modo real
Visando manter compatibilidade com os programas escritos para 8086/8088,
o 80286 é capaz de operar no chamado modo real. O processador passa a se
comportar como um 8086, endereçando apenas 1 MB de memória. É apenas
acrescido das novas instruções adicionadas ao conjunto de instruções
originais do 8086, exceto aquelas usadas para gerenciamento de tarefas. Por
isso é quase certo dizer que o 80286 operando em modo real é equivalente
ao 8086. Alguns dizem que isso é “o mesmo que um XT”. É mais ou menos
Capítulo 8 – Arquitetura de processadores 8-43
isso o que acontece, mas devemos lembrar que o 8086, 8088 e 80286 são
processadores, e o XT é um computador. Seria correto dizer que no modo
real, o 80286 opera como um 8086 acrescido de instruções novas como
BOUND, ENTER, LEAVE, INSB, INSW, OUTSB, OUTSW, novos shifts,
rotates e a nova instrução IMUL, além das instruções PUSHA e POPA.
Entretanto muitos programadores optavam por não utilizar essas novas
instruções, para que seus programas fossem compatíveis com o IBM XT.
Alguns programas tinham versões para XT e versões otimizadas para 80286,
que usavam essas novas instruções. Apenas no final dos anos 80, quando o
AT-286 era mais comum que o XT, surgiram programas que rodavam
somente no 286, utilizando essas novas instruções.
Modo protegido
O 80286 passa a ter novos recursos para gerenciamento de tarefas e
endereçamento de memória quando opera no modo protegido. Lembre que
no 8086, cada segmento tinha 64 kB, e era definido pelos registradores de
segmento (CS, DS, ES e SS). Todos os segmentos eram contidos dentro da
memória física de 1 MB. No 286 operando em modo protegido, os
segmentos também têm 64 kB, e são definidos por um registrador de
segmento (CS, DS, ES e SS) e um offset. A diferença está na formação desses
endereços. Consideremos por exemplo o endereço F000:1000 no modo real.
Conforme mostramos neste capítulo, o endereço absoluto correspondente é
F1000. É obtido acrescentando um zero hexadecimal (ou 4 zeros binários) à
direita do segmento e somando o resultado com o offset. O resultado terá 20
bits, permitindo endereçar até 1 MB.
Não foi bem isso o que ocorreu. O IBM PC passou a ser cada vez mais
usado, até chegar ao ponto em que microcomputador passou a ser sinônimo
de IBM PC. O número de PCs aumentou ainda mais depois que surgiram os
clones, ou seja, PCs similares produzidos por outros fabricantes. Ao lado do
PC, o sistema operacional MS-DOS com toda a sua limitação tornou-se mais
utilizado que todos os demais sistemas operacionais.
Arquitetura do 80386
É muito importante conhecer bem o 386, pois todos os processadores
posteriores, do 486 ao Pentium 4, utilizam métodos semelhantes de
gerenciamento de memória e multitarefa, bem como possuem conjuntos de
instruções similares, com apenas algumas poucas diferenças.
*** 100%
Figura
8.14
Diagrama interno do
processador 80386.
Figura
8.15
Registradores do
80386.
Os registradores AX, BX, CX, DX, SI, DI, BP e SP foram todos expandidos
para 32 bits. Os registradores de segmento CS, SS, DS e ES também estão
presentes e são de 16 bits. Foram adicionados mais dois registradores para
apontar para segmentos de dados: FS e GS. O contador de instruções (IP),
Capítulo 8 – Arquitetura de processadores 8-47
que antes tinha 16 bits, agora tem 32 bits, e novos flags resultaram no
aumento do registrador de flags também para 32 bits.
Além da maioria das instruções antigas agora poderem também operar com
32 bits, existem várias instruções novas. A maioria delas são aplicadas ao
gerenciamento de tarefas e ao gerenciamento de memória. São portanto
instruções para serem usadas pelo sistema operacional, e não pelos
programas comuns.
Modo real
No modo real, o esquema de enereçamento do processador é similar ao do
8086. Além disso não estão disponíveis os recursos avançados de
endereçamento e gerenciamento de memória, nem de multitarefa. Estão
entretanto disponíveis as novas instruções que manipulam dados e 32 bits e
novos modos de endereçamento de memória.
8-48 Hardware Total
Os endereços no modo real são formados a partir de um segmento e offset,
ambos de 16 bits. O valor existente no registrador de segmento é adicionado
de 4 bits “0” e somado com o offset. O resultado é o endereço efetivo de 20
bits, usado para acessar a memória física. Neste modo é possível acessar até
1 MB de memória, e cada segmento tem 64 kB. Exatamente como no 8086.
Figura 8.16
Endereçamento no modo real.
Assim como ocorreu no 286, o modo real do 386 foi criado para oferecer
compatibilidade com os programas escritos para o 8086, como o DOS e seus
aplicativos. O modo real está presente também nos processadores modernos,
por isso é possível executar um boot com um disquete de DOS em um PC
equipado com o Pentium 4 e usar programas de modo real.
Modo protegido
Além da velocidade resultante do maior clock e de operar diretamente com
dados de 32 bits, o 80386 tem a grande vantagem de operar no modo
protegido, possibilitando acessar grandes áreas de memória e permitir a
multitarefa. Os valores de offset podem ter 16 ou 32 bits, permitindo formar
segmentos de 64 kB e de 4 GB. Graças ao endereçamento com offsets de 32
bits, um programa poderia teoricamente ocupar toda a memória física de um
processador 386.
O 80386 opera com páginas de 4 kB. Todas essas páginas podem estar
fisicamente localizadas na memória RAM. Entretanto é comum utilizar este
recurso para implementar a memória virtual. No Windows a memória virtual
consiste em um arquivo mantido no disco (swap file ou arquivo de troca), o
WIN386.SWP, localizado em C:\Windows. A RAM é fisicamente dividida
em páginas de 4 kB, assim como o arquivo de troca, entretanto este arquivo
tem tamanho bem maior que a memória física.
Multitarefa
Um computador pode executar vários programas ao mesmo tempo,
compartilhando seu tempo entre todos eles. Este tipo de ambiente é
chamado de multitarefa (multitask). Assim como o 286, o 80386 tem no seu
modo protegido, todos os recursos para operar em um ambiente multitarefa.
Um desses recursos é a diferenciação entre os níveis de privilégio das tarefas.
As tarefas do 386 podem ter níveis 0, 1, 2 e 3. O nível 0 é o único que tem
acesso a todos os recursos do processador, e deve ser usado pelo núcleo do
sistema operacional. Neste nível podem ser executadas as instruções para
gerenciamento das demais tarefas e gerenciamento de memória. Tarefas com
níveis 1 e 2 não podem executar essas instruções críticas, mas têm aceso a
algumas instruções não suportadas por programas comuns. Esses dois níveis
devem ser usados por módulos do sistema operacional e drivers. O nível 3 é
o mais baixo, e pode executar praticamente todas as instruções, exceto
aquelas mais críticas, só permitidas pelos níveis superiores. Programas
comuns devem operar no nível 3. A figura 19 mostra como são organizados
esses níveis.
Capítulo 8 – Arquitetura de processadores 8-53
Figura 8.19
Níveis de privilégio do 386.
Pipeline do 386
Pipeline é uma técnica amplamente utilizada nos processadores mais novos,
mas já era utilizada em pequena escala no 386. Seu funcionamento é
equivalente ao de uma linha de montagem de automóveis. Ao invés de
montar um automóvel de cada vez, a montagem é dividida em várias etapas
menores. Em cada estágio é feita uma parte da montagem, e o automóvel é
passado para o estágio seguinte. Todos os estágios trabalham ao mesmo
tempo, e no cômputo geral, a produção ao final do dia é bem elevada.
Essas unidades podem ser vistas na figura 14. Observe ainda que os blocos
do 386 são interligados por um barramento interno de 32 bits.
Arquitetura do 80486
Explicando em poucas palavras, um processador 80486 é similar a um 80386,
acrescido de um coprocessador matemático 80387, mais 8 kB de cache L1
integrada. Existem entretanto outras diferenças na arquitetura interna, sendo
a principal delas, o aumento do número de estágios pipeline. A figura 20
mostra o diagrama interno do 486.
*** 75%
Figura
8.20
Diagrama interno do
486.
Figura 8.21
Pipeline do 486.
A operação dos estágios pipeline do 486 é mostrada na figura 21. São usados
5 estágios:
Prefetch
Decode 1
Decode 2
Execution
Writeback
Arquitetura do Pentium
Além do aumento de clock, o uso de arquitetura pipeline foi utilizada nos
processadores 386 e 486 para aumentar o desempenho. O Pentium também
tem suas operações de decodificação e execução realizadas por 5 estágios, tal
qual o 486. A grande evolução é a introdução da arquitetura superescalar,
através da qual podem ser executadas duas instruções ao mesmo tempo.
Podemos ver na figura 22 o diagrama do Pentium, no qual encontramos os
módulos U-Pipeline e V-Pipeline. Esses dois módulos operam de forma
simultânea, e graças a eles é possível executar duas instruções ao mesmo
tempo. Outro melhoramento é a adoção do barramento de dados com 64
bits, com a qual é possível reduzir os efeitos da lentidão da memória RAM.
O Pentium tem ainda uma cache L1 maior, dividida em duas seções
independentes, sendo uma para código e outra para dados. A unidade de
ponto flutuante foi reprojetada, e é muito mais rápida que a do 486.
** 75%
Figura
8.22
Diagrama interno do
Pentium.
Capítulo 8 – Arquitetura de processadores 8-57
Arquitetura superescalar
Uma arquitetura superescalar é aquela na qual múltiplas instruções podem
ser executadas simultaneamente. Podemos ver na figura 23 como os
pipelines U e V do Pentium executam instruções. A execução simultânea é
possível desde que se tratem de instruções independentes, ou seja, que a
execução da segunda operação não dependa do resultado da primeira.
Observe que no instante t1, as instruções I1 e I2 são finalizadas, e em cada
um dos instantes seguintes, duas novas instruções são finalizadas. Desta
forma o Pentium pode teoricamente executar duas instruções a cada ciclo.
Figura 8.23
Funcionamento dos estágios pipeline do
Pentium.
U-Pipeline V-Pipeline
8-58 Hardware Total
MOV SI, 1000 MOV DI, 2000
MOV CX,1000 MOV AL,[SI]
INC SI MOV [DI],AL
INC DI DEC CX
JNZ MOVER MOV AL,[SI]
Previsão de desvio
As dependências entre instruções podem causar uma paralisação em uma
das pipelines, mas assim que a dependência é resolvida, as instruções
prosseguem ao longo da pipeline. Pior situação é quando ocorrem desvios
condicionais. Não é possível nesse caso saber que caminho tomará a
seqüência de instruções antes da finalização de sua execução. Veja o
exemplo:
....
DEC CX
JNZ LAB01
LAB00: MOV AX,1000
ADD AX,DX
LAB01: MOV BX,2000
....
MOV SI,1000
MOV DI, 2000
MOV CX,100
LAB01: LODSB
STOSB
DEC DX
JNZ LAB01
MOV AX,1000
….
Instrução CPUID
A partir do Pentium, os processadores Intel (o mesmo ocorre com
processadores de outros fabricantes) passaram a incluir no seu conjunto de
instruções, uma que fornece infromações que identificam o processador. É a
instrução CPUID (CPU Identification). Programas de diagnóstico e
programas que dão informações sobre a configuração de hardware utilizam
esta instrução para informar corretamente o modelo do processador, bem
como identificar suas características.
Microarquitetura P6
Esta arquitetura foi usada a partir de 1995, com o lançamento do Pentium
Pro, e sofreu algumas modificações posteriores, dando origem ao Pentium II,
Celeron e Pentium III, bem como suas versões Xeon.
CISC e RISC
Os processadores Intel, até o Pentium inclusive, são considerados máquinas
CISC (Complex Instruction Set Computer). Significa que seu conjunto de
instruções é bastante complexo, ou seja, tem muitas instruções que são
usadas com pouca freqüência. Um programador de linguagem Assembly usa
com muita freqüência instruções MOV, CALL, RET, JMP, ADD e outras,
mas raramente usa instruções como XLAT e todas as opções de shifts e
Capítulo 8 – Arquitetura de processadores 8-61
rotates A instrução XLAT, por exemplo, poderia ser substituída pela
seqüência ADD BX,AX / MOV AL,[BX]. Teoricamente o uso de uma única
instrução teria uma execução mais rápida que se fossem usadas duas ou mais
instruções, mas na prática não é o que ocorre. Um processador com um
conjunto de instruções muito complexo perde muito tempo para decodificar
uma instrução. Além disso, um maior número de circuitos internos seria
necessário para a implementação de todas essas instruções. Muitos desses
circuitos são pouco utilizados a acabam apenas ocupando espaço e
consumindo energia. Maior número de transistores resulta em maior
aquecimento, o que impõe uma limitação no clock máximo que o
processador pode utilizar.
Execução dinâmica
Processadores de microarquitetura P6 utilizam um mecanismo de execução
fora de ordem que a Intel chama de Dynamic Execution. A execução fora
de ordem é um recurso necessário para o paralelismo no processamento de
instruções. A execução dinâmica utiliza por sua vez, três técnicas:
Previsão de desvio
Análise dinâmica do fluxo de dados
Execução especulativa
Execução especulativa
A execução especulativa é uma das três técnicas usadas na execução
dinâmica, e sem dúvida é uma grande inovação, por isso preferimos explicá-
la separadamente. Processadores de arquitetura P6 buscam constantemente
Capítulo 8 – Arquitetura de processadores 8-63
instruções na memória, fazem sua decodificação e as colocam em um pool
de instruções (figura 24). Podemos visualizar este pool como uma espécie de
“tanque” com instruções a serem executadas. As unidades de execução
trabalham constantemente executando as instruções deste pool que não
possuem dependências em relação a outras instruções. A ordem na qual
essas instruções são executadas não é necessariamente a mesma ordem na
qual elas se encontram nos programas. Uma unidade de retirada é
encarregada de finalizar as instruções, o que consiste em armazenar valores
finais na memória e nos registradores. Esta unidade de retirada é
encarregada de restabelecer a ordem original das instruções, conforme se
encontram nos programas.
Figura 8.24
Modelo simplificado de um processador
de microarquitetura P6.
MOV AX,2000
DEC BX
JZ LAB01
MOV AX,1000
INC CX
LAB01: …
Micro-ops
O núcleo dos processadores de arquitetura P6 é RISC. Sua unidade de
busca e decodificação converte as instruções CISC (x86) obtidas da memória
em instruções RISC. A Intel prefere chamar essas instruções RISC de micro-
ops.
Capítulo 8 – Arquitetura de processadores 8-65
Figura 8.25
Diagrama interno de
processadores P6.
Adições na arquitetura P6
O Pentium Pro foi o primeiro processador a utilizar esta arquitetura. Com o
Pentium II, algumas alterações importantes foram feitas, como a adição de
instruções MMX, maior eficiência na execução de programas de 16 bits e
alterações estratégicas na cache L2. Como sabemos, o Pentium Pro tinha 256
kB de cache L2 integrada, e o Pentium II, assim como as primeiras versões
do Pentium III, usavam uma cache L2 separada do núcleo, formada por
chips SRAM, com 512 kB e operando com a metade da freqüência do
núcleo.
O Pentium III recebeu novas instruções chamadas SSE. São novas instruções
MMX e para processamento de gráficos em 3D. Posteriormente o Pentium
III teve a sua cache L2 integrada ao núcleo. Esta cache passou também a ter
256 kB e opera com a mesma freqüência do núcleo. Finalmente o Pentium
III Tualatin teve esta cache aumentada para 512 kB.
Arquitetura do Pentium 4
O Pentium 4 e o Intel Xeon são os primeiros processadores a utilizarem a
nova arquitetura Netburst da Intel. Apesar de ter muitos pontos em comum
com a arquitetura P6, a Netburst é um projeto totalmente novo.
Capítulo 8 – Arquitetura de processadores 8-67
Figura 8.26
Diagrama interno do Pentium
4.
De 32 para 64 bits
Os processadores usados em praticamente todos os PCs modernos utilizam a
arquitetura x86, também chamada de IA-32. O termo x86 é devido à origem
dos processadores usados no PC, começando com o a família 8086/8088.
Processadores 8086, 8088, 80186, 80188 e 80286 eram todos de 16 bits.
Significa que a maioria das suas instruções operavam com valores inteiros de
até 16 bits, e que praticamente todos os seus registradores internos tinham 16
bits.
Tanto a Intel como a AMD estão entrando na era dos 64 bits, cada uma com
sua própria arquitetura:
Capítulo 8 – Arquitetura de processadores 8-69
Intel: IA-64
AMD: AMD x86-64
Intel IA-64
A arquitetura IA-64 é incompatível com a IA-32. Isto significa que os
programas que usamos nos PCs atuais não funcionarão nos PCs baseados na
arquitetura IA-64. Para facilitar a transição entre as arquiteturas IA-32 e IA-
64, o processador Intel Itanium (o primeiro a ser produzido com a IA-64)
utiliza um tradutor interno de instruções IA-32 para IA-64. Desta forma
poderá utilizar os programas atuais, porém com desempenho reduzido.
AMD x86-64
A AMD também lançará processadores de 64 bits, entretanto foi adotada
uma arquitetura diferente, chamada AMD x86-64. Entendendo de forma
bem simples, esta arquitetura engloba a atual IA-32 (ou x86, de 32 bits) e
adiciona recursos de 64 bits. Desta forma os programas poderão operar com
valores de 64, 32, 16 e 8 bits. Os atuais programas de 32 bits funcionarão
perfeitamente nesta nova plataforma. Internamente os processadores
possuirão os mesmos registradores internos encontrados nas máquinas x86,
porém ampliados para 64 bits. É uma evolução parecida com a transição de
16 para 32 bits, a partir do 80386. No 386, todos os registradores e instruções
de 16 bits foram mantidos, e ainda ampliados para 32 bits.
8-70 Hardware Total
Os programas atuais para 32 bits continuarão funcionando normalmente,
com seu pleno desempenho, ao contrário do que ocorre na arquitetura IA-
64, que é incompatível com a IA-32. Temos aqui um pequeno problema: os
futuros programas de 64 bits para a plataforma IA-64 serão incompatíveis
com os programas de 64 bits para a arquitetura x86-64. Os fabricantes de
software terão que desenvolver seus programas nas duas versões, e quando
não o fizerem, o usuário terá que usar apenas os programas específicos para
sua arquitetura, Intel ou AMD.
Figura 8.27
Processador Intel Itanium.
Além da cache L3, o Itanium possui uma cache L1 com 32 kB (16 kB para
código e 16 kB para dados) e cache L2 com 96 kB. Parece um tamanho
pequeno para uma cache L2, mas note que se compararmos com outros
processadores, é a cache L3 de 2 MB ou 4 MB do Itanium que faz o trabalho
que em outros processadores é feito pela cache L2, com 256 kB ou 512 kB.
Ainda baseado na tecnologia de 0,18, resultando na alta dissipação de calor
pelos seus 25 milhões de transistores do seu núcleo (sem contar os quase 300
milhões da cache L3), o Itanium terá sucessores baseados na nova tecnologia
de 0,13.
Figura 8.29
Cartucho PAC418, vista inferior.
OBS: Esses são os modelos previstos ao final de 2001, antes do lançamento do Itanium. A Intel
atrasou o seu lançamento e trabalhava na nova versão do Itanium, o McKinley, com clocks
mais elevados.
Figura 8.30
Identificação da voltagem do núcleo do
Itanium.