instituto federal de educação, ciência e tecnologia de ... · - os microprocessadores são...

60
Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 1 Instituto Federal de Educação, Ciência e Tecnologia de São Paulo Apostila de Laboratório de Microprocessadores Prof. Dr. Gilberto Igarashi 2016

Upload: duongngoc

Post on 07-Feb-2019

214 views

Category:

Documents


0 download

TRANSCRIPT

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 1

Instituto Federal de Educação, Ciência e Tecnologia de São Paulo

Apostila de Laboratório de Microprocessadores

Prof. Dr. Gilberto Igarashi

2016

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 2

Experiência 1: Apresentação da estrutura da disciplina, editores, compiladores e simuladores

Objetivo Apresentar para os alunos a estrutura da disciplina, bem como as ferramentas que serão utilizadas durante a disciplina. Conteúdo Esta disciplina tem como objetivo introduzir o aluno na programação de software embarcado (firmware) bem como apresentar os dispositivos que irão executa-lo: os microprocessadores e os microcontroladores. - os Microprocessadores são dispositivos digitais que possuem basicamente a CPU (Central Processing Unit – Unidade de Processamento Central), onde esta localizada a ALU (Aritmetic Logic Unit – Unidade Lógica Aritmética) responsável pela execução dos cálculos, e o circuito controlador para acesso a memória. - os Microcontroladores são dispositivos digitais que possuem um microprocessador interno otimizado além de periféricos externos adicionais responsáveis por diversas funções de controle/automação. Ex: interface I/O, timers, interface serial, conversores analógico/digitais. Atualmente, as ferramentas para a programação destes dispositivos evoluíram de forma que a sua programação pode ser realizada em diversas linguagens. Estas podem ser classificadas, basicamente, em: - linguagem de baixo nível: linguagem de programação mais próximo ao nível da máquina, que permite a melhor compreensão e domínio do hardware utilizado, bem como o menor código possível; em contrapartida torna o código não portável entre microcontroladores/microprocessadores de diferentes modelos/fabricantes. Ex: linguagem Assembly - linguagem de alto nível: linguagem de programação mais próximo ao nível do usuário, oferecendo mais facilidade na abstração para a elaboração do código e na portabilidade de código entre microcontroladores/microprocessadores de diferentes modelos/fabricantes; em contrapartida o código geralmente acaba ficando com tamanho superior a um código de mesma função elaborado diretamente na linguagem Assembly. Ex: linguagem C, linguagem Basic. Um programa escrito em linguagem Assembly ou em linguagem C (chamado de PROGRAMA FONTE), não pode ser diretamente processado pelo microprocessador/microcontrolador do sistema, devendo primeiramente ser traduzido para a sua linguagem de máquina, com o uso de tabelas ou através de um programa destinado para tal tarefa chamado de COMPILADOR. Define-se COMPILADOR como um programa aplicativo que transforma um arquivo constituído por códigos ASCII, gerado normalmente por um editor de textos, em um arquivo binário que contém os bytes correspondentes às instruções (códigos de máquina) do microprocessador/microcontrolador. Como resultado da compilação geralmente são criados dois arquivos: - arquivo de mesmo nome, porém, com a extensão “.LST”, que corresponde a um arquivo texto que mostra o resultado da compilação, contendo para cada linha de programa, o código de máquina correspondente à instrução, sendo muito útil na depuração de erros de compilação. - arquivo de mesmo nome, porém com a extensão “.HEX”, usado por gravadores de memórias e microcontroladores e também pelo programa simulador. Existem no mercado programas, chamados IDE (Integrated Development Enviroment – Ambiente de Desenvolvimento Integrado) que disponibilizam uma interface contendo o editor de texto, o compilador e ferramentas para debug num mesmo programa. Ex: Reads51, MPLAB IDE, Keil. Também existem simuladores dos mais diversos capazes de simular tanto o funcionamento do microprocessador/microcontrolador, quanto hardwares externos conectados a ele. Ex: EdSim51, Proteus. Em nossas aulas utilizaremos os seguintes programas: - DosBox (simulador do MS-DOS) - Debug (simulador para x86) Devido ao simulador Debug ter sido projetado na era do sistema MS-DOS (sistema anterior ao Windows) para ser executado nas plataformas Windows mais atuais é necessário a utilização conjunta do simulador DosBox, de forma a simular o sistema MS-DOS e assim poder executar o Debug.

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 3

Para executar o Debug através do DosBox siga os seguintes procedimentos: 1) crie uma pasta C:\TEMP em seu computador e copie nesta pasta o arquivo debug.exe 2) execute o DosBox (pode ser executado no próprio pendrive) 3) digite: MOUNT D C:\TEMP 4) digite: D: 5) digite: DEBUG

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 4

Experiência 2: Introdução ao Debug, sistemas microprocessados e movimentação de variáveis no microprocessador x86

Objetivo Apresentar o software Debug, noções básicas da estrutura de um microprocessador e as instruções em linguagem Assembly básicas utilizadas para a movimentação de variáveis. Conteúdo Antes de iniciarmos os trabalhos do laboratório serão introduzidos de forma subjetiva alguns conceitos acerca da

estrutura básica que acompanha a maior parte dos sistemas microprocessados, ilustrado pela Figura 1.

Figura 1: Estrutura básica de um sistema microprocessado genérico

Memória: são dispositivos responsáveis por armazenar os dados (entenda-se números binários). Funcionam como um

armário contendo várias gavetas, conforme ilustra a Figura 2. Portanto, quando dissermos “armazene o valor 20H no endereço de memória 01H” estaremos armazenando o dado 20H na gaveta de endereço 01H.

Figura 2: Diagrama representativo de uma memória genérica

Microprocessador: é o dispositivo central, que comanda todos os outros dispositivos segundo o firmware programado,

conforme ilustra a Figura 3. Possui internamente uma CPU (que contém a ULA, responsável pela execução de operações aritméticas) e uma memória interna dedicada, cujas gavetas são identificadas por nomes, e não por endereço de memória. Estas gavetas são chamadas de registradores e cada um destes registradores possui uma função específica.

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 5

Figura 3: Diagrama representativo de um microprocessador genérico

O software Debug tem como objetivo simular a estrutura básica mostrada na Figura 1. Inicializando o Debug, e digitando o comando “?” obtemos uma lista dos comandos disponíveis. A (Assemble) C (Compare) D (Dump) E (Enter) F (Fill) G (Go) H (Hexarithmetic) I (Input) L (Load) M (Move) N (Name) P (Ptrace) Q (Quit) R (Register) S (Search) T (Trace) U (Unassemble) W (Write) Comando R (Register) Mostra e altera o conteúdo dos registros. Digitando: -R serão exibidos na tela o conteúdo dos registradores: AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=075F ES=0B3C SS=0B3C CS=075F IP=0100 NV UP EI PL NZ NA PO NC 0B3C:0100 030000 MOV [0000],AX Todos estes registros tem tamanho de 16 bits. Dentre eles podemos destacar:

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 6

