Docsity
Docsity

Prepare-se para as provas
Prepare-se para as provas

Estude fácil! Tem muito documento disponível na Docsity


Ganhe pontos para baixar
Ganhe pontos para baixar

Ganhe pontos ajudando outros esrudantes ou compre um plano Premium


Guias e Dicas
Guias e Dicas

Apostila Informatica Cap 8 Arquitetura Processadores, Notas de aula de Engenharia Agronômica

informatica, hardware, software.

Tipologia: Notas de aula

2010

Compartilhado em 28/10/2010

valter-daniel-fantin-6
valter-daniel-fantin-6 🇧🇷

4.7

(287)

188 documentos

1 / 75

Toggle sidebar

Esta página não é visível na pré-visualização

Não perca as partes importantes!

bg1
Capítulo 8
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.
Registradores internos do processador
Para entender como um processador executa programas, precisamos
conhecer a sua arquitetura interna, do ponto de vista de software. Dentro de
um processador existem vários circuitos chamados de registradores. Os
registradores funcionam como posições de memória, porém o seu acesso é
extremamente rápido, muito mais veloz que o da cache L1. O número de
bits dos registradores depende do processador.
Processadores de 8 bits usam registradores de 8 bits
Processadores de 16 bits usam registradores de 16 bits
Processadores de 32 bits usam registradores de 32 bits
Processadores de 64 bits usam registradores de 64 bits
A figura 1 mostra os registradores internos dos processadores 8086, 8088 e
80286, todos de 16 bits. Todos os processadores têm uma linguagem baseada
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a
pf1b
pf1c
pf1d
pf1e
pf1f
pf20
pf21
pf22
pf23
pf24
pf25
pf26
pf27
pf28
pf29
pf2a
pf2b
pf2c
pf2d
pf2e
pf2f
pf30
pf31
pf32
pf33
pf34
pf35
pf36
pf37
pf38
pf39
pf3a
pf3b
pf3c
pf3d
pf3e
pf3f
pf40
pf41
pf42
pf43
pf44
pf45
pf46
pf47
pf48
pf49
pf4a
pf4b

Pré-visualização parcial do texto

Baixe Apostila Informatica Cap 8 Arquitetura Processadores e outras Notas de aula em PDF para Engenharia Agronômica, somente na Docsity!

Capítulo 8

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.

Registradores internos do processador

Para entender como um processador executa programas, precisamos conhecer a sua arquitetura interna, do ponto de vista de software. Dentro de um processador existem vários circuitos chamados de registradores. Os registradores funcionam como posições de memória, porém o seu acesso é extremamente rápido, muito mais veloz que o da cache L1. O número de bits dos registradores depende do processador.  Processadores de 8 bits usam registradores de 8 bits  Processadores de 16 bits usam registradores de 16 bits  Processadores de 32 bits usam registradores de 32 bits  Processadores de 64 bits usam registradores de 64 bits A figura 1 mostra os registradores internos dos processadores 8086, 8088 e 80286, todos de 16 bits. Todos os processadores têm uma linguagem baseada

8- 2 Hardware Total em códigos numéricos na memória. Cada código significa uma instrução. Por exemplo, podemos ter uma instrução para somar o valor de AX com o valor de BX e guardar o resultado em AX. As instruções do processador que encontramos na memória são o que chamamos de linguagem de máquina. Nenhum programador consegue criar programas complexos usando a linguagem de máquina, pois ela é formada por códigos numéricos. É verdade que alguns programadores conseguem fazer isso, mas não para programas muito longos, pois tornam-se difíceis de entender e de gerenciar. Ao invés disso, são utilizados códigos representados por siglas. As siglas são os nomes das instruções, e os operandos dessas instruções são os registradores, valores existentes na memória e valores constantes. Figura 8. 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 Esta instrução é representada na memória pelo seguinte código de máquina: 01 D Portanto a instrução ADD AX,BX é representada na memória por dois bytes, com valores 01 e D8 (em hexadecimal). Os bytes na memória que formam os programas são o que chamamos de linguagem de máquina. Esse códigos são lidos e executados pelo processador. Já as representações por siglas, como “ADD AX,BX”, formam o que chamamos de linguagem assembly. Quando programamos em linguagem assembly, estamos utilizando

