EXEMPLO DE TP1
DESCRIÇÃO RESUMIDA DE UMA ARQUITETURA DE
PROCESSADOR: O ESTUDO DE CASO DA INTEL X86 EM SUA
PRIMEIRA VERSÃO
NEY LAERT VILAR CALAZANS
[email protected]
Pontifícia Universidade Católica do Rio Grande do Sul (PUCRS)
PORTO ALEGRE, 09 DE ABRIL DE 2011
SUMÁRIO
SUMÁRIO ................................................................................................................................................................. 2
1
INTRODUÇÃO .................................................................................................................................................... 3
2
DIAGRAMA DE BLOCOS DO PROCESSADOR 8086............................................................................................... 3
3
ELEMENTOS DEFINITÓRIOS DA ARQUITETURA .................................................................................................. 4
3.1
3.2
3.3
3.4
3.5
REGISTRADORES DO PROGRAMADOR EM LINGUAGEM DE MONTAGEM ___________________________________ 4
CONJUNTO DE INSTRUÇÕES _________________________________________________________________ 6
FORMATOS DE INSTRUÇÃO _________________________________________________________________ 6
MODOS DE ENDEREÇAMENTO _______________________________________________________________ 6
LINGUAGEM DE MONTAGEM________________________________________________________________ 8
4
EXEMPLO DE PROGRAMA – SOMA DOS ELEMENTOS DE UM VETOR ................................................................. 8
5
REFERÊNCIAS BIBLIOGRÁFICAS .......................................................................................................................... 8
3
1 INTRODUÇÃO
A família x86 da Intel surgiu com o processador 8086 (também chamado iAPX86),
um microprocessador de 16 bits integrado em um único circuito integrado (CI ou chip)
projetado pela Intel entre o início de 1976 e a metade de 1978, quando foi colocado no
mercado [WIK11]. O 8086 foi o primeiro processador da arquitetura x86 de processadores
compatíveis, sendo aquela que hoje domina a maior parte do mercado de computadores
pessoais, laptops e servidores. O 8088 da Intel, colocado no mercado em 1979 é uma versão
levemente modificada do 8086, com um barramento de dados externo de apenas oito bits,
ao contrário dos 16 bits do barramento de dados do 8086 (o que na época permitia o uso de
circuitos de suporte mais baratos). Notadamente, o 8088, que é uma organização
levemente diferente da mesma arquitetura x86 inicial, foi o processador usado como
unidade central de processamento (UCP, em inglês CPU) do IBM PC original [WIK11].
Este documento descreve a arquitetura x86 em sua versão inicial. A descrição
assume uma forma bastante resumida, apontando apenas as características principais da
família, através de um Diagrama de Blocos do 8086, na Seção 2 e explorando brevemente
os cinco elementos definitórios da arquitetura x86 na Seção 3. Finalmente, ilustra-se a
utilização do 8086 fornecendo um programa em linguagem de montagem deste
processador, na Seção 4.
2 DIAGRAMA DE BLOCOS DO PROCESSADOR 8086
A Figura 1 apresenta o diagrama de blocos da Unidade Central de Processamento
(UCP, ou CPU em inglês) 8086, retirada da referência [INT79].
Figura 1 – Diagrama de blocos do processador 8086 e diagrama de pinagem para um
encapsulamento de 40 pinos do mesmo processador [INT79].
Note-se a simplicidade da organização, com apenas seis blocos principais, uma
unidade de controle e temporização (Control and Timing), um conjunto de registradores de
4
dados (Data Pointer and Index Registers), um conjunto de registradores de controle (Segment
Registers and Intruction Pointer), uma ULA e conjunto de qualificadores (16 bit ALU -- Flags),
uma unidade de controle de interface com os barramentos de acesso à memória e
dispositivos de entrada e saída (Bus Interface Unit) e uma fila de instruções (6-byte
Instruction Queue). Esta última unidade deriva de uma característica de paralelismo
primitiva deste processador, denominada de pré-busca de instruções (em inglês, prefetch). A
Bus Interface Unit adianta a busca de instruções consecutivas da memória enquanto
processador decodifica e executa as instruções que já estão na fila de seis bytes. Assim, esta
fila funciona como uma memória cache de instruções primitiva. Isto serve para aumentar a
vazão de processamento do 8086.
Todos os outros elementos do processador
correspondem àqueles estudados na disciplina de Organização de Computadores, quais
sejam, o Bloco de Controle, com os registradores de controle e o bloco de Dados, com os
registradores acessíveis ao programador em linguagem de montagem.
No diagrama de pinagem, deve-se notar o seguinte:
• Existem três pinos de alimentação, um VCC (pólo positivo da alimentação) e dois GND
(pinos de terra);
• Existe um pino de relógio (CLK), e um pino de reinicialização do processador (RESET),
características de um circuito síncrono;
• São vinte pinos de endereço para a memória (AD0 a A19). Os pinos de dados são
dezesseis (AD0 a AD15), multiplexados com os pinos de endereço da memória,
reduzindo a pinagem de trinta e seis pinos (20+16) para apenas vinte;
• Os demais quinze pinos são sinais de controle com diversas funções, incluindo controle
de acesso à memória, acesso a dispositivos de entrada e saída, interrupção do
processador por periféricos, etc. Mais informações sobre a função destes podem ser
encontradas na referência [INT79].
3 ELEMENTOS DEFINITÓRIOS DA ARQUITETURA
Este Capítulo tem como objetivo apresentar separadamente as cinco características
que definem a arquitetura x86 em sua versão inicial, implementada pela organização 8086.
3.1 REGISTRADORES DO PROGRAMADOR EM LINGUAGEM DE MONTAGEM
Os registradores do processador 8086 acessíveis ao programador em linguagem de
montagem são tipicamente de dezesseis bits e são mostrados na Figura 2. Nesta Figura
percebe-se que os registradores são agrupados por funcionalidade em quatro grupos:
• Registradores de Dados – São quatro de dezesseis bits, AX, BX, CX e DX, cada um dos
quais pode ser visto como dois registradores de oito bits, separando as partes alta (H) e
baixa (L) dos dezesseis bits. Assim pode-se contar com oito registradores de oito bits.
Estes são os registradores primários para armazenar e manipular dados;
• Registradores de Endereços – São quatro de dezesseis bits, SP, BP, SI e DI. Como os
endereços de memória do 8086 são de vinte bits, conforme visto na Seção 2, só uma
parte de um endereço está armazenada nestes. Um endereço efetivo de vinte bits é
5
obtido combinando um destes registradores com um dos registradores de segmento
descritos abaixo.
Figura 2 – Registradores do processador 8086 acessíveis ao programador em linguagem de
montagem. Todos são de 16 bits, embora alguns possam ser utilizados como dois registradores de oito
bits, tais como o registrador AX e os qualificadores [INT79].
• Registradores de controle – São dois de dezesseis bits, o IP, que corresponde ao
contador de programa (PC) de outros processadores e os qualificadores (FLAGSH e
FLAGSL) de diversas operações, as principais sendo os resultados de operações lógicas
e aritméticas. Na realidade este registrador é composto de bits manipulados
isoladamente; por exemplo, um deles armazena o sinal (0-positivo, 1–negativo) do
resultado da última operação lógica ou aritmética que foi executada pelo processador;
• Registradores de Segmento – São quatro registradores de dezesseis bits, CS, DS, SS, ES.
Eles são usados para determinar o início de uma região da memória do processador
8086 onde se armazena algum bloco fundamental de informação. Por exemplo, o
conteúdo do registrador CS determina onde na memória inicia a área que contém o
programa ora em execução, enquanto o registrador DS determina onde na memória
inicia a área que contém os dados do programa ora em execução, SS determina a região
de pilha, onde se armazena informações de natureza dinâmica (aquelas que são criadas
e destruídas ao longo da execução de um programa), e o registrador ES serve para
qualquer outro propósito onde se queira definir o início de um bloco de informações
na memória do processador. Um endereço de memória efetivo, de vinte bits, é
tipicamente formado tomando o valor de um registrador de segmento, acrescentando
quatro bits à direita deste valor (o que equivale a multiplicar o valor do registrador por
16) e somando este valor de vinte bits com um valor de dezesseis bits normalmente
proveniente de um registrador de endereço [INT79].
6
3.2 CONJUNTO DE INSTRUÇÕES
Cada instrução da arquitetura x86 na sua versão inicial ocupa um código objeto
cujo tamanho pode variar de um a cinco bytes. Em geral, o primeiro byte determina
quantos bytes a mais a instrução ocupa. As principais classes de instruções do processador
8086 são [INT79]:
• Transferência de Dados – Instruções que lêem ou escrevem dados na memória, na
pilha em um dispositivo de entrada ou saída ou qualquer segmento do programa,
como MOV;
• Instruções Aritméticas – de função óbvia, exemplos são: ADD, ADC (soma com vai-um
de operação anterior), SUB, etc.;
• Instruções Lógicas – de função óbvia, exemplos são: NOT, SHR (deslocamento de bits
para a direita ou shift), NOT, etc.;
• Manipulação de Cadeias de Caracteres – exemplo SCAS (Varre cadeia procurando por
bytes específicos), etc.
• Controle de Fluxo de Execução – instruções de salto como JMP (Salto incondicional), JE
e JZ (Saltos condicionais se igual ou se última instrução executada gerou 0 como
resultado), chamada e retorno de subrotina (CALL e RET), etc.
3.3 FORMATOS DE INSTRUÇÃO
Os formatos de instrução do processador 8086 são variáveis em termos de tamanho
e composição. Para dar um exemplo deles, mostra-se na Figura 3 um trecho do conjunto
de instruções. Aparecem ali exatamente doze instruções, incluindo três formas de ADD,
três de ADC, duas de INC (incremento), duas de ajuste de formato de representação de
dados (AAA e BAA) e duas de subtração (SUB). Note-se que um mesmo mnemônico pode
corresponder a mais de um código objeto de instrução, o que não acontece, por exemplo,
no MIPS para instruções. Note-se também que os modos de endereçamento fazem com
que existam três tipos de instrução ADD, uma para somar um registrador ou um dado de
uma posição de memória com um registrador, colocando o resultado ou na memória ou
em outro registrador; um ADD para somar uma constante a um registrador ou ao
conteúdo de uma posição da memória, e assim por diante. Finalmente, dependendo do
modo de endereçamento, um ADD, por exemplo, pode gerar código de dois bytes, de
quatro bytes, de três bytes ou mesmo o tamanho da instrução pode variar entre quatro e
três (veja os pontos onde se diz data if, que indicam que o último byte do código objeto
pode ou não existir, dependendo do que há em certos bits do início do código.
3.4 MODOS DE ENDEREÇAMENTO
A família x86 provê muitas formas diferentes de fazer acesso a operandos de
instruções. Isto define modos de endereçamento, ou seja, os diferentes meios de especificar
como obter cada operando de uma instrução. Operandos podem se encontrar em
registradores do processador, dentro da própria instrução (implicando em constantes), na
memória ou em portas de entrada e saída do processador. Além disto, endereços de
memória de portas de entrada e saída podem ser calculados de muitas formas diferentes.
7
Figura 3 – Trecho da especificação do conjunto de instruções do processador 8086, mostrando
algumas instruções e seus formatos específicos, retirado de [INT79].
Estas características fazem da x86 uma arquitetura muito distinta, por exemplo, da
arquitetura MIPS, que se baseia em apenas um modo de acesso à memória e entrada e
saída (registrador-base mais deslocamento) e três modos para especificar endereços da
memória de programa (relativo nos branches, pseudo-absoluto nos jumps e a registrador
em instruções como JR).
Discutem-se aqui apenas alguns dos principais modos de endereçamento da x86.
Os mais simples são o modo a registrador e o modo imediato, equivalentes a modos de mesmo
nome existentes, por exemplo, no MIPS. Os modos de acesso à memória são bem mais
numerosos e vários deles são bastante elaborados. Este fato deriva da escolha do emprego
de segmentos de memória para gerar endereços de memória de tamanho maior que o
tamanho dos registradores da arquitetura, como discutido brevemente na Seção 3.1. Esta
escolha derivou de razões tecnológicas, pois na época em que a arquitetura foi criada (anos
70 do século XX) a disponibilidade de memória externa excedia o que podia ser
endereçado por registradores de um microprocessador integrado em um único chip.
O modo de acesso à memória mais simples é o modo direto, com duas variantes:
longo e curto. Nestes, um valor de dezesseis ou oito bits contido no código da instrução
deve ser usado junto com um dos registradores de segmento para gerar o endereço efetivo
de memória onde fazer acesso (seja para leitura ou escrita). Outro é o modo indireto a
registrador, onde um registrador de índice ou um registrador base contém o valor a ser
combinado com um registrador de segmento para obter o endereço efetivo de memória.
Além destes, e não discutidos aqui, também existem os modos com endereçamento
base, indexado, base indexado, cadeia de caracteres, porta direta e porta direta indexado [INT79].
8
3.5 LINGUAGEM DE MONTAGEM
A linguagem de montagem da x86 inclui diversos recursos comuns à maioria das
linguagens de montagem de processadores: diretivas de controle do processo de
montagem e definição de dados, instruções especificadas por mnemônicos de poucas
letras, tipicamente três a cinco, primitivas muito simples para especificar dados. Uma
diferença com relação a arquiteturas do tipo Conjunto de Instruções Reduzido (em inglês
Reduced Instruction Set Computer, ou RISC) como o MIPS são modos mais sofisticados de
especificar os operandos das instruções, tais como a possibilidade de indexar vetores
diretamente no código (ver exemplo no programa da Seção a seguir).
4 EXEMPLO DE PROGRAMA – SOMA DOS ELEMENTOS DE UM VETOR
Um exemplo de programa está apresentado na Figura 4. Note-se que a estrutura
geral de um programa em linguagem de montagem é mantida, com segmentos de texto e
de dados. Mas não existe separação explícita entre estas áreas, que podem assim ocupar
regiões de memória contíguas, de acordo com o desejo do programador.
Existem três diretivas usadas neste programa: name para dar um nome ao
programa, que é puramente documentacional; org, cujo nome deriva de origin (origem em
Português), e que serve para definir o endereço a partir do qual montar o programa abaixo
desta; e db (de define byte) que serve para criar um ou mais bytes de dados na memória.
Deve-se salientar que os programas nesta arquitetura costumam ser bem mais compactos
que os de uma arquitetura RISC, graças à riqueza dos modos de endereçamento da x86.
; Pr ogr ama q ue ca lcu la a som a dos e lem en tos de u m v et or,
; ar maz ena o re su lta do na po si ção d e m em óri a ' m'
na me "c alc -s um"
or g 1 00 h
; D ir eti va pa ra co loc ar o có dig o do pro gr ama
; a p art ir do e nde reç o de me mór ia 10 0 h ex a
mo v
cx ,5
; G er a n úm ero d e e lem en tos d o v et or
mo v
al ,0
; R eg ist ra dor A L ( 8 b it s), v ai gu ard ar a som a
mo v
bx ,0
; B X vai c ont er o índ ic e d o vet or (i nic ia liz ad o c om 0)
ne xt : ad d
al ,ve ct or[ bx ] ; E st a i ns tru çã o b usc a o p ró xim o ele men to do v eto r
in c
bx
; I nc rem en ta o índ ice
lo op
ne xt
; E xe cut a laç o até cx =0 (l oo p f az CX -1 e sal ta se C X / =0)
mo v
m, al
; A rm aze na re su lta do da so ma em A L n a p os içã o de me mór ia m
en d:
re t
; va ria ble s:
ve ct or db
m
db
5, 4, 5 , 2 , 1
0
Figura 4 – Exemplo de programa para o processador 8086 e qualquer outro que implemente a
arquitetura x86 original. O programa soma todos os elementos de um vetor e escreve o resultado na
memória.
5 REFERÊNCIAS BIBLIOGRÁFICAS
[WIK11] Wikipedia. “x86 assembly language”. Available at http://en.wikipedia.org/wiki/
X86_assembly_language, captured in March 2011.
[INT79]
Intel Corporation. “Intel 8086”. Family Users Manual, 1979. 208 pages.
[INT90]
Intel Corporation. “8086 16-BIT HMOS MICROPROCESSOR 8086/8086-2/8086-1”.
Microprocessor Datasheet, September 1990. 30 pages.
Download

Exemplo de Trabalho TP1