AX,BX,CX,DX ; registradores de dados genéricos DS ; (Data Segment) registrador que aponta para um endereço de referência na memória de dados CS ; (Code Segment) registrador que aponta para um endereço de referência na memória de programa Para alterar o valor de um determinado registro, por exemplo alterar o valor contido no registro AX de 0000H para 12ABH, digitamos: -R AX AX 0000 :12AB Portanto, digitando novamente: -R Será exibido: AX=12AB BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=075F ES=0B3C SS=0B3C CS=075F IP=0100 NV UP EI PL NZ NA PO NC 0B3C:0100 030000 MOV [0000],AX Comando D (Dump) Mostra o conteúdo da memória de dados, ou da memória de programa. Para visualizar o valor contido nos endereços da memória de dados digitamos: -D DS:0000 Será exibido: 075F:0000 CD 20 5E A7 00 EA FD FF-AD DE 4F 03 A3 01 8A 03 . ^.......0..... 075F:0010 A3 01 17 03 A3 01 92 01-01 01 01 00 02 FF FF FF ................ 075F:0020 FF FF FF FF FF FF FF FF-FF FF FF FF 00 00 00 00 ................ 075F:0030 00 00 14 00 18 00 5F 07-FF FF FF FF 00 00 00 00 ......_......... 075F:0040 20 20 20 20 20 20 20 20-00 00 00 00 00 00 00 00 ........ 075F:0050 20 20 20 20 20 20 20 20-00 00 00 00 00 00 00 00 ........ 075F:0060 20 20 20 20 20 20 20 20-00 00 00 00 00 00 00 00 ........ 075F:0070 20 20 20 20 20 20 20 20-00 00 00 00 00 00 00 00 ........ Cada endereço de memória tem tamanho de 32 bits e é identificado por um endereço composto de 16 bits + 16 bits, cujo valor dos 16 bits mais significativos esta gravado no registro DS. Para visualizar o valor contido nos endereços da memória de programa digitamos: -D CS:0100 Será exibido: 075F:0100 CD 20 5E A7 00 EA FD FF-AD DE 4F 03 A3 01 8A 03 . ^.......0..... 075F:0110 A3 01 17 03 A3 01 92 01-01 01 01 00 02 FF FF FF ................ 075F:0120 FF FF FF FF FF FF FF FF-FF FF FF FF 00 00 00 00 ................ 075F:0130 00 00 14 00 18 00 5F 07-FF FF FF FF 00 00 00 00 ......_......... 075F:0140 20 20 20 20 20 20 20 20-00 00 00 00 00 00 00 00 ........ 075F:0150 20 20 20 20 20 20 20 20-00 00 00 00 00 00 00 00 ........ 075F:0160 20 20 20 20 20 20 20 20-00 00 00 00 00 00 00 00 ........ 075F:0170 20 20 20 20 20 20 20 20-00 00 00 00 00 00 00 00 ........ Cada endereço de memória tem tamanho de 32 bits e é identificado por um endereço composto de 16 bits + 16 bits, cujo valor dos 16 bits mais significativos esta gravado no registro CS.

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 7

Comando E (Enter) Altera o valor contido em um endereço da memória de dados, ou da memória de programa. Para alterar o conteúdo do endereço da memória de dados 075F:0000H de CDH para 41H digitamos: -E DS:0000 Será exibido na tela o endereço de memória e o valor atual contido neste endereço (no caso CDH): 075F:0000 CD. Para altera-lo basta digitar após o ponto ‘.’ o novo valor (no caso 41H): 075F:0000 CD.41 Se for digitado <Enter> após digitar o novo valor o processo de alteração de valores se encerra. Se for digitado <Space> será exibido o valor do endereço seguinte e solicitado o seu novo valor. Portanto, digitando o comando: - D DS:0000 Será exibido: 075F:0000 41 20 5E A7 00 EA FD FF-AD DE 4F 03 A3 01 8A 03 A ^.......0..... 075F:0010 A3 01 17 03 A3 01 92 01-01 01 01 00 02 FF FF FF ................ 075F:0020 FF FF FF FF FF FF FF FF-FF FF FF FF 00 00 00 00 ................ 075F:0030 00 00 14 00 18 00 5F 07-FF FF FF FF 00 00 00 00 ......_......... 075F:0040 20 20 20 20 20 20 20 20-00 00 00 00 00 00 00 00 ........ 075F:0050 20 20 20 20 20 20 20 20-00 00 00 00 00 00 00 00 ........ 075F:0060 20 20 20 20 20 20 20 20-00 00 00 00 00 00 00 00 ........ 075F:0070 20 20 20 20 20 20 20 20-00 00 00 00 00 00 00 00 ........ Comando A (Assemble) Insere uma instrução (código) Assembly na memória de programa. Vamos utilizar como exemplo nesta etapa uma instrução simples para movimentação de valores contidos nos endereços de memória: a instrução MOV. Supondo que desejamos movimentar (copiar) o valor contido no registrador AX para o endereço de memória de dados 075F:0000H. Para isto podemos utilizar a instrução MOV da seguinte forma: MOV [0],AX

O mecanismo básico de funcionamento de um sistema microprocessado é ilustrado na Figura 4:

Figura 4: Funcionamento básico de um sistema microprocessado para armazenar um valor na memória de dados

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 8

A etapa 1 é chamada de Fetch e consiste na busca da instrução a ser executada na memória de programa (neste caso MOV [0],AX). A etapa 2 é a execução da instrução propriamente dita. Esta instrução é o nosso programa a ser executado pelo microcontrolador, e este programa deve ser armazenado na memória de programa. Ela está no formato texto e, para que possa ser armazenada na memória de programa, deve ser convertido para número. O programa responsável por este trabalho é o COMPILADOR, e o Debug já possui um compilador interno, acessível pelo comando A. Portanto, para inserir nossa instrução precisamos definir o endereço de memória onde será inserida esta instrução. Supondo que desejamos inserir esta instrução no endereço de memória de programa 075F:0100H. Para isto, digitamos o comando A da seguinte forma: -A CS:0100 Em seguida será exibido a posição de memória de programa 075F:0100H e esperado a digitação da instrução Assembly para compilação. Digitando nosso código, teremos: 075F:0100 MOV [0],AX 075F:0103 Se tudo foi digitado corretamente até aqui o Debug irá interpretar a instrução Assembly digitada, compila-la e armazena-la na memória de programa no endereço 075F:0100H. Para verificar basta fazer uso do comando D: -D CS:0100 Será exibido: 075F:0100 A3 00 00 A7 00 EA FD FF-AD DE 4F 03 A3 01 8A 03 ..........0..... 075F:0110 A3 01 17 03 A3 01 92 01-01 01 01 00 02 FF FF FF ................ 075F:0120 FF FF FF FF FF FF FF FF-FF FF FF FF 00 00 00 00 ................ 075F:0130 00 00 14 00 18 00 5F 07-FF FF FF FF 00 00 00 00 ......_......... 075F:0140 20 20 20 20 20 20 20 20-00 00 00 00 00 00 00 00 ........ 075F:0150 20 20 20 20 20 20 20 20-00 00 00 00 00 00 00 00 ........ 075F:0160 20 20 20 20 20 20 20 20-00 00 00 00 00 00 00 00 ........ 075F:0170 20 20 20 20 20 20 20 20-00 00 00 00 00 00 00 00 ........ Comando U (Unassemble) Mostra na tela um resumo do programa digitado até o momento. Para exibir o código armazenado a partir da posição de memória de programa CS:0100H digitamos: -U CS:0100 Será exibido: 075F:0100 A30000 MOV [0000],AX 075F:0103 0000 ADD [BX+SI],AL 075F:0105 0000 ADD [BX+SI],AL 075F:0107 0000 ADD [BX+SI],AL 075F:0103 0000 ADD [BX+SI],AL 075F:0109 0000 ADD [BX+SI],AL 075F:010B 0000 ADD [BX+SI],AL 075F:010D 0000 ADD [BX+SI],AL 075F:010F 0000 ADD [BX+SI],AL 075F:0111 0000 ADD [BX+SI],AL 075F:0113 0000 ADD [BX+SI],AL 075F:0115 0000 ADD [BX+SI],AL

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 9

Comando T (Trace) Executa, instrução por instrução, o programa armazenado na memória de programa. Para que o microprocessador saiba onde está localizada na memória de programa a instrução a ser executada ele faz uso do registrador IP. Se, digitando o comando R obtermos: AX=12AB BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=075F ES=075F SS=075F CS=075F IP=0100 NV UP EI PL NZ NA PO NC 075F:0100 A30000 MOV [0000],AX Significa que o processador irá executar a instrução armazenada no endereço 16bits:16bits, onde os 16bits da esquerda correspondem ao valor armazenado no registro CS e os 16bits da direita correspondem ao valor armazenado no registro IP. Ou seja, será executada a instrução contida no endereço 075F:0100H. Nossa próxima etapa é executar a instrução programada. Para isto, basta executar a função T digitando: -T Será exibida na tela: AX=12AB BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=075F ES=075F SS=075F CS=075F IP=0103 NV UP EI PL NZ NA PO NC 075F:0003 A7 CMPSW Repare que o registro IP incrementou em 3 (quantidade de bytes da instrução “MOV [0],AX” executada). Para visualizar o valor de AX copiado no endereço de memória de dados 075F:0000H basta utilizar o comando D: -D DS:0000 Será exibida na tela: 075F:0000 AB 12 00 A7 00 EA FD FF-AD DE 4F 03 A3 01 8A 03 ..........0..... 075F:0010 A3 01 17 03 A3 01 92 01-01 01 01 00 02 FF FF FF ................ 075F:0020 FF FF FF FF FF FF FF FF-FF FF FF FF 00 00 00 00 ................ 075F:0030 00 00 14 00 18 00 5F 07-FF FF FF FF 00 00 00 00 ......_......... 075F:0040 20 20 20 20 20 20 20 20-00 00 00 00 00 00 00 00 ........ 075F:0050 20 20 20 20 20 20 20 20-00 00 00 00 00 00 00 00 ........ 075F:0060 20 20 20 20 20 20 20 20-00 00 00 00 00 00 00 00 ........ 075F:0070 20 20 20 20 20 20 20 20-00 00 00 00 00 00 00 00 ........ Repare que foram armazenados nos endereços de memória de dados: 075F:0000 AB 075F:0001 12 Sendo que no registro AX o valor armazenado é 12ABH. Este formato de armazenamento de valores é chamada de