8- 4 Hardware Total Os códigos hexadecimais que representam as instruções do processador são chamados de opcodes. As siglas que representam essas instruções são chamadas de mnemônicos. Daremos neste capítulo, noções básicas da linguagem assembly dos processadores modernos. Não ensinaremos a linguagem a fundo, mas o suficiente para você entender como os processadores trabalham. Como a programação nos processadores modernos é relativamente complexa, começaremos com o 8080, de 8 bits. A arquitetura do 8080 deu origem à do 8086, que por sua vez deu origem ao 386 e aos processadores modernos. Entendendo o 8080, que é bem mais simples, será mais fácil entender os processadores modernos.

Linguagem Assembly 8080

Aprender assembly do 8080 não é uma inutilidade, por duas razões. Primeiro porque você entenderá com muito mais facilidade o assembly dos processadores modernos, que afinal foram inspirados no 8080. Segundo que nem só de PCs vive um especialista em hardware. Você poderá trabalhar com placas controladoras que são baseadas nos processadores 8051 e Z80. Ambos são de 8 bits e também derivados do 8080, e são bastante utilizados em projetos modernos. A figura 2 mostra os registradores internos do 8080. São registradores de 8 bits, com exceção do PC (Program Counter) e do SP (Stack Pointer), que têm 16 bits. Figura 8. Registradores internos do 8080. O registrador mais importante é o acumulador. Ele é o valor de saída da unidade lógica e aritmética (ALU), na qual são realizadas todas as operações. Processadores atuais permitem fazer operações com todos os registradores, mas no 8080, o acumulador deve obrigatoriamente ter um dos operandos, e sempre é onde ficam os resultados. Os registradores B, C, D, E, H e L são de uso geral. Servem como operandos nas operações lógicas e aritméticas envolvendo o acumulador. O PC é um registrador de 16 bits, e seus valores são usados para formar o barramento de

Capítulo 8 – Arquitetura de processadores 8- 5 endereços do processador durante as buscas de instruções. O PC tem sempre o endereço da próxima instrução a ser executada. 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. Os FLAGS são um conjunto de 8 bits que representam resultados de operações aritméticas e lógicas. São os seguintes esses bits: Símbolo Nome Descrição Z Zero Indica se o resultado da operação foi zero CY Carry Indica se uma operação aritmética teve “vai um” ou “pede emprestado” P Parity Indica a paridade do resultado da operação. S Signal Indica o sinal de uma operação, se foi positivo ou negativo AC Aux. Carry Carry auxiliar, em algumas instruções especiais. Apesar de ser um processador de 8 bits, o 8080 é capaz de realizar algumas operações de 16 bits. Nessas operações, os registradores B e C são tratados como um valor de 16 bits. O mesmo ocorre com o par D/E e H/L. Além de manipular os registadores, o 8080 também permite obter valores na memória. Esses valores podem ser de 8 ou 16 bits, e nas instruções que fazem esses acessos, basta indicar o endereço de 16 bits da posição de memória que desejamos acessar. Além disso é possivel usar os registradores HL, BC e DE como apontadores para posições de memória. Nas instruções do assembly do 8080, o pseudo registrador M é na verdade a posição de memória (8 bits) cujo endereço está em HL.

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. LXI: Carrega um valor constante de 16 bits em um dos pares BC, DE, HL e no Stack Pointer. Exemplos: LXI H,35AFh ; Carega HL com o valor 35AF hexadecimal LXI D,25100 ; Carrega DE com o valor 25100 decimal LXI B,0 ; Carrega BC com 0 LXI SP,200 ; Carrega o Stack Pointer com 200 decimal Note que os números de 8 bits podem assumir valores inteiros positivos de 0 a 255 decimal (ou de 0 a FF em hexadecimal). Os números inteiros positivos de 16 bits podem assumir valores entre 0 e 65.535 decimal (ou 0 a FFFF hex). 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. LDA e STA: A instrução LDA carrega o acumulador (registrador A) com o valor que está no endereço de memória especificado. A instrução STA faz o inverso, ou seja, guarda o valor de A na posição de memória especificada. Exemplos: LDA 1000h ; Carrega A com o valor existente em [1000h] STA 2000h ; Guarda o valor de A em [2000h] Estamos utilizando a partir de agora a notação [nnnn] para indicar a posição de memória cujo endereço é nnnn. Esta notação não é usada no assembly para 8080, mas é usada no assembly do 8086 e superiores. LHLD e SHLD: A instrução LHLD carrega nos registradores H e L, o valor de 16 bits existente nas duas células de memória cujo endereço é especificado. A instrução SHLD faz o inverso. Exemplos:

8- 8 Hardware Total LHLD 1000h ; Faz L=[1000h] e H=[1001h] SHLD 2000h ; Guarda L em [2000h] e H em [2001h] Aqui vai mais um conceito importante. A memória do 8080 é uma sucessão de bytes, mas podemos também acessar words, ou seja, grupos de 16 bits. A operação envolve dos bytes consecutivos, e nas instruções indicamos apenas o endereço do primeiro byte. Os 8 bits menos significativos estão relacionados com a posição de memória indicada, e os 8 bits seguintes estão relacionados com a próxima posição. A figura 3 ilustra o que ocorre ao usarmos a instrução SHLD 2000h, levando em conta que H está com o valor 35h e L com o valor 8Ch. Figura 8. Armazenando HL em [2000h]. Esta convenção é utilizada por todos os processadores Intel. Sempre que é feita uma leitura ou escrita na memória, as partes menos significativas dizem respeito aos endereço menores, e as partes mais significativas correspondem aos endereços maiores. LDAX e STAX: Essas instruções fazem respectivamente operações de load (carrega) e store (guarda) do acumulador, usando a posição de memória cujo endereço está no par BC ou DE. Exemplos: 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.

8- 10 Hardware Total ADI. Soma com A, o valor constante especificado. O resultado fica armazenado em A. Exemplos: ADI 90 ; A = A+ ADI 35 ; A = A+ ADC: Semelhante à instrução ADD, exceto que o bit Carry também é adicionado. Esta operação serve para fazer somas com “vai 1”. Desta foram podemos dividir números grande em valores de 8 bits, e somar 8 bits de cada vez. Sempre que fazemos uma soma, o Carry ficará com o “vai 1” da operação, e assim poderá ser usado para somar a parcela seguinte. Exemplos: ADC L ; A = A+L+carry ADC D ; A = A+D+carry ADC M ; A = A+[HL]+carry ACI: Semelhante à instrução ADI, exceto pelo Carry também entrar na soma. Exemplos: ACI 90 ; A = A+90+carry ACI 84 ; A = A+84+carry SUB: Faz uma subtração de A com o registrador (A = A-registrador) ou com M. Exemplos: SUB D ; A = A-D SUB C ; A = A-C SUB M ; A = A-[HL] Nesta operação, o carry é ligado para indicar o resultado negativo, o que serve para fazer cálculos com vários dígitos, usando o método de “pedir emprestado”. SUI: Subtrai do acumulador, o número especificado. Por exemplo: SUI 20 ; A = A- SUI 82 ; A = A- 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: SBI 2Fh ; A = A-2Fh-carry SBI 73h ; A = A-73h-carry INR: Incrementa em uma unidade o valor do registrador especificado. Serve para implementar contadores. Exemplos: INR A ; A = A+ INR C ; C = C+ INR D ; D = D+ INR L ; L = L+ INR M ; [HL] = [HL]+ Quando o valor do registrador é FF e usamos esta instrução, ele passará a ficar com o valor 00 e o bit Carry será ligado. O bit Zero também será ligado, indicando que o resultado da operação foi zero. DCR: Diminui de uma unidade o conteúdo do registrado especificado. Esta instrução é usada para implementar contagens decrescentes. Exemplos: DCR A ; A = A- DCR C ; C = C- DCR D ; D = D- DCR H ; H = H- DCR M ; [HL] = [HL]- Quando o registrador tem o valor 1 e usamos esta instrução, o seu conteúdo passará a ser 00. O bit Zero será ligado, indicando que o resultado da operação foi 0. Se o registrador estiver com o valor 00 e usarmos novamente esta instrução, seu valor passará a ser FF. O bit Carry será ligado, para indicar que o resultado tem valor negativo. 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:

Capítulo 8 – Arquitetura de processadores 8- 13 Além das instruções já conhecidas, estamos usando a instrução JNZ (Jump if not Zero). Este instrução é um exemplo de desvio condicional. O programa continuará a partir do endereço TRAN caso o bit ZERO não esteja ativado, ou seja, se o resultado da operação anterior (C=C-1) não foi zero. Quando a contagem chegar a zero, a instrução JNZ não provocará o desvio, e o programa continuará com a instrução seguinte. 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. Para entender o funcionamento dessas instruções, temos que lembrar as tabelas verdade dos operadores NOT, AND, OR e XOR: 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. Chegou a hora de apresentar mais um conceito: a identificação dos bits. Em um grupo de 8 bits, chamamos cada um desses bits, da direita para a esquerda, de bit 0, bit 1, até bit 7, ou seja: bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit ORA, ORI, XRA, XRI: ORA faz a operação OR do acumulador com o registrador especificado; ORI faz o mesmo com um valor constante; XRA faz a operação XOR (OU Exclusivo) do acumulador com o registrador especificado, XRI faz o mesmo com um valor constante. Exemplos: 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 Aproveitamos para mostrar alguns macetes de programação assembly. A instrução ORI serve para ligar um bit selecionado. Para ligar os bits 7, 6, 5, 4, 3, 2, 1 e 0 basta fazer um ORI com valores 80h, 40h, 20h, 10h, 8, 4, 2 e 1, respectivamente. A instrução XRI fará a inversão do bit correspondente (use os mesmos valores que indicamos para a instrução ORI). A instrução XRA A tem o efeito de zerar o acumulador. CMP, CPI: A instrução CMP compara o acumulador com outros registradores. A instrução CPI compara o acumulador com um valor

8- 16 Hardware Total 9 bits, sendo 8 do acumulador e mais o Carry. A operação dessas instruções é mostrada na figura 5. Figura 8. Instruções RAL e RAR. CMA: Complementa o acumulador, ou seja, faz a inversão de todos os seus bits. STC, CMC: Essas instruções servem para carregar valores no Carry. A instrução STC faz Carry=1, e a instrução CMC inverte o valor do Carry. Note que não existe uma instrução para zerar o Carry. Ao invés dela, podemos usar STC seguida de CMC, ou então usar a instrução ANA A ou ORA A, que não alteram o valor de A mas zeram o Carry. 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. JMP: Esta é a principal e mais simples instrução de desvio. É o que chamamos de desvio incondicional, ou seja, sempre será executada, não importa em que condições. Por exemplo, ao encontrar a instrução JMP 8000h, o processador continuará a execução do programa a partir das instruções localizadas no endereço 8000h.

Capítulo 8 – Arquitetura de processadores 8- 17 CALL e RET: A instrução CALL também é um desvio, mas bem diferente do JMP. É uma chamada de rotina. Uma rotina é um trecho de programa que pode ser chamado de vários pontos de um programa principal. No final de uma rotina deve exitir uma instrução RET, que faz o processador retornar ao ponto imediatamente após a instrução CALL. Comparando as instruções CALL e JMP, a única diferença é que no caso da instrução CALL, o endereço da próxima instrução (endereço de retorno) é guardado no topo da pilha. O valor do SP (stack pointer é atualizado para permitir novos empilhamentos). A instrução RET simplesmente obtem o endereço no topo da pilha e o coloca em PC (Program Counter), fazendo com que a execução continue de onde parou. Mostraremos novamente nosso pequeno trecho de programa que move um certo número de bytes de uma parte para outra da memória, mas desta vez usando uma rotina. O trecho começa no endereço 1000, onde carregamos o par HL com o endereço da origem, DE com o endereço do destino e o registrador C com o número de bytes (no caso são 16 bytes, que corresponde a 10 em hexadecimal). A seguir é chamada uma rotina que está no endereço 1020. Esta é a rotina responsável pela movimentação. Depois que a rotina é chamada, a próxima instrução a ser executada é JMP 0, que está no endereço 100A. 1000: 21 00 81 LXI H, 8100 1003: 11 00 82 LXI D, 8200 1006: 0E 10 MVI C, 1008: CD 20 10 CALL 1020 100A: C3 00 00 JMP 0 ... 1020: 7E MOV A,M 1021: 12 STAX D 1022: 23 INX H 1023: 13 INX D 1024: 0D DCR C 1025: C2 20 10 JNZ 1020 1028: C9 RET Observe que a rotina de movimentação localizada no endereço 1020 é genérica. Ela pode mover dados entre duas posições quaisquer de memória, dadas por HL e DE. O número de bytes também pode ser qualquer (de 1 a 255), e deve ser dado em C. Dizemos então que HL, DE e C são os parâmetros desta rotina. É importante entender o que acontece com a stack ao executarmos instruções CALL e RET. Na instrução CALL, o endereço de retorno e empilhado. Na instrução RET, o endereço de retorno é desempilhado. No