Little-endian. A sequência de armazenamento oposta a esta é chamada de Big-endian, conforme ilustra a Figura 5.

Figura 5: Formatos Big-endian e Little-endian

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 10

Comandos N, W e L No Debug é possível salvar seu programa em linguagem Assembly em um arquivo para que o mesmo possa ser recuperado mais tarde. Os arquivos são salvos via Debug com formatação binária e com extensão “.com”. Um resumo do procedimento a ser seguido é ilustrado a seguir: -N TESTE.COM -R AX=12AB BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=075F ES=075F SS=075F CS=075F IP=0100 NV UP EI PL NZ NA PO NC 075F:0100 A30000 MOV [0000],AX -R BX BX 0000 :0000 -R CX CX 0000 :0500 -R AX=12AB BX=0000 CX=0500 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=075F ES=075F SS=075F CS=075F IP=0100 NV UP EI PL NZ NA PO NC 075F:0100 A30000 MOV [0000],AX -W Gravando 00500 bytes Para salvar o programa no arquivo “.com” primeiro deve ser atribuído um nome ao mesmo. Isto é conseguido através do comando N seguido do nome do arquivo com extensão “.com”. Este nome não deve ultrapassar 8 caracteres de tamanho, nem utilizar caracteres com acento. O passo seguinte é carregar os registradores BX e CX com o tamanho do programa em bytes que, nos nossos exemplos de aula, sempre iniciarão a partir do endereço CS:0100H. Uma prática que torna esse processo menos trabalhoso é sempre colocar um tamanho fixo que seja sempre acima do tamanho real do programa. Um bom valor para as aulas são 500 bytes, uma vez que os nossos programas dificilmente ultrapassarão este limite. Portanto, admitindo a quantidade de 500 bytes será salvo no arquivo “.com” os bytes contidos na memória de programa a partir do endereço CS:0100H até o endereço CS:0100H+499 = CS:02F3H. Por último, basta utilizar o comando W que automaticamente salvará os bytes da memória de programa no arquivo “.com” definido. Uma vez que o arquivo esta salvo é possível abri-lo novamente. Um resumo do procedimento a ser seguido é ilustrado a seguir: -N TESTE.COM -L Antes de carregar o arquivo “.com” salvo deve ser informado ao programa Debug o nome deste arquivo através do comando N. Em seguida, basta utilizar o comando L que carregará os bytes salvos nas mesmas posições que se encontravam anteriormente. Exercícios 1) Verifique o que realiza a instrução MOV AX,[0] utilizando os comandos do Debug mostrados até aqui. 2) Quantos bytes são ocupados na memória de programa para armazenar o programa abaixo? MOV AX,[0000] MOV [0010],AX MOV AX,[0002] 3) Utilizando os comandos do Debug carregue os seguintes valores nos formatos Big-endian e Little-endian:

a) valor ABCDEFH a partir do endereço de memória de dados 075F:0000H b) valor 123456H a partir do endereço de memória de programa 075F:0020H

4) A partir do endereço da memória de dados 075F:0000H preencha 16 posições seguidas com os valores de 00H a 0FH.

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 11

Experiência 3: Registradores e movimentação de variáveis no microprocessador x86

Objetivo Apresentar com mais detalhes os registradores do microprocessador x86 e as instruções em linguagem Assembly básicas utilizadas para a movimentação de variáveis. Conteúdo Digitando o comando R no Debug temos na tela uma visão dos principais registros do x86: AX=12AB BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=075F ES=075F SS=075F CS=075F IP=0100 NV UP EI PL NZ NA PO NC 075F:0100 A30000 MOV [0000],AX O processador x86 possui 4 registradores de uso geral de 16 bits cada denominados AX, BX, CX e DX, conforme

ilustra a Figura 6. O termo uso geral é exatamente porque o programador pode usá-los para evitar armazenar um determinado dado na memória externa, economizando assim o tempo de busca na memória de dados e tornando a execução do programa mais veloz. Além disso, esses registradores podem ser divididos logicamente em 2 sub-registradores de 8 bits, assim, o lado mais significativo do registrador de 16 bits recebe a letra H (High) e o lado menos significativo recebe a letra L (Low), formando então um novo conjunto de 8 registradores de 8 bits. É importante notar que essa divisão é somente lógica pois, fisicamente, o espaço ocupado pelo registrador e seus sub-registradores é o mesmo. Ou seja, uma alteração em AH alteraria automaticamente o conteúdo de AX.

Figura 6: Registradores de uso geral do x86 Os registradores de uso geral também possuem características de uso específico. O registrador CX é usado pelo processador para armazenar valores de contagem de loops, o registrador AX é usado para armazenar resultados de multiplicações e parcelas de divisões, o registrador BX é usado para armazenar endereços base (ponteiro) para acesso indireto à memória de dados e o registrador DX é usado para armazenar endereços de dispositivos de entrada e saída para comunicação do processador com o mundo externo.

Outro grupo de registradores são os registradores de ponteiro e de índice, conforme ilustra a Figura 7. Tais registradores são de uso específico e interno ao processador, ou seja, seus valores referenciam operações internas ao processador e se alterados influenciarão nas tarefas do mesmo. Como o próprio nome já diz eles têm como função indicar ao processador o ponto onde se encontra determinada informação.

Figura 7: Registradores de ponteiro e de índice do x86

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 12

O registrador SP indica o ponto onde está localizado o topo da pilha de armazenamento do processador na memória. O conceito de pilha será detalhado mais adiante. Os registradores BP, SI e DI são aplicados para acessos em programação de forma mais automatizada. Eles não serão explorados neste curso. Por último o registrador IP, que tem a função de indicar o endereço de memória em que está situada a próxima instrução do programa que será executada.

Por último existe o grupo de registradores de segmento, conforme ilustra a Figura 8. Tais registradores apontam para os segmentos da memória onde estão armazenadas as informações necessárias para o funcionamento do processador. O registrador CS indica o segmento da memória de programa onde se encontra o código do programa que será executado. O registrador DS indica o segmento da memória de dados onde estão armazenadas as variáveis utilizadas no programa. O registrador SS indica o segmento da memória de dados onde a pilha do processador está armazenando os dados a ela destinados. O registrador EX indica o segmento extra, uma área de dados adicional do processador.

Figura 8: Registradores de segmento do x86 O processador x86 possui ainda 8 flags, com tamanho de um bit, usados para armazenar estados do sistema (flags de

status) e controlar as operações internas do mesmo (flags de controle), conforme ilustra a Figura 9.

Figura 9: Flags do processador x86 Os flags de status são modificados pelo processador geralmente após operações aritméticas ou lógicas, de forma a refletir propriedades dos resultados dessas operações. Os flags de controle são modificados pelo usuário para alterar alguma característica particular do sistema. Elas serão exploradas com mais detalhes numa próxima etapa desta apostila. A instrução MOV possui a seguinte sintaxe:

MOV operando1, operando2 Onde operando1 e operando2 são, respectivamente, o destino e a origem. Apesar de intuitivamente lembrar a ideia de mover, na realidade faz uma cópia no destino do valor armazenado na origem. As possibilidades básicas para movimentação de dados são: a) modo constante imediato Ex: Copiar um valor constante de 16 bits para um registrador de 16 bits MOV DX,8955 ; armazena o valor 8955H no registrador DX Ex: Copiar um valor constante de 8 bits para um registrador de 8 bits MOV AL,54 ; armazena o valor 54H no registrador AL

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 13

b) modo imediato Ex: Copiar o valor contido em um endereço de memória para o registrador MOV AL,[0350] ; copia o valor armazenado no endereço de memória de dados ; DS:0350H para o registrador AL c) modo registrador Ex: Copiar o valor contido em um registrador para um endereço de memória MOV [0220],DH ; copia o valor armazenado no registrador DH para o endereço de ; memória de dados DS:0220H Ex: Copiar o valor contido em um registrador para outro registrador MOV DX,AX ; copia o valor armazenado no registrador AX no registrador DX d) modo indireto Este modo permite o acesso indireto da memória de dados utilizando o registrador BX como apontador. Ex: Copiar o valor contido no endereço apontado por DS:BX no registrador, admitindo que o conteúdo do registrador DS seja igual a 075FH. Na forma indireta seria: MOV BX,0010 ; armazena o valor 0010H no registrador BX MOV DX,[BX] ; copia o valor contido no endereço apontado por DS:BX ;(neste caso, DS:0010H) no registrador DX Na forma imediata seria: MOV DX,[0010] ; copia o valor armazenado no endereço de memória de dados ; DS:0010H para o registrador DX No anexo II da apostila é mostrado o set de instruções completo do microprocessador x86. Exercícios 1) Carregue o valor BC21H no registrador AX utilizando: a) instruções MOV de 8 bits b) instruções MOV de 16 bits 2) Carregue o valor 71H na posição de memória de dados 075F:0010H utilizando: a) instruções Assembly b) comando do Debug 3) Carregue o valor 8CH na posição de memória de dados 075F:0020H de forma indireta (utilizando registrador BX como apontador). 4) Armazenar a palavra “IFSP” a partir do endereço de memória de dados 075F:0010H utilizando instruções Assembly. 5) Estude a instrução XCHG. Quantas instruções MOV são necessárias para realizar a mesma função da instrução XCHG?

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 14

Experiência 4: Flags e instruções aritméticas do microprocessador x86

Objetivo Apresentar as instruções aritméticas do microprocessador x86. Conteúdo Conforme foi mostrado na Figura 3 o microprocessador possui internamente uma CPU que contém a ULA, responsável por processar as operações aritméticas quando estas forem solicitadas no programa Assembly. Basicamente, a ULA do x86 é capaz de processar as seguintes operações aritméticas: a) Adição (instruções ADD operando1,operando 2) Efetua a soma aritmética de dois operandos. O resultado é armazenado no operando à esquerda. O operando à direita permanece inalterado. Ex: Somar o conteúdo do registrador AX com o conteúdo do registrador BX ADD AX,BX ; realiza AX = AX + BX Vamos analisar com mais detalhes a instrução ADD consultando as informações referentes a ela no Anexo II (lista de instruções Assembly do x86), conforme ilustra a Figura 10.

Figura 10: Descrição da instrução ADD do microprocessador x86

A primeira coluna (Instrução) diz respeito ao código que identifica a instrução (neste caso, ADD). A segunda coluna (Operandos) diz respeito às variações possíveis dos operandos que esta instrução pode receber. Conforme pode ser observado, esta instrução permite a soma registro+memória (ex: ADD AX,[0]), memória+registro (ex: ADD [0],AX), registro+registro (ex: ADD AX,BX) e registro+valor imediato (ex: ADD AX,1234). A terceira coluna (Descrição) diz respeito a algumas informações relevantes a execução da função. Geralmente inicia com uma breve descrição de seu objetivo (Soma aritmética). A seguir é representada em formato de microcódigo a lógica executada pela instrução (operando1 ← operando1 + operando2). Portanto, admitindo que a instrução em questão fosse ADD AX,BX o conteúdo do registro AX (operando1) seria somado ao conteúdo do registro BX (operando2) e o resultado armazenado em AX (operando1). Posteriormente é apresentado um exemplo de programa utilizando a instrução. Por fim, é mostrado em uma pequena tabela as flags que são afetadas por esta instrução. As flags são bits especiais cujo objetivo é sinalizar alguns status específicos da CPU. O processador x86 possui 8 flags, representadas na Figura 11, identificadas por 2 letras (blocos vermelhos). No Debug é possível visualizar seus status através do comando R.

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 15

Figura 11: Flags do microprocessador x86 A seguir segue uma breve descrição das principais flags que serão utilizadas em nossas aulas: Signal flag (SF): indica que a última instrução gerou um resultado positivo (PL) ou negativo (NG) Zero flag (ZF): indica que a última instrução gerou um resultado igual a zero (ZR) ou diferente de zero (NZ) Auxiliary flag (AF): indica que a última instrução gerou um carry bit intermediário (AC) do quarto bit mais significativo, ou que não gerou um carry bit intermediário (NA) Parity flag (PF): indica que a última instrução gerou um resultado com quantidade par de “1s” (PE), ou um resultado com quantidade impar de “1s” (PO) Carry flag (CF): indica que a última instrução gerou um carry bit (CY) no bit mais significativo, ou que não gerou um carry bit (NC). Por exemplo, admitindo que através do comando R obtemos: AX=1280 BX=2F82 CX=0500 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000 DS=077A ES=077A SS=077A CS=077A IP=0100 NV UP EI PL ZR AC PE CY 077A:0100 01D8 ADD AX,BX Executando a instrução ADD AX,BX através do comando T obtemos: AX=4202 BX=2F82 CX=0500 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000 DS=077A ES=077A SS=077A CS=077A IP=0102 NV UP EI NG NZ NA PO NC 077A:0102 0000 ADD [BX+SI],AL A operação realizada foi: 111 1111 ; carry bits 0001 0010 1000 0000 ; 1280H (registro AX) + 0010 1111 1000 0010 ; 2F82H (registro BX) ---------------------- 0100 0010 0000 0010 ; 4202H (registro AX) Devido a isto, após a execução da instrução: - Signal flag (SF): a operação gerou um valor positivo (PL) - Zero flag (ZF): a operação gerou um resultado no registro AX diferente de zero (NZ) - Auxiliary flag (AF): a operação não gerou um carry bit intermediário (NA) - Parity flag (PF): a operação gerou um resultado no registro AX com quantidade de “1s” igual a três, é impar (PO) - Carry flag (CF): a operação não gerou um carry bit no bit mais significativo (NC) Outra variação da instrução ADD é a instrução ADC, que leva em consideração o resultado do carry bit da instrução anterior.

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 16

b) Subtração (instruções SUB operando1,operando2) Efetua a subtração aritmética de dois operandos. O resultado é armazenado no operando à esquerda. O operando à direita permanece inalterado. Ex: Subtrair o conteúdo do registrador AX com o conteúdo do registrador BX SUB AX,BX ; realiza AX = AX - BX Outra variação da instrução SUB é a instrução SBB, que leva em consideração o resultado do borrow bit da instrução anterior. c) Incremento (instrução INC operando) Soma 1 ao operando especificado, sem afetar o Carry Flag (CF). Ex: Incrementar o conteúdo do registrador AX. INC AX ; realiza AX = AX + 1 d) Decremento (instrução DEC operando) Subtrai 1 do operando especificado, sem afetar o Carry Flag (CF). Ex: Decrementar o conteúdo do registrador BX. DEC AX ; realiza AX = AX + 1 e) Multiplicação (instrução MUL operando) Efetua a multiplicação sem sinal de dois operandos. Para multiplicações de 8 bits x 8 bits o primeiro operando deve ser AL e o resultado será armazenado em AX. Para multiplicações de 16 bits x 16 bits o primeiro operando deve ser AX e o resultado será armazenado em DX (parte alta) e em AX (parte baixa). Ex: Multiplicar o conteúdo do registrador AL pelo conteúdo do registrador BH. MUL BH ; realiza AX = AL x BH f) Divisão (instrução DIV operando) Efetua a divisão sem sinal. Para divisões de um número de 32 bits por um número de 16 bits o dividendo será a concatenação de DX:AX, o divisor será o operando, o quociente será armazenado no registro AX e o resto será armazenado no registro DX, ou seja: (dividendo) DX:AX |__operando__ (divisor) (resto) DX AX (quociente) Ex: Dividir o valor 9 por 2. MOV DX, 0 ; carrega o par DX:AX (dividendo) com o valor 0000 0009H MOV AX, 9 MOV BX, 2 ; carrega BX (divisor) com o valor 0002H DIV BX ; realiza DX:AX ÷ BX, com quociente em AX e resto em DX Após a execução do programa os valores dos registros serão: AX=0004 BX=0002 CX=0000 DX=0001 SP=FFFE BP=0000 SI=0000 DI=0000 DS=075F ES=075F SS=075F CS=075F IP=0110 NV UP DI PL NZ NA PO NC

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 17