Capítulo 8 – Arquitetura de processadores 8- 19 Nesta tabela mostramos a ação de cada uma desas instruções, e ainda uma interpretação dessas ações. Por exemplo, a instrução JZ pode ser usada logo depois uma operação aritmética e queremos que seja feito o desvio se o resultado foi zero. Pode ainda ser usada depois de uma comparação e queremos que o desvio seja feito se os valores comparados forem iguais. Da mesma forma existem as chamadas condicionais de rotinas e os retornos condicionais: CZ, CNZ, CC, CNC, CPE, CPO, CP, CM RZ, RNZ, RC, RNC, RPE, RPO, RP, RM RST n: Esta instrução é similar a uma instrução CALL. A diferença é que ela não precisa que seja indicado o endereço, pois está implícito. Podemos usá-la de 8 formas diferentes: RST 0 / RST 1 / RST 2 / RST 3 / RST 4 / RST 5 / RST 6 / RST 7 Essas instruções têm o mesmo efeito que: CALL 0000 / CALL 0008 / CALL 0010 / CALL 0018 / … / CALL 0038 O objetivo dessas instruções é economizar bytes, já que ao invés dos 3 bytes ocupados por uma instrução CALL, usa apenas um byte. Quando uma certa rotina é usada muitas vezes em um programa, podemos colocá-la a partir de um desses endereços e chamá-las através das instruções RST. Note que esses endereços estão separados apenas por 8 bytes, portanto não é possível colocar diretamente neles, rotinas maiores que este tamanho. O que normalmente fazemos é usar nesses endereços, instruções de JMP para outra área onde ficam as rotinas. PCHL: Carrega em PC o valor existente em HL. Isto é equivalente a executar um JMP para o endereço especificado por HL. É útil quando queremos desviar para um local variável, em função do valor em HL, obtido por exemplo, de uma tabela de endereços. Operações com a pilha, E/S e controle Para completar o conjunto de instruções do 8080, falta apenas uma pequena miscelânea de instruções para para manipulação da stack, entrada/saída e controle.

8- 20 Hardware Total PUSH e POP: Já vimos como a stack é usada para emplilhar e desempilhar endereços nas instruções CALL e RET. São sempre valores de 16 bits. Além de endereços, podemos ainda empilar e desempilhar dados na stack. Por exemplo, a instrução PUSH H guardará o valor de HL no topo da stack. A instrução POP H fará o inverso, ou seja, retirará da pilha o valor do seu topo e o copiará para HL. As instruções PUSH e POP podem ser usadas com os parâmetros B, D e H, que operam com os pares BC, DE e HL. Podemos ainda usar PUSH PSW, que salva em um grupo de 16 bits, o valor do acumulador e dos flags. A instrução POP PSW faz o inverso. XTHL: Lembra da instrução XCHG, que troca os valores de HL e DE? A instrução XTHL faz algo parecido. Troca os valores de HL e do topo da pilha. 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. IN, OUT: São instruções importantíssimas que servem para o processador trocar dados com o mundo exterior. Através da instrução IN podemos obter dados provenientes de interfaces que estão ligadas aos periféricos. O dado lido ficará no acumulador. A instrução OUT faz o inverso, ou seja, transfere para o endereço de E/S especificado, o valor que está no acumulador. Exemplos: IN 70h ; Lê dado que está no endereço de E/S 70h OUT 40h ; Envia para o endereço de E/S 40h, o valor de A DI, EI: Essas instruções controlam as interrupções de hardware. DI faz com que as interrupções sejam desabilitadas. EI faz com que sejam habilitadas novamente. São úteis durante o atendimento a interrupções de hardware e em certos trechos críticos que não podem ser interrompidos. HLT: Halt. Faz o processador parar de executar instruções. O processador só sai deste estado quando ocorre uma interrupção. 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.