g) Números negativos (instrução NEG operando) Efetua o complemento de dois no operando especificado. Ou seja, muda o sinal do número ali armazenado. Ex: Inverter o sinal do valor armazenado no registrador AX (supondo 0002H = 0002D) NEG AX ; executa o complemento 2 em AX 0000 0000 0000 0010 -> 0002H = 2D ------------------- 1111 1111 1111 1101 -> FFFDH (complemento 1) 1 + ------------------- 1111 1111 1111 1110 -> FFFEH = -2D (complemento 2) │ └sinal (0=positivo / 1=negativo) Exercícios 1) Fazer um programa que some 32H com 27H, subtraia 10H desse resultado e armazene o resultado final incrementado de 1 na posição DS:0020H da memória de dados. 2) Fazer um programa que some o conteúdo das posições de memória de dados DS:0020H e DS:0021H e guarde o resultado nas posições de memória DS:0022H (parte alta) e DS:0023H (parte baixa). 3) Admitindo que um valor de 16 bits esteja armazenado nas posições de memória de dados DS:0000H (parte alta) e DS:0001H (parte baixa) e que outro valor de 16 bits esteja armazenado em DS:0002H (parte alta) e DS:0003H (parte baixa) fazer um programa, utilizando somente operações de soma de 8 bits + 8 bits e de movimentação, que some estes dois valores e armazene o resultado a partir do endereço de memória de dados DS:0004H. 4) Fazer um programa que realize a subtração entre dois números positivos contidos nos registradores AX e BX ( ou seja AX – BX) sem utilizar as instruções SUB e SBB. 5) Fazer um programa que some dois valores positivos de 32 bits. Desafio Fazer um programa que calcule o delta de uma equação do 2º grau dada por:

(DS:0000H).x2 + (DS:0001H).x + (DS:0002H) = 0 Admita que os valores inseridos nas posições de memória sejam sempre positivos.

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 18

Experiência 5: Instruções lógicas do microprocessador x86

Objetivo Apresentar as instruções lógicas do microprocessador x86. Conteúdo Conforme foi mostrado na Figura 3 o microprocessador possui internamente uma CPU que contém a ULA, responsável por processar as operações lógicas quando estas forem solicitadas no programa Assembly. Basicamente, a ULA do x86 é capaz de processar as seguintes operações lógicas: a) Lógica AND (instrução AND operando1,operando2) Executa a lógica AND, bit a bit, entre dois operandos. O resultado é armazenado no operando à esquerda. O operando à direita permanece inalterado. Ex: Executar a lógica AND entre os registradores AX (contendo F527H) e BX (contendo 5798H). AND AX,BX ; realiza AX = AX and BX Ou seja: AX F527 1111 0101 0010 0111 BX 5798 0101 0111 1001 1000 and ------------------------------- AX 5500 0101 0101 0000 0000 Esta lógica é muito interessante quando desejamos fazer uma mask (máscara) para zerar determinados bits. Ex: Zerar os dois bits menos significativos de AX. AND AX,FFFC ; realiza AX = AX and mask AX xxxx xxxx xxxx xxxx xxxx mask FFFC 1111 1111 1111 1100 and --------------------------------- AX xxxx xxxx xxxx xx00 b) Lógica OR (instrução OR operando1,operando2) Executa a lógica OR, bit a bit, entre dois operandos. O resultado é armazenado no operando à esquerda. O operando à direita permanece inalterado. Ex: Executar a lógica OR entre o registrador AX e o valor 123BH. OR AX,123B ; realiza AX = AX or 123B Esta lógica é muito interessante quando desejamos fazer uma mask para setar determinados bits. Ex: Setar os dois bits mais significativos de AX. OR AX,C000 ; realiza AX = AX or mask AX xxxx xxxx xxxx xxxx xxxx mask C000 1100 0000 0000 0000 or --------------------------------- AX 11xx xxxx xxxx xxxx

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 19

c) Lógica NOT (instrução NOT operando) Efetua a lógica NOT bit a bit no operando. O resultado é armazenado no próprio operando. Ex: Inverter todos os bits do valor armazenado no registrador BX. NOT BX ; realiza BX = not BX d) Lógica XOR (instrução XOR operando1,operando2) Efetua a lógica XOR (eXclusive OR) bit a bit entre dois operandos. O resultado é armazenado no operando à esquerda. O operando à direita permanece inalterado. Ex: Executar a lógica XOR entre os registradores AX e BX. XOR AX,BX ; realiza AX = AX xor BX Esta lógica é muito interessante quando desejamos fazer uma mask para inverter o valor de determinados bits. Nesta mask as posições com valor 1 terão seu valor invertido e as posições com valor 0 terão seu valor mantido. Ex: Inverter os dois bits menos significativos do registrador AX. XOR AX,0003 ; realiza AX = AX xor mask AX uuuu uuuu uuuu uuuu uuuu mask 0003 0000 0000 0000 0011 xor --------------------------------- AX uuuu uuuu uuuu uuūū Além das operações lógicas existem também algumas operações de manipulações de bits. As principais são: a) Operação de rotação à direita (instrução ROR operando1,operando2) Efetua a rotação a direita dos bits do operando1. O total de bits a rotacionar é dado pelo valor do operando2. O resultado é armazenado no operando1. A cada rotação o bit à direita é transferido para o bit à esquerda do resultado. O operando2 poder ser o valor 1 (para uma única rotação) ou o registrador CL. Ex: Rotacionar o conteúdo do registrador AX (supondo 1232H) dois bits para a direita. MOV CL,2 ; carrega a qtde de rotacoes a ser realizada em AX ROR AX,CL ; realiza AX = AX >> 2 AX (antes) 0001 0010 0011 0010 AX (depois) 1000 0100 1000 1100 Existe ainda a instrução RCR que considera o carry bit da operação anterior no processo de rotação. b) Operação de rotação à esquerda (instrução ROL operando1,operando2) Efetua a rotação a esquerda dos bits do operando1. O total de bits a rotacionar é dado pelo valor do operando2. O resultado é armazenado no operando1. A cada rotação o bit à esquerda é transferido para o bit à direita do resultado. O operando2 poder ser o valor 1 (para uma única rotação) ou o registrador CL. Ex: Rotacionar o conteúdo do registrador AX (supondo 1232H) três bits para a esquerda. MOV CL,3 ; carrega a qtde de rotacoes a ser realizada em AX ROL AX,CL ; realiza AX = AX << 3 Existe ainda a instrução RCL que considera o carry bit da operação anterior no processo de rotação.

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 20

Exercícios 1) Fazer um programa em Assembly que leia o valor armazenado na posição de memória DS:0000H, admitindo que seu bit MENOS significativo seja o 1º bit e o bit MAIS significativo seja o 8º bit, ou seja: DS:0000H = X X X X X X X XB ↓ ↓ 8o bit 1o bit

a) armazene em DS:0001H o valor com seu 3º bit setado (obs: setar é colocar valor 1) b) armazene em DS:0002H o valor com seu 2º bit resetado (obs: resetar é colocar valor 0) c) armazene em DS:0003H o valor com seus 1º e 4º bits invertidos d) armazene em DS:0004H o valor rotacionado 3 bits a direita e) armazene em DS:0005H o valor rotacionado 2 bits a esquerda

2) Utilize as instruções SHL ou SHR no lugar das instruções ROL ou ROR para implementar os itens d) e e) do exercício 1. Qual a diferença entre estas instruções?

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 21

Experiência 6: Instruções de desvio do microprocessador x86

Objetivo Apresentar as instruções responsáveis por implementar os desvios condicionais e os desvios incondicionais de execução do programa no microprocessador x86. Conteúdo Um dos recursos mais poderosos de se implementar nos programas é a capacidade de alterar a sua sequência de execução durante a sua própria execução. Chamamos isto de desvio ou salto (branch) do programa. Basicamente podem ser implementadas de três formas: desvio incondicional, desvio condicional e chamada de subrotina. Os dois primeiros serão explorados nesta experiência. O terceiro será abordado na experiência seguinte. 1) Desvio incondicional A sequência de execução é alterada sem analisar qualquer condição a) Instrução JMP endereco Efetua um salto incondicional para o endereço da memória de programa composto pelo par CS:endereço. Ex: efetuar um salto incondicional do programa para o endereço de memória de programa 075F:0150H. MOV CX,075F JMP 0150 2) Desvio condicional As instruções de desvio condicional trabalham analisando diretamente o estado dos flags da última operação realizada pelo processador e desviam a execução do programa para um determinado endereço se o resultado for verdadeiro. Estes desvios condicionais, pela própria natureza de sua aplicação e devido ao projeto do processador, saltam apenas de forma relativa e limitada a 127 posições de endereço de programa para cima ou 127 posições de endereço de programa para baixo. Caso seja necessário um salto maior é possível faze-lo através de um salto que atinja diretamente uma instrução de salto incondicional JMP. Antes de analisarmos as instruções de desvio condicional é interessante analisarmos uma outra instrução muito comum de ser utilizada antes destas: a instrução CMP. Instrução CMP operando1,operando2 Esta instrução executa a subtração operando1 – operando2, descartando o resultado desta subtração e afetando somente os flags correspondentes. Ex: Comparar os conteúdos dos registradores AL e BL MOV AL,5 ; AL = 5 MOV BL,5 ; BL = 5 CMP AL,BL ; AL e BL não alteram seu valor e flag ZF = ZR (resultado zero)

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 22

A seguir são mostradas as principais instruções de desvio condicional do microprocessador x86: a) Instrução JE endereco Salta se o operando1 for igual ao operando2 (de acordo com o resultado da instrução CMP) b) Instrução JNE endereço Salta se o operando1 não for igual ao operando2 (de acordo com o resultado da instrução CMP) c) Instrução JL endereço Salta se o operando1 for menor que o operando2 (de acordo com o resultado da instrução CMP) d) Instrução JNL endereço Salta se o operando1 não for menor que o operando2 (de acordo com o resultado da instrução CMP) e) Instrução JLE endereço Salta se o operando1 for menor ou igual ao operando2 (de acordo com o resultado da instrução CMP) f) Instrução JNLE endereço Salta se o operando1 não for menor e não for igual ao operando2 (de acordo com o resultado da instrução CMP) g) Instrução JB endereço Salta se o operando1 estiver abaixo do operando2 (de acordo com o resultado da instrução CMP). h) Instrução JNB endereço Salta se o operando1 não estiver abaixo do operando2 (de acordo com o resultado da instrução CMP). i) Instrução JBE endereço Salta se o operando1 estiver abaixo ou for igual ao operando2 (de acordo com o resultado da instrução CMP). j) Instrução JNBE endereço Salta se o operando1 não estiver abaixo e não for igual ao operando2 (de acordo com o resultado da instrução CMP). k) Instrução JP endereço Salta se o resultado anterior tiver paridade par. Somente os 8 bits menos significativos do resultado serão analisados (de acordo com o resultado das instruções CMP, SUB, ADD, TEST, AND, OR e XOR). l) Instrução JNP endereço Salta se o resultado anterior não tiver paridade par. Somente os 8 bits menos significativos do resultado serão analisados (de acordo com o resultado das instruções CMP, SUB, ADD, TEST, AND, OR e XOR).

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 23

Ex: Saltar para o endereço da memória de programa CS:0150H se o valor contido no registrador AL não tiver paridade par. ORL AL,0 ; instrução para setar/resetar flags sem alterar valor de AL JNP 150 ; saltar se AL não tiver paridade par m) Instrução JO endereço Salta se a flag de overflow estiver setada (flag OF = OV). n) Instrução JNO endereço Salta se a flag de overflow não estiver setada (flag OF = NV). o) Instrução JS endereço Salta se o resultado for um número negativo (de acordo com o resultado das instruções CMP, SUB, ADD, TEST, AND, OR e XOR). p) Instrução JNS endereço Salta se o resultado for um número positivo (de acordo com o resultado das instruções CMP, SUB, ADD, TEST, AND, OR e XOR). Utilizando as instruções de desvio pode-se implementar diversas estruturas importantes para a elaboração dos mais diversos programas. Serão destacadas abaixo duas dessas estruturas: lógica de comparação e lógica de repetição. - Lógica de comparação Nesta lógica a idéia é comparar um determinado valor com outro valor. Caso o resultado da comparação seja verdadeiro o programa é desviado. Caso seja falso o programa segue a seqüencia normal de execução. Ex: comparar se o valor de AX é igual a 10. Caso seja verdadeiro o valor de AX muda para 20. Caso seja falso o valor de AX muda para 30. CS:0100 CMP AX,000A ; compara se AX e igual a 10 JE 110 MOV AX,001E ; AX diferente de 10 portanto muda para 30 CS:0110 MOV AX,0014 ; AX igua a 10 portanto muda para 20 - Lógica de repetição Nesta lógica a idéia é executar um determinado trecho do programa uma quantidade de vezes. Ex: zerar cinco posições de memória de dados a partir do endereço de memória DS:0010H . CS:0100 MOV BX,0010 ; carregar BX com primeiro end de memória a ser zerado MOV DX,0005 ; carregar DX com qtde de end de memória a serem zerados MOV AL,0 ; carregar AL com zero CS:0108 MOV [BX],AL ; zerar posicao de memoria apontado por BX INC BX ; apontar para proxima posicao de memoria DEC DX ; decrementar contador de repeticao CMP DX,0000 ; testar se terminou qtde de repeticoes JNE 108

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 24

Exercícios 1) Fazer um programa que analise se o número inserido dentro do registro AX é par ou impar. O resultado da análise deve ser mostrado com um caracter ASCII no endereço de memória de dados 075F:0000H. Caso seja par será mostrado o caracter “P”. Caso seja ímpar será mostrado o caracter “I”. 2) Fazer um programa que analise se o número inserido dentro do registro AL tem paridade par ou impar. Caso seja ímpar o valor de BX será 1, caso seja par o valor de BX será 2, e caso seja zero o valor de BX será zero. 3) Fazer um programa que analise a nota de um aluno (inserido dentro do registro AX) e escreva uma mensagem em caracter ASCII a partir do endereço de memória de dados 075F:0000H. Caso a nota seja menor que 4,0 escreva a mensagem “reprovado”, caso a nota seja 4,0 ≤ nota < 6,0 escreva a mensagem “exame” e caso a nota seja igual ou superior a 6,0 escreva a mensagem “aprovado”. 4) Existem ainda outras instruções alternativas para desvio que são equivalentes a algumas das instruções mencionadas. O quadro abaixo ilustra estas instruções.

Instrução original Instrução alternativa JE endereço JZ endereço JNE endereço JNZ endereço JL endereço JNGE endereço JNL endereço JGE endereço JLE endereço JNG endereço JNLE endereço JG endereço JB endereço JNAE endereço JNB endereço JAE endereço JBE endereço JNA endereço JNBE endereço JÁ endereço JP endereço JPE endereço JNP endereço JPO endereço

Analise cada uma das instruções e verifique se os programas anteriormente feitos podem ter suas instruções originais substituídas pelas instruções alternativas.

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 25

Experiência 7: Stack memory e subrotinas no microprocessador x86

Objetivo Apresentar os conceitos de stack memory e chamadas de sub-rotinas no microprocessador x86. Conteúdo A stack memory é um recurso muito comum em sistemas microprocessados que permite ao usuário salvar e reaver dados em uma estrutura chamada pilha de memória. O procedimento é semelhante ao processo de armazenar várias folhas de papel (dados) em uma pilha de papel (stack memory). Armazenamos na pilha de papeis folha de papel sobre folha de papel. Para reaver uma folha de papel temos de iniciar pela última folha armazenada no topo da pilha. No microprocessador x86 utilizamos os registradores SS, SP, endereços de memória de dados e as instruções assembly PUSH e POP. Supondo que após um comando R do Debug temos: AX=AABB BX=0000 CX=0000 DX=0000 SP=00FF BP=0000 SI=0000 DI=0000 DS=075F ES=075F SS=075F CS=075F IP=0100 NV UP EI PL ZR AC PE CY 075F:0100 50 PUSH AX Antes de executar a instrução PUSH AX teremos a seguinte estrutura, ilustrada pela Figura 12. Nesta estrutura, o par SS:SP define um ponteiro que aponta para o endereço de memória referente ao topo da stack memory.

Figura 12: Estrutura da stack memory antes da execução da instrução PUSH AX

Após a execução da instrução PUSH AX teremos a seguinte estrutura, ilustrada pela Figura 13, onde o processador copia os bytes que compõem o valor armazenado no registro AX e os armazena na pilha, no formato little-endian.

Figura 13: Estrutura da stack memory após da execução da instrução PUSH AX

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 26

Para reaver a informação salva na pilha de memória basta executar a instrução POP em conjunto com o registro no qual será armazenada a informação. Neste caso, como salvamos o registro AX, para reaver seu conteúdo basta executar: POP AX Outro recurso também comum de ser encontrado é o uso de subrotinas. Subrotinas são um conjunto de instruções que, normalmente, deseja-se que sejam executadas várias vezes durante um determinado programa. Seu funcionamento é semelhante aos desvios de programa mostrados na experiência anterior, com a diferença que a chamada de uma subrotina oferece recursos adicionais que permitem o retorno do programa no ponto de chamada da subrotina em conjunto com o recurso de stack memory. No microprocessador x86 utilizamos os registradores SS, SP, endereços de memória de dados e as intruções assembly CALL e RET. Supondo que desejamos executar em um determinado programa diversas vezes a soma entre os registros AX e BX. Neste caso, pode-se disponibilizar a soma entre esses registros através de uma subrotina. O código abaixo ilustra um exemplo de implementação desta subrotina em um programa que se inicia no endereço de memória de programa 075F:0100H e cuja subrotina de soma entre os dois registros esteja localizado a partir do endereço 075F:0117H. Vamos admitir que após um comando R do Debug temos: AX=0000 BX=0000 CX=0000 DX=0000 SP=00FD BP=0000 SI=0000 DI=0000 DS=075F ES=075F SS=075F CS=075F IP=0100 NV UP EI PL ZR AC PE CY 075F:0100 50 PUSH AX E após um comando U do Debug a partir da memória de programa CS:0100H, temos: 075F:0100 B80100 MOV AX,0001 075F:0103 BB0200 MOV BX,0002 075F:0106 E80E00 CALL 0117 075F:0109 B80300 MOV AX,0003 075F:010C BB0400 MOV BX,0004 075F:010F E80500 CALL 0117 075F:0112 90 NOP 075F:0113 0000 ADD [BX+SI],AL 075F:0115 0000 ADD [BX+SI],AL 075F:0117 01D8 ADD AX,BX 075F:0119 C3 RET 075F:011A 0000 ADD [BX+SI],AL 075F:011C 0000 ADD [BX+SI],AL Um resumo da ordem de execução deste programa é mostrado a seguir. MOV AX,0001 → O valor 0001H será armazenado no registro AX. MOV BX,0002 → O valor 0002H será armazenado no registro BX. CALL 0117 → É feita a chamada para a subrotina localizada no endereço de memória de programa CS:0117H. Neste momento o endereço de retorno do programa (075F:0109H) é salvo na stack memory e o valor do registro IP é alterado para 0117H, o que desvia o programa para o endereço da memória de programa 075F:0117H. ADD AX,BX → É feita a soma entre os registros AX e BX RET → É feito o retorno do programa para o endereço de memória de programa salvo na stack memory (neste caso 075F:0109H) MOV AX,0003 → O valor 0003H será armazenado no registro AX. MOV BX,0004 → O valor 0004H será armazenado no registro BX. CALL 0117 → É feita a chamada para a subrotina localizada no endereço de memória de programa CS:0117H. Neste momento o endereço de retorno do programa (075F:0112H) é salvo na stack memory e o valor do registro IP é alterado para 0117H, o que desvia o programa para o

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 27

endereço da memória de programa 075F:0117H. ADD AX,BX → É feita a soma entre os registros AX e BX RET → É feito o retorno do programa para o endereço de memória de programa salvo na stack memory (neste caso 075F:0112H) Um último comentário é a respeito da chamada de uma subrotina. Em alguns casos pode ocorrer a situação no qual o programa principal utilize, por exemplo, alguns registros. E estes mesmos registros, por exemplo, são utilizados também pela subrotina. Seria interessante que a execução da subrotina fosse transparente para estes registros, ou seja, após o retorno da subrotina o valor destes registros estivessem com os mesmos valores antes da chamada da subrotina. Para isto, pode-se utilizar as instruções PUSH no início da subrotina (para salvar os registros desejados) e POP no final da subrotina (para reaver os registros desejados). O exemplo a seguir exibe um exemplo da subrotina anterior utilizando as instruções PUSH e POP, de forma a não perder o valor de AX, sempre armazenando o resultado da soma em DX. PUSH AX ADD AX,BX MOV DX,AX POP AX O exemplo a seguir demonstra como poderia ser o código caso também se quisesse salvar o valor de BX durante a chamada da subrotina. Observe a ordem de execução destas instruções, que deve levar em conta o funcionamento do mecanismo de stack memory. PUSH AX PUSH BX ADD AX,BX MOV DX,AX POP BX POP AX Exercícios 1) Faça uma subrotina que realize a subtração de dois valores de 8 bits presentes nos endereços de memória 075F:0200H e 075F:0201H, armazenando o resultado em 075F:0202H, levando em consideração que a subrotina seja transparente. exemplo: 075F:0200H = numero A 075F:0201H = numero B após execução da subrotina: 075F:0202H = resultado A - B 2) Faça uma subrotina que altere a letra em código ASCII armazenada no endereço de memória de dados 075F:0200H de minúscula para maiúscula, levando em consideração que a subrotina seja transparente. exemplo: 075F:0200H = letra c após execução da subrotina: 075F:0200H = letra C 3) Faça uma subrotina que calcule a soma de dois números de 16 bits, levando em consideração que a subrotina seja transparente. exemplo: 075F:0200H e 075F:0201H → número A (little endian) 075F:0202H e 075F:0203H → número B (little endian) após a execução da subrotina: 075F:0204H , 075F:0205H e 075F:0206H → resultado A+B (little endian)

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 28

Experiência 8: Instruções adicionais do microprocessador x86

Objetivo Apresentar algumas instruções adicionais do microprocessador x86 e o recurso de tabelas. Conteúdo Primeiramente, vamos explorar algumas instruções adicionais do microprocessador x86. São elas a instrução LOOP e a instrução NOP. A seguir vamos aprender um importante recurso utilizado para simplificar alguns programas: o uso de tabelas. a) Instrução LOOP Seu objetivo é implementar de uma forma mais enxuta a estrutura de laço de repetição mostrada na Experiência 6. Sua lógica é: Decremente o registrador CX e salte para o endereço especificado se o conteúdo de CX, após o decremento, não for zero. Ex: incrementar AX quatro vezes e salvar o resultado em BX. CX:0100 MOV CX, 4 ; INICIALIZA CX COM QTDE DE LACOS CS:0103 INC AX ; INCREMENTA AX LOOP 0103 ; DECREMENTA CX E SALTE SE NÃO FOR ZERO MOV BX, AX ; SALVA O RESULTADO EM BX b) Instrução NOP Esta instrução ao ser executada não realiza nenhuma operação. Embora ela não execute nada, esta instrução leva um tempo para ser processada pelo microprocessador, o que a torna interessante quando necessitamos adicionar algum atraso em nosso programa. Ex: utizando a instrução NOP adicione um delay para o laço do programa anterior. CX:0100 MOV CX, 4 ; INICIALIZA CX COM QTDE DE LACOS CS:0103 INC AX ; INCREMENTA AX NOP NOP NOP LOOP 0103 ; DECREMENTA CX E SALTE SE NÃO FOR ZERO MOV BX, AX ; SALVA O RESULTADO EM BX

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 29

c) Recurso de tabelas Uma tabela nada mais é do que informação (bytes) armazenada na memória. Esta informação pode ser utilizada de inúmeras formas para a simplificação de programas, como por exemplo, na codificação/decodificação de valores, simplificar a implementação de fórmulas, linearização de curvas, etc. Ex: implemente um algoritmo que criptografe números de 0 a 9 alterando seu valor da seguinte forma:

Número original Novo valor criptografado 0 1 1 3 2 5 3 7 4 9 5 2 6 4 7 6 8 8 9 0

Para implementar o programa vamos admitir que: - o valor a ser criptografado se encontra em AX - o número criptografado será armazenado em CX - a tabela de criptografia foi escrita a partir do endereço DS:0000H da seguinte forma: 075F:0000 01 03 05 07 09 02 04 06-08 00 00 00 00 00 00 00 ................ 075F:0010 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 075F:0020 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 075F:0030 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ Uma possível solução seria: CS:0100 MOV BX,075F ;inicializa DS

MOV DS,BX MOV BX,AX ;carrega BX com o numero a ser criptografado

MOV CX,[BX] ;a movimentação indireta busca na tabela o valor ; criptografado e armazena em CX MOV CH,0 ;limpar parte alta (sujeira)

Exercícios 1) Faça um programa que descriptografe a criptografia implementada no exemplo. 2) Admita que um determinado sensor de temperatura produza uma determinada tensão de acordo com a temperatura medida. O seu sistema microprocessado é capaz de medir a tensão gerada por este sensor, e o valor medido se encontra armazenado na posição de memória DS:0000H. Este sensor, infelizmente, possui uma resposta não linear, ou seja, não produz uma tensão diretamente proporcional a temperatura medida. A tabela a seguir ilustra a resposta do sensor.

Tensão gerada (V) Temperatura (oC) 0 20 2 21 4 22 7 23 10 24 14 25

a) Faça um programa, sem utilizar o recurso de tabela, que linearize a resposta do sensor. b) Faça um programa, utilizando o recurso de tabela, que linearize a resposta do sensor.

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 30

Experiência 9: Prática de programação

Objetivo Desenvolver e aprimorar a prática de programação de sistemas microprocessados. Conteúdo Nesta aula iremos praticar através de exercícios a prática de programação. Exercícios 1) Fazer um programa em assembly que exiba em caracteres ASCII entre os endereços da memória de dados 075F:0110H e 075F:0112H o valor armazenado na posição de memória de dados 075F:0100H convertido em decimal. Exemplo: 075F:0100 80 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 075F:0110 31 32 38 00 00 00 00 00-00 00 00 00 00 00 00 00 128............. 075F:0120 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 075F:0130 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 075F:0140 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 075F:0150 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 075F:0160 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 075F:0170 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2) Fazer um programa em assembly que simule uma calculadora de 8 bits. Ela funcionará da seguinte forma: - antes de executar o programa no registro AX será armazenada um valor que corresponde a operação desejada: 0: soma 1: subtração 2: multiplicação 3: divisão - nos endereços de memória de dados 075F:0100H e 075F:0101H estarão armazenados os dois números que sofrerão a operação selecionada - no endereço de memoria de dados 075F:0110H e 05F:0111H serão armazenados o resultado da operação selecionada. Exemplo: supondo que no registro AX esteja armazenado o valor 0 (soma): 075F:0100 F0 46 00 00 00 00 00 00-00 00 00 00 00 00 00 00 .F.............. 075F:0110 01 36 00 00 00 00 00 00-00 00 00 00 00 00 00 00 .6.............. 075F:0120 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 075F:0130 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 075F:0140 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 075F:0150 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 075F:0160 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 075F:0170 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 31

3) Fazer um programa em assembly que realize a criptografia de uma mensagem de 16 caracteres ASCII armazenada entre os endereços da memória de dados 075F:0100H e 075F:010FH, exibindo o resultado desta criptografia entre os endereços da memória de dados 075F:0110H e 075F:011FH. A criptografia a ser aplicada corresponde a somar o valor 2 para cada valor de caracter ASCII. Exemplo: 075F:0100 54 45 53 54 41 52 20 41-4C 47 4F 52 49 54 4D 4F TESTAR ALGORITMO 075F:0110 56 47 55 56 43 54 22 43-4E 49 51 54 4B 56 4F 51 VGUVCT”CNIQTKVOQ 075F:0120 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 075F:0130 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 075F:0140 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 075F:0150 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 075F:0160 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 075F:0170 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ Observação: repare que a operação de criptografia será repetida 16 vezes, portanto, implemente esta operação de criptografia dentro de uma subrotina que seja transparente. 4) Fazer um programa em assembly que descriptografe a mensagem criptografada no exercício anterior, exibindo o resultado da mensagem descriptografada entre os endereços da memória de dados 075F:0120H e 075F:012FH 5) Fazer um programa que analise as notas de um aluno. Ele é avaliado através de 4 provas, valendo de zero a dez. As notas devem ser inseridas da seguinte forma: 075F:0100H = nota da prova P1 075F:0101H = nota da prova P2 075F:0102H = nota da prova P3 075F:0103H = nota da prova P4 O programa deve calcular a média das 4 notas e exibir o resultado na posição de memória 075F:0110H. O programa também deve escrever uma mensagem em caracteres ASCII a partir do endereço de memória de dados 075F:0120H. Caso a nota seja menor que 4,0 escreva a mensagem “reprovado”, caso a nota seja 4,0 ≤ nota < 6,0 escreva a mensagem “exame” e caso a nota seja igual ou superior a 6,0 escreva a mensagem “aprovado”.

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 32

Anexo I. Código ASCII

TABELA DE CODIGOS ASCII

Hex Sinal Hex Sinal Hex Sinal

20 (espaço) 40 @ 60 `

21 ! 41 A 61 a

22 " 42 B 62 b

23 # 43 C 63 c

24 $ 44 D 64 d

25 % 45 E 65 e

26 & 46 F 66 f

27 ' 47 G 67 g

28 ( 48 H 68 h

29 ) 49 I 69 i

2A * 4A J 6A j

2B + 4B K 6B k

2C , 4C L 6C l

2D - 4D M 6D m

2E . 4E N 6E n

2F / 4F O 6F o

30 0 50 P 70 p

31 1 51 Q 71 q

32 2 52 R 72 r

33 3 53 S 73 s

34 4 54 T 74 t

35 5 55 U 75 u

36 6 56 V 76 v

37 7 57 W 77 w

38 8 58 X 78 x

39 9 59 Y 79 y

3A : 5A Z 7A z

3B ; 5B [ 7B {

3C < 5C \ 7C |

3D = 5D ] 7D }

3E > 5E ^ 7E ~

3F ? 5F _

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 33

Anexo II: Set de instruções do processador x86

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 34

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 35

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 36

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 37

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 38

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 39

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 40

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 41

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 42

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 43

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 44

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 45

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 46

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 47

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 48

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 49

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 50

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 51

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 52

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 53

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 54

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 55

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 56

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 57

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 58

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 59

Apostila de Laboratório de Microcoprocessadores Prof. Igarashi página 60

Bibliografia Prof. Gilberto Igarashi – Laboratório de Microcontroladores (Apostila) – IFSP Campus SPO – 2010 Prof. Alexandre Aragão – Laboratório de Microprocessadores (Apostila) – IFSP Campus SPO – 2012 Edsim51 – Simulador de 8051 – Prof James Rogers - Institute of Technology Sligo (www.edsim51.com) Prof. Kip Irvine – Using Debug (apostila) – Florida International University (http:;kipirvine.com/asm/debug/debug_tutorial.pdf)