Microprocessadores

Propaganda
Microprocessadores
Ementa: Arquitetura de microprocessadores. Instruções de transferencia de dados,
operações lógicas e aritméticas, desvios e subrotinas. Interrupções . Linguagem Assembly.
Introdução ao projeto de microcomputadores. Aspectos de sistemas de desenvolvimento para
microprocessadores.
COMENTÁRIOS
1 - Introdução
1.1 - Assembler, Assembly e linguagem de máquina
1.2 - Arquitetura de um microcomputador padrão
1.2.1 - Placa principal
1.2.1.1 - Unidade Central de Processamento (UPC)
1.2.1.2 - Memória Principal
1.2.2 - Barramento (endereço, dados e controle)
1.2.2.1 - Via de Endereço
1.2.2.2 - Via de Controle
1.2.2.3 - Via de Dados
1.2.3 - Placa de Vídeo
1.2.4 - Placa de Entrada / Saída
1.2.5 - Placa Controladora de Disco
1.2.6 Exemplo da Arquitetura de um computador
1.2.7 Fluxograma do seguenciamento de instruções
1.3 - Sistema de Entrada e Saída básico("Bios")
1.4 - Sistema Operacional ("DOS")
1.4.1 - Sistema Central
1.4.2 - Programas Auxiliares
1.4.3 - Gerenciador de Comandos
2 - Os Microprocessadores
2.1 - Definição de "Bit, Byte, Word, Dword"
2.2 - Arquitetura Interna de um Computador padrão
2.2.1 - Registros de Dados
2.2.2 - Registros de Segmentos
2.2.3 - Registros de Apontadores
2.2.4 - Associação entre registradores, apontadores e segmentos
2.2.5 - Registro de Estado
2.3 - Modo de Endereçamento
2.4.1 - Endereçamento Imediato
2.4.2 - Endereçamento Direto
2.4.3 - Endereçamento por Registros
2.4.4
2.4.5
2.4.6
- Endereçamento Indireto
- Endereçamento Base
- Endereçamento Índice
2.4.7
2.4.8
- Endereçamento de E/S
- Resumo dos tipos de endereçamento
3 - Programação
3.1 - Utilitários Debug
3.1.1 - Como entrar no Debug
3.1.2 - Comando do Debug
3.2 - Exemplos de programa, escritos em linguagem assembly, utilizando o utilitário
debug
3.2.1 - Instrução MOV
3.2.2 - Instrução ADD
3.2.3 - Instrução SUB
3.2.4 - Programa exemplo: Somar dois valores
3.2.5 - Instrução CMP
3.2.6 - Instrução de Salto Condicional
3.3 - Instruções para manipular dados.
3.3.1 - Instrução MOVSB e MOVSW
3.3.2 - Instrução REP
3.3.3 - Instrução LODSW e STOSB - STOSW
3.3.4 - Instrução CMPSB - CMPSW
3.4 - Instruções para manipular bits
3.4.1 - Instrução RCL
3.4.2 - Instrução RCR
3.4.3 - Instrução ROL
3.4.4 - Instrução ROR
3.4.5 - Instrução SAL e SHL
3.4.6 - Instrução SHR
3.4.7 - Instrução SAR
3.4.8 - Aplicando as instruções que manipulam bits
3.4.8.1 - RCL e SAL
3.4.8.2 - RCR e SHR
3.5 - Instruções aritméticas
3.5.1 - Instrução DD e ADC
3.5.2 - Instrução SUB e SBB
3.5.3 - Instrução MUL
3.5.4 - Instrução DIV
3.5.5 - Instrução DEC
3.5.6 - Instrução INC
3.6 - Instruções lógicas
3.6.1 - Instrução AND
3.6.2 - Instrução OR
3.6.3 - Instrução XOR
3.7 - Instruções de desvio e transferência de controle
3.7.1 - Instrução JUMP Relativo
3.7.2 - Instrução JUMP
3.7.3 - Instrução CALL
2
3.8 - Instruções de controle de "loops"
3.8.1 - Instrução LOOP
3.8.2 - Instrução LOOPZ e LOOPNZ
3.9 – Acesso a memória de pilha
3.9.1 – Instruções PUSH e POP
3.10 - Instruções de entrada e saída
3.11 - Interrupções
3
COMENTÁRIOS
O microprocessador é um circuito eletrônico programável que realiza desde os trabalhos mais
simples até os mais complexos, exercendo controle de equipamentos industriais como
furadeiras, tornos, semáforos de trânsito, na medicina, na indústria de material bélico, etc.
Apesar de ser um sistema complexo, sua aplicação é bastante simples e ilimitada.
A linguagem Assembly de um microprocessador serve primordialmente para os seguintes
propósitos:
- evitar o uso direto das instruções e endereços de máquina dos microprocessadores em sua
forma binária ou hexadecimal, tarefa que é bastante árdua para o ser humano;
- entender e testar os programas e rotinas de interfaceamento para uso de dispositivos
terminais e uso de memória e registradores;
- preparar novas rotinas para projetos eletrônicos de controle de processos e aplicações
usando microprocessadores.
Entretanto, o uso da linguagem de baixo nível como a linguagem Assembly torna-se tarefa
cada vez mais trabalhosa, tratando-se de microprocessadores poderosos, em decorrência da
amplitude e complexidade dos seus componentes de hardware envolvidos.
É desaconselhável preparar e testar programas extensos em linguagem Assembly ao se tratar
de microprocessadores de 16, 32 ou mais bits, tendo em vista as dificuldades e diversidade das
opções de uso das instruções.
A linguagem Assembly para microprocessadores com 16 bits (8086/8088/80286), 32 bits
(80386, 80486) ou mais bits é, entretanto, um meio indispensável para analisar, entender e
preparar software para projetos de interface de equipamentos e aplicações com esses
microprocessadores. Pois, apesar da maioria dos equipamentos de computação serem
provenientes do exterior, quando há a necessidade de inteligar um específico dispositivo a um
computador é necessario implementar a interface entre eles, pois este dado não é fornecido
pelo fabricante.
Não se trata de preparar programas extensos, mas de preparar programas curtos ou entender e
adaptar os programas existentes que acompanham os manuais de aplicações utilizando
microprocessadores. Os microprocessadores são amplamente utilizados e seus software’s são
padronizados e compatíveis entre si.
4
CAPÍTULO I
1 - Introdução
1.1 - Assembler, Assembly e Linguagem de Máquina
Linguagem de máquina é o conjunto de instruções primitivas (instruções de
máquina), formada de códigos binários (dígitos 0 e 1)). Este é o único tipo de informação
que o computador digital binário pode manipular. Os dígitos 0 e 1 são armazenados
internamente no computador em forma de energia elétrica, por exemplo:
Digito 0 - não há energia - FALSO
Digito 1 - há energia
- VERDADEIRO
A principal desvantagem da linguagem de máquina é a sua utilização, pois, ela é
difícil e cansativa. Para facilitar o uso mais conveniente do usuário foi criada a linguagem
assembly, que expressa uma instrução de máquina por um mneumônico, por exemplo:
Instrução de máquina
Correspondente
0110 0111
Instrução Assembly
MOV AX, BX
Assembler é um montador que transforma cada instrução assembly em uma instrução de
máquina. A correspondência entre elas é uma para uma, isto é, uma instrução assembly
corresponde a uma instrução de máquina.
1.2 - Arquitetura de um Microcomputador Padrão
1.2.1 - Placa Principal
No minímo deve ser constituída pela Unidade de Processamento Central (UPC) e
pela Memória Principal (MP)
1.2.1.1 - Unidade Central de Processamento (UPC)
A UPC, que num microcomputador (C) é um microprocessador (P), tem
por função controlar todos os outros componentes do C, fazendo com que os
dados fluam de modo a obedecer as instruções (ordens) captadas do programa
pela UPC. Ela manipula os dados, endereçando posições de memória e
realizando cálculos.
5
A UPC é constituída de (Figura 1 . 1):

Unidade de Controle (UC): Gerencia o fluxo de dados; é a unidade ïnteligente
da UPC;
Unidade Lógica e Aritmética (ULA) : Utilizada para cálculos lógicos e
aritméticos;
Registros : Utilizados para a manipulação de dados armazenados na memória.


1.2.1.2 - Memória Principal (MP)
Utilizada para armazenamento de dados binários. É bem mais rápida do que
as memórias secundarias (Discos), pois não utilizam dispositivos mecânicos.
Existem dois tipos : ROM e RAM.

ROM (Read Only Memory) - É uma memória apenas de leitura, e, ao contrário
da RAM ela não é apagada quando o C é desligado.
Ela armazena os seguintes programas:
-
INICIALIZAÇÃO DO C – Este programa é executado assim que o C é
ligado, ele envia mensagens para o vídeo, testa a memória RAM e aciona o
driver ou Winchester para armazenar o Sistema Operacional (SO) na
memória RAM.
- BIOS (Basic Input Output System) - responsável pelo gerenciamento
das funções básicas do computador, que tem como principais tarefas: ler
teclado, cuidar do vídeo, porta paralela, porta serial e etc. A BIOS fornece
rotinas para o gerenciamento das funções de E/S de um C.

RAM (Random Acess Memory) - Utilizada para auxiliar o processamento de
dados. Ela é apagada quando o C é desligado. É uma memória de leitura e
escrita
1.2.2 - Barramento
O barramento é constituído dos condutores que interligam a Unidade Central de
Processamento (UCP) aos demais componentes do computador. Ele possui 3 vias:
1.2.2.1 - Via de Endereço
Indica para qual endereço a UPC deve transmitir ou receber os dados da
memória principal ou de um dispositivo de Entrada / Saída. Ela é unidirecional.
6
1.2.2.2 -Via de Controle
Constituída por sinais ( I/OR, I/OW, MR, MW, INT, INTA , etc.) que
controlam principalmente o sentido do fluxo de dados. Onde:
I/OR – Leitura de Entrada/Saída;
I/OW – Escrita de Entrada/Saída;
MR – Leitura da Memória Principal;
MW – Escrita na Memória Principal;
INT – Pedido de interrupção de algum periférico;
INTA – Reconhecimento do pedido de interrupção pela CPU, isto é, a CPU
vai atender o pedido de interrupção .
Esta via é bidirecional.
1.2.2.3 - Via de Dados
Utilizada para a comunicação de dados entre a UPC e os demais
componentes do C. Ela é bidirecional.
1.2.3 - Placa de Vídeo
Responsável pelo controle do vídeo. Nos atuais PC's ela é ligada
diretamente ao barramento do C, como visto na Fig. 1.2
Possui uma RAM, onde todos os dados que forem armazenados nela serão
mostrados no monitor de vídeo. Esta memória RAM é denominada RAM de
vídeo. Dependendo da Seleção das opções da placa, pode-se escolher entre
modo texto, modo gráfico, resolução de gráficos, cores, etc.
7
1.2.4 - Placa de E/S
As placas de E/S são utilizadas para a comunicação de dados entre os
dispositivos periféricos e a placa central. Existem dois tipos de portas nas placas
de E/S: as paralelas e as seriais. A serial converte dados paralelos para seriais (
Fig. 1.3).
-
Comparação entre as interfaces seriais e paralelas:
serial: transfere um byte ou palavra um bit de cada vez;
paralela: transfere um byte ou palavra de uma só vez;
serial: a conexão requer poucos fios;
paralela: a conexão requer no mínimo um fio para cada bit
na serial a transferência dos dados é mais lenta do que a transmissão paralela.
Para a transmissão de dados serialmente é possível dois modos diferentes: o modo
síncrono e o modo assíncrono.
8
No modo assíncrono para cada caractér transmitido é adicionado um bit que indica o
início do caractér (start bit), um ou dois bits que indicam o fim do caractér (stop bit) e,
opcionalmente, um bit para a verificação da transmissão (parity bit). Este bit de paridade é
utilizado para verificar se houve algum erro na trasmissão.
No modo síncrono inicialmente é feita a transmissão de caractéres especiais para a
sincronização do emissor com o receptor, este caractéres são denominados de caractéres de
sincronização. Após isto, são enviados os dados um em seguida do outro sem sinais
especiais para a separação de um caractér do outro.
1.2.5 - Placa Controladora de Discos
Esta placa controla os discos, drivers e Winchester. É responsável pelos
movimentos da cabeça de leitura/gravação, codificação/ decodificação
(modulação, demodulação) dos dados magnéticos gravados nos discos (Fig.
1.4).
1.2.6 - Exemplo de um Microcomputador
A Fig. 1.5 esboça a arquitetura de um microcomputador padrão.
9
1.2.7 - Fluxograma de sequenciamento de instruções
10
Fig. 1.6 - Sequenciamento de Instruções
11
1.3 - Basic Input Output System (BIOS)
Conjunto de rotinas básicas que tratam da E/S de dados. Normalmente estas rotinas
são implementadas pelo fabricante. Para sua implementação o fabricante deve seguir
determinadas regras, para tornar compatível seus equipamentos com os de outros
fabricantes. Assim uma BIOS que tenha sido desenvolvida por um determinado
fabricante, poderá ser utilizada no computador de outro fabricante.
1.4 - Disk Operational System (DOS)
É um programa que intermedia o operador, o programa sendo executado e a BIOS. É
dividido em três partes:
1.4.1 - Sistema Central (S.C)



Contém as principais rotinas do sistema operacional (SO)
Função principal: gerenciar e organizar as informações, em geral, "contidas" em
discos, vídeo, impressora, etc.
O SC é armazenado na RAM da memória principal na inicialização, através do
programa monitor, residente na ROM.
1.4.2 - Programas Auxiliares



Complementa o S.C.
Separado do S.C., pois caso estivessem juntos não haveria espaço suficiente na
RAM.
Quando necessário o programa auxiliar é carregado na RAM, executado e após
isto, a RAM é novamente liberada.
1.5 - Gerenciador de Comandos (G.C.)
É o programa que liga o usuário ao sistema operacional.
Usuário envia comando (digita no teclado)  G.C. recebe o comando G.C.
interpreta o comando  G.C. passa as ordens para o sistema central (S.C.)
12
CAPITULO II
2 - O MICROPROCESSADOR C
O P é o componente do C que controla todos os outros componentes. Ele realiza o
fluxo de dados entre os outros componentes obedecendo as ordens transmitidas pelo
programa em execução, residente na Memória Principal.
2.1 - Bit, Byte, Word e Códigos
bit - Unidade elementar de informação de um C
byte - Conjunto de 8 bits
Ordem crescente
B7
B6
B5
B4
B3
B2
bit mais significativo
B1
B0
bit menos significativo
onde:
B0 = 20 = 1;
B1 = 21 = 2;
B2 = 22 = 4;
.
.
.
B7 = 27 = 128.
word - especifica 16 bits ou 2 bytes
dword - especifica 32 bits ou 4 bytes ou 2 words
Binário
0000
0001
0010
0011
0100
0101
0110
0111
1000
Octal
00
01
02
03
04
05
06
07
10
Códigos
Decimal
00
01
02
03
04
05
06
07
08
Hexadecimal
0
1
2
3
4
5
6
7
8
13
1001
1010
1011
1100
1101
1110
1111
11
12
13
14
15
16
17
09
10
11
12
13
14
15
9
A
B
C
D
E
F
2.2 –Arquitetura Interna do Microprocesador 8086
Em linguagem de máquina toda a programação é baseada em registradores. Eles são
utilizados na manipulação dos dados que estão armazenados na memória principal ou nos
dispositivos de E/S. Estes registros são internos a UPC.
Em um P existem diversos tipos de registradores, fisicamente são iguais, mas
possuem funções diferentes. Os registros internos são fisicamente similares a memória
(MP), mas tem acesso mais rápido, pois a CPU não necessita ir buscar a informação na
Memória Principal (MP), a informação já está contida na CPU.
O P 8086 é dividido em 4 grupos de registros (Fig. 2.1) de acordo com suas
funções:
a ) Dados : é essencialmente o conjunto de registros aritméticos utilizados para
processar informações;
b ) Apontadores: são utilizados para endereçar a memória (MP); incluem registro de
base e índice , utilizados para endereçar dados, o contador de programa ou
apontador de instruções, utilizado para endereçar a próxima instrução e o apontador
de pilha, utilizado para endereçar a memória de pilha ;
c ) Segmentos : é um conjunto de registros de base de propósitos especiais,
utilizados para endereçar a memória (MP); eles indicam o início de um dos três
segmentos de memória (segmento de instruções ou segmento de dados ou segmento
de pilha);
d ) Estado : indica o estado do processo, isto é, como as variáveis de estado mudam
com a execução do programa.
A figura 2.1 mostra a configuração interna do microprocessador 8086.
14
Fig. 2.1 - Configuração interna do P 8086
2.2.1 - Registros de Dados
O microprocessador 8086 possui quatro registros de dados (AX, BX, CX e DX), cada
um deles com 16 bits (palavra). Todos eles são de uso geral, porém, existem algumas
diferenças entre eles. Entre as caracteristicas comuns, pode-se citar:
 são utilizados para armazenar operandos e resultados da ULA;
 a palavra (word) pode ser particionada em dois bytes: o byte mais significativo
(H) e o byte menos significativo (L);
 todas as instruções em assembly que referenciam a palavra, por exemplo, AX,
também podem referenciar tanto o byte mais significativo, AH, bem como o byte
menos significativo, AL; portanto, pode ser acessada a palavra (word) ou o byte
mais significativo ou o byte menos significativo.
Ordem crescente
AX
15
8
AH
Bit mais significativo
7
0
AL
Bit menos significativo
15
As diferenças entre estes registros são :
AX - é o único registro utilizado para transferir ou receber dados de portas de E/S:
instrução IN AX, endereço da porta de E/S;
BX - utilizado como registro de base;
CX - utilizado como contador para determinadas instruções:
instruções REP ou LOOP;
DX - é o único registro que endereça portas de E/S:
instrução IN AX, DX ____ nesta instrução o conteúdo de DX possui o
endereço da porta de E/S
2.2.2 - Registros de Segmentos:




Utilizados como endereço de base de uma posição de memória;
Indicam, na memória principal o início de um dos três tipos de segmentos ou
áreas;
Cada um deles possui 16 bits;
São denominados de segmento porque dividem a memória em segmentos de 64
kbytes ( 216 ).
CS (Code Segment) – segmento (área ou memória) de código : utilizado pelo P
para determinar o endereço da próxima instrução; indica o endereço inicial da
memória de instruções;
DS (Data Segment) - segmento de dados : utilizado para acessar dados da
memória; indica o endereço inicial da memória de dados;
ES (Extra Segment) - segmento extra de dados : utilizado para acessar dados que
estão em outro segmento que não seja DS; normalmente este registro é utilizado
quando o número de dados na área de dados excede 64 Kbytes; indica o
endereço inicial da memória extra de dados;
SS (Stack Segment) - segmento de pilha : utilizado para salvar registros e para
guardar endereços de retorno de chamada de subrotinas e interrupções; indica o
endereço inicial da memória pilha.
2.2.3 - Registros Apontadores


Utilizados para endereçar a memória a partir da base definida pelos segmentos;
Indicam (apontam) dentro de seu segmento qual o endereço da informação a ser
acessada;
 Cada um deles possui 16 bits;
SP (Stack Pointer) - Apontador de pilha (Stack Point) - endereço de retorno de
chamada de subrotina (CALL) ou de subrotina de atendimento de interrupção ou
de registros “salvos” na memória de pilha;
16
BP (Base Pointer) - Apontador de base;
IP (Instruction Pointer) - Apontador de instruções (programa) - indica na
memória de instruções qual a próxima instrução;
SI (Source Index) - índice fonte - indica o endereço do dado a ser lido da
memória dados;
DI (Destination Index) - índice destino - indica o endereço do dado a ser
escrito na memória dados.
2.2.4 - Associação entre Registradores apontadores / segmentos
Quando o microprocessador 8086 vai acessar uma dos três segmentos, ele
calcula o endereço de onde está contida ou deve ser armazenada a informação na memória
principal, da seguinte maneira (o resultado está em hexadecimal):
SP + 10 * SS
SI + 10 * DS
DI + 10 * ES
IP + 10 * CS
= endereço da posição da pilha;
= endereço do dado a ser lido da MP;
= endereço do dado a ser escrito na MP;
= endereço da próxima instrução.
Exemplo: Calcular endereço físico da próxima instrução a ser lida da MP. Sendo
CS = 123AH
IP = 341BH
341BH
- endereço apontador
123AOB
- endereço segmento (início)
157BBH
- endereço físico da instrução
Endereço
Físico 00000
Memória
.
.
.
123A0
Endereço
Apontador
341B
.
.
.
157BB
Endereço
Próxima
Instrução
.
.
.
CS
Início da
memória de
Instrução
Range de Segmento
= 64 Kbytes
Pois IP=16 bits
2239F
Fig. 2.2
17
2.2.5 - Registro de Estado
(PSW - Program Status Word)
Principais características
 9 bits de estado = 9 bits de flags
 Flags divididos em : condicionais e controle
 Formatação (Fig. 2.3)
15
14
13
12
11
10
9
8
7
6
OF
DF
IF
TF
SF
ZF
5
4
3
AF
2
PF
1
0
CF
8080 FLAGS
Fig. 2.3 PSW do 8086

Flags condicionais
CF - Carry - setado quando ocorre um vai um ("carry-out") no bit mais
significativo do byte ou da palavra;
PF - Paridade - Setado quando a paridade é par; resetado quando a paridade é
impar;
AF - Auxiliar Carry - Setado quando ocorre um "Carry-Out" no bit 3 do byte ou
no bit 7 da palavra (Word);
ZF - Zero - Setado quando o resultado da operação é zero;
SF - Sinal - Setado quando o resultado da operação é negativo;

Flag de Controle
DF - Utilizado para movimentação de "strings" (Conjunto de dados)
DF = 0
Movimento na forma
crescente de endereços
DADO 1
DADO2
.
Strings
.
.
DADO N
DF = 1
Movimento na forma
decrescente de endereços
18
IF - Interrupt Enable: quando setado a UPC alerta pedido de interrupção
externa, caso contrario não;
TF - TRAP: quando setado após a instrução, é gerada automáticamente uma
interrupção interna.
Utilizado normalmente na chamada de uma sub- rotina.
Armazena endereço da próxima instrução para que o microprocessador retorne
ao programa principal que estava executando.
ENDEREÇO
FFFFH
FFFDH
FFFBH
1 ordem de
2 entrada
3 dos dados
FFFBH
FFFDH
FFFFH
1 ordem de
2 saída
3 dos dados
Último a entrar é o primeiro a sair (memória 4F0)
Fig. 2.4 Endereçamento da pilha (Stack)
Endereço
n-2
n-1
N
n +1
Ender. de
retorno 0
Programa
na MP
.
CALL 0
10H
20H
Endereço
2010h
p-2
p-1
p+1
Ender. de
retorno 1
Subrotina
0 na MP
Inicio SC0
Endereço
CALL 1
31H
41H
41314
Subrotina
1 na MP
Inicio SB1
Retorno 1
Retorno 0
Fig. 2.4 Chamadas de sub-rotinas
19
2.3 - Modo de Endereçamento
Modo de Endereçamento é o caminho no qual o operando é especificado. O
operando pode estar contido em:
 registros internos da CPU;
 própria instrução;
 memória principal;
 porta E/S;
Os endereços dos operandos da memória ou portas de E/S podem ser calculados de
modos diferentes. Estes modos definem o modo de endereçamento, e são:
2.3.1 - Imediato
Os operandos, de 8 ou 16 bits são dados ou valores que fazem parte da instrução.
Portanto o dado é especificado na instrução.
Código de Operação
Operando
Operando
Fig. 2.5 - Formato de Endereçamento Imediato
Exemplo: MOV AX, ABFDh
(3 bytes)
1º Byte
DC
2º Byte
FD
Instrução
Low Byte
(Registro AX
Exemplo: MOV AL, ABh
REG AL  ABh
3º Byte
AB
High Byte
Valor)
(2 bytes)
------ significado: o byte menos significativo do AX recebe o valor ABh
Dados: IP = 0000h e CS = 0100h
Calculo do endereço físico da instrução
endereço físico da próxima instrução a ser executada = IP + 10*CS
0000h +
IP = endereço do apontador de instrução
20
01000h - 10 * CS = endereço do início do segmento de código na MP
________
01000h endereço físico da próxima instrução
Endereço
Conteúdo da memória
Instrução
01000h
B0 - código de operação
MOV AL, ABH
01001h
AB – Operando
01002h
XX
Próxima instrução
Conteúdo dos Registros Internos da UPC
Antes da
instrução
00000
.
.
.
00100
.
.
.
AH
AL
XX
XX
Após a
instrução
00002
.
.
.
00100
.
.
.
AH
AL
XX
AB
IP
CS
AX
IP
CS
AX
2.3.2 - Direto
O endereço do dado está contido na instrução. Esta parte da instrução é denominada
deslocamento.
1º Byte
Código de operação
2º Byte
deslocamento menos
significativo
3º Byte
deslocamento mais
significativo
Exemplo: MOV CX, [ 1 2 3 4 h] (4 bytes)
CX  conteúdo de memória com endereço de deslocamento 1 2 3 4 h
Supondo : IP = 0000h , CS= 0100h e DS = 0200h
Endereço físico instrução : 0000 + 1000 = 1000h
Endereço físico dado : 1234 + 10*200 = 3234H
21
Endereço
1000
1001
1002
1003
1004
.
.
.
3234
3235
Conteúdo da
Memória
8B
OE
34
12
XX
.
.
.
AA
BB
Instrução
Código operação
MOV CX, [1234H]
Endereço
Próxima instrução
.
.
.
operando fonte
.
.
.
Conteúdo dos Registros internos da UPC
00000
.
.
.
00100
00200
.
.
.
CH
XX
IP
.
CS
DS
.
CL
XX
CX
00004
.
.
.
00100
00200
.
.
.
CH
BB
IP
CS
DS
CL
AA
CX
Observe que o conteúdo do endereço menor é armazenado no “registro menos
significativo” e o conteúdo do endereço maior é armazenado no “registro mais
significativo”.
2.3.3 Registradores
O dado está no registro interno que é especificado pela instrução
Exemplo: MOV AX, BX (2 bytes)
AX  Conteúdo do registro BX ------ o dado está no registro BX, e, ele será
carregado no registro AX.
Supondo : IP = 0000h, CS = 0100h e BX = 1234h
22
endereço físico da instrução = 1000h
Endereço
01000
01001
01002
Conteúdo da memória
8B - código de operação
C3
XX
Instrução
MOV AX, BX
Próxima instrução
Conteúdo dos Registros Internos da UPC
Antes da
instrução
00000
.
.
.
00100
.
.
.
XXXXX
01234
Após a
instrução
IP
CS
AX
BX
00002
.
.
.
00100
.
.
.
01234
01234
IP
CS
AX
BX
2.3.4 - Indireto
O endereço do dado é especificado pelo conteúdo da memória ou do registrador
contido na instrução. No endereçamento indireto por registrador, o endereço do dado
está nos registros de base BX ou BP ou nos de índice DI ou SI, que estão
especificados na instrução.
Exemplo : MOV AX , [SI] (2 bytes)
AX  conteúdo da memória cujo endereço é dado pelo registro SI.
Supondo : IP = 0000h, CS = 0100h, SI = 1234h e DS = 0200h
Endereço físico da instrução = IP + 10 * CS = 1000h
Endereço físico do dado = SI + 10 * DS = 1234 + 2000 = 3234h
23
Endereço
01000
01001
01002
.
.
.
03234
03235
8B
04
XX
Conteúdo da memória
- código de operação
Instrução
MOV AX, [SI]
Próxima instrução
.
.
.
Operando fonte
AA
BB
Conteúdo dos Registros Internos da UPC
Antes da
instrução
0000
.
.
.
0100
0200
.
.
.
XXXX
.
.
.
1234
Após a instrução
IP
CS
DS
AX
SI
0002
.
.
.
0100
0200
.
.
AH .
AL
BB
AA
.
.
.
1234
IP
CS
DS
AX
SI
2.3.5 - Base
O endereço do dado é obtido pela soma de um deslocamento, contido na
instrução, com o conteúdo do registro de base BX ou BP.
24
Exemplo : MOV [BX] . Beta, AL ou MOV [BX + Beta], AL (4 bytes)
Supondo : IP = 0000h, CS = 0100h , BX = 1000h, DS = 0200h e Beta = 1234h
Endereço físico da instrução = 1000h
Endereço físico do dado = (Beta + BX) + 10 * DS = (1234 + 1000) + 2000 = 4234h
Endereço
Conteúdo da memória
Instrução
01000
88
- código de operação
01001
07
MOV [BX]. Beta, AL
01002
34
- Operando
01003
12
01004
XX
Próxima instrução
.
.
.
.
.
.
.
.
.
04234
CD
Dado no endereço destino
após execução
Conteúdo dos Registros Internos da UPC
Antes da instrução
0000
.
.
.
0100
0200
.
.
.
BC
IP
0004
.
.
.
0100
0200
.
.
.
CS
DS
CD
1000
.
.
Após a instrução
AX
BX
BC
IP
CS
DS
CD
1000
.
.
AX
BX
2.3.6 - Índice
25
O endereço do dado é obtido pela soma de um deslocamento, contido na
instrução, com o conteúdo do registro de índice SI ou DI, similar ao endereçamento
por base.
Exemplo : MOV AL, ARRAY. [SI]
ou MOV AL, [ARRAY + SI} (4 Bytes)
Supondo : IP = 0000h, CS = 0100h , SI = 2000h, DS = 0300h e ARRAY = 1234h
Endereço físico da instrução = 1000h
Endereço físico do dado = (Array + SI) + 10*DS = ( 1234 + 2000 ) + 3000 = 6234h
Endereço
01000
01001
01002
01003
01004
.
.
.
06234
Conteúdo da memória
- código de operação
8A
44
34
12
XX
Instrução
MOV AL, Array [ SI ]
- Operando
Próxima instrução
.
.
.
.
.
.
F4
Conteúdo dos Registros Internos da UPC
Antes da
instrução
0000
.
.
.
0100
0300
.
.
.
XX
Após a
instrução
IP
0004
.
.
.
0100
0300
.
.
.
CS
DS
XX
.
.
.
2000
AX
SI
XX
IP
CS
DS
F4
.
.
.
2000
AX
SI
2.3.7 - Endereçamento de E/S
26
O endereçamento de Entrada/Saída (I/O) é utilizado juntamente com as
instruções IN e OUT para acessar portas de periféricos, podendo ser fixo ou variável.
Neste tipo de endereçamento o registrador A ( AX, AH ou AL) deverá sempre
ser utilizado como registro fonte ou destino.



Canal Fixo
Até 255 periféricos
I N AL, porta
AL  Conteúdo da porta
OUT porta, AX Porta  Conteúdo de AX




Canal Variável
O registro DX é o único que pode ser utilizado para endereçar um canal variável
Até 64k periféricos
IN AX, DX
AX  Conteúdo da porta endereçada por DX
OUT DX, AH
Conteúdo da porta endereçada por DX  Conteúdo AH
2.3.8 - Resumo dos modos de Endereçamento






Imediato - dado está na instrução;
Direto - endereço do dado está na instrução;
Registrador - dado está no registro especificado na instrução;
Indireto - endereço do dado está nos registro de base BX ou BP especificado na
instrução;
Base - endereço do dado é a soma de um deslocamento (dado na instrução), com
o conteúdo do registro de base BX ou BP;
Índice - similar ao de base, porém utiliza os registros de índice SI ou DI..
27
Fig. Computação do endereço da memória
Registros envolvidos nos modos de endereçamento
Instruções
Dados
Direto
Registro Indireto
Base
Indice
Baseado Indexado
X
Pilha
28
CAPITULO III
3 - Programação
3.1 - Utilitário Debug
29
O Debug é um utilitário fornecido junto com o MS-DOS, que tem a finalidade de
depurar programas.Através do Debug é possível fazer pequenos programas, ou testar
outros programas feitos através de um compilador assembler.
O Debug permite que se execute um programa passo a passo, isto é, uma instrução
de cada vez. A cada instrução executada é possível examinar o estado dos registradores e
da memória antes de prosseguir.
Não serão mostrados todos os comandos ou sintaxes do debug, isto pode ser visto
em algum livro que trate especificamente deste assunto. Apenas será mostrado a forma
prática e objetiva de seus principais comandos, o que permitirá que sejam feitos e
testados os primeiros programas dados como exemplos.
3.1.1 - Como Entrar no Debug
Localizar o Debug no disquete do DOS. Para entrar no programa digitar
:>Debug <Enter>.
Ao entrar no Debug, apenas surgirá um tracinho (-) no canto esquerdo do vídeo,
antecedendo o cursor.
3.1.2 - Comandos do Debug
Comando R (registers)
O comando R exibe no vídeo o conteúdo de todos os registradores e a próxima
instrução a ser executada pelo programa sendo ‘ debugado’.
Este comando também permite que se coloque qualquer valor em qualquer
registrador.
Para ver o valor de todos os registradores digitar:
R <Enter>
Para colocar um valor em um registrador, digitar:
R[registrador] <Enter> Exemplo RAX <Enter> ( p/ carregar AS)
Após digitar <Enter> será mostrado no vídeo o valor atual do registrador
desejado e pode-se digitar um novo valor, ou apenas pressionar <Enter> para não
alterar o valor atual.
Comando A (assembler)
O comando A entra num minicompilador assembler do Debug. Através dele é
possível fazer pequenos programas, como o mostrado a seguir:
Digitar A100 <Enter>
Neste caso, o numero 100 é o endereço onde o programa será armazenado.
30
Surgirá um endereço formado por 8 dígitos. Os primeiros 4 dígitos representam
o registrador CS e portanto são o segmento do programa. Os últimos 4 dígitos
deverão ter o endereço 0100, que foi especificado no comando.
Digitar o seguinte programa, sempre digitando < Enter> no final de cada linha.
MOV
MOV
ADD
MOV
INT
AS, 200
BX, 300
AS, BX
[200], AS
3
Ao terminar de digitar o programa, teclar <Enter> deixando uma linha em
branco para sair automaticamente do miniassembler.
Comando U (unassembler)
O comando U ‘disassembla’ um programa, convertendo os dígitos de volta em
instruções. O formato deste comando é:
U[endereço] <Enter>:
Digitando apenas U <Enter> ele recomeçará a partir do ultimo endereço exibido.
Digite U100 <Enter>
Para ver o programa implementado.
Comando T (trace)
Este comando permite a execução passo a passo de um programa. A cada
instrução executada, ele mostra o estado dos registradores e da memória envolvida
na operação. Este comando é utilizado para executar e testar o programa dado acima.
O formato do comando T, é:
T = [segmento; endereço] <enter>
Comando D (dump)
Este comando permite que a memória seja examinada. Pode-se ver qualquer
região da memória do computador , mas neste caso, será visto o endereço 200 do
segmento de dados apontado por DS para ver o resultado da operação feita pelo
processador.
A sintaxe deste comando é:
31
D[segmento: endereço] <enter>
Se o segmento for omitido, o segmento atual do registrador Ds será usado. Se o
endereço for emitido, o último endereço mostrado será o ponto de partida, isto quer
dizer que digitando apenas D <enter> o próximo bloco da memória será mostrado.
Digite D200 <enter>
(é omitido o segmento)
Aparece o conteúdo do endereço 200 do segmento DS. Seguindo o exemplo
acima, neste endereço observa-se o valor 500, sendo 00 no endereço 200 e 05 no
endereço 201.
Comando Q (quit)
Este comando é usado para sair do Debug voltando para o DOS.
Digite:
Q <enter>
3.2 - Exemplo de programa escrito em linguagem assembly, utilizando o utilitario
Debug
32
3.2.1 - Instrução MOV
Usada para atribuir valores a um registrador ou a um endereço da memória. É
uma das instruções fundamentais para manipulação dos dados. Na prática, qualquer
programa, por menor que seja, sempre usará ao menos uma instrução MOV.
Pode ser usada para carregar valores nos registradores ou para guardar valores
na memória.
Exemplos:
MOV
MOV
MOV
MOV
MOV
AX, 01
AX , BX
[100], AX
AX, [100]
[100], 01
;Carrega o registrador AX com o valor 1
;Carrega o registrador AX com valor do registrador BX
;Põe o valor de AX no endereço 100
;Coloca em AX o conteúdo do endereço 100
;Coloca o valor 1 no endereço 100
Note que as chaves [ ] são utilizadas para especificar o conteúdo de um
endereço. O simples fato de esquecer de usar um destes símbolos durante a
programação, pode comprometer todo o resultado do programa, pois o valor obtido
pode ser totalmente diferente do desejado. Veja exemplo:
MOV
MOV
AX, 100
AX, [100]
;o registrador AX valerá 100
;o registrador AX terá o valor contido no endereço 100
3.2.2 - Instrução ADD
Soma dois valores e coloca o resultado da operação em um registrador ou um
endereço da memória. A operação sempre é realizada somando-se o elemento que
está depois da vírgula ao elemento que está antes, atribuindo ao primeiro elemento o
resultado da soma.
Exemplos:
ADD
AX, BX
ADD
ADD
AX, 01
AX, [100]
ADD
[100], AX
ADD
[100], 01
;Soma o valor de AX com o valor de BX e põe o
resultado em AX.
; Soma ao valor de AX + 1 e deixa o resultado em AX.
;Soma ao valor de AX o conteúdo do endereço 100 e
deixa o resultado em AX.
;Soma ao conteúdo do endereço 100, o valor de AX e
deixa o resultado no endereço 100.
;Soma ao conteúdo do endereço 100, o valor 1 e deixa o
resultado no endereço 100.
33
3.2.3 - Instrução SUB
Subtrai dois valores e coloca o resultado da operação em um registrador ou em um
endereço da memória. A operação sempre realizada subtraindo o segundo elemento
do primeiro, e o resultado deixado no primeiro elemento.
Exemplos:
SUB
SUB
SUB
SUB
AX, BX
AX, 01
AX, [100]
[100], AX
SUB
[100], 01
;Subtrai de AX o valor de BX
;Subtrai 1 de AX
;Subtrai de AX o conteúdo de endereço 100
;Subtrai do conteúdo do endereço 100,
o
de AX.
;Subtrai 1 do conteúdo do endereço 100
valor
3.2.4 - Programa exemplo: Somar dois valores
Neste exemplo, temos dois números gravados na memória. Queremos saber qual
é a soma destes números e colocar o resultado em um lugar seguro da memória. Para
obter o resultado é preciso ler em AX o primeiro número, somá-lo ao segundo e
guardar o resultado na memória. Veja como isto é feito.
MOV
ADD
MOV
AX, [valor1]
AX, [valor2]
[resultado], AX
;obtém o valor do primeiro número
;soma com o segundo número
;salva o resultado na memória
Como você pode perceber, neste exemplo nós realizamos a soma de sois
números sem utilizar nenhum valor específico. No lugar dos valores, utilizamos os
nomes : Valor1, valor2, resultado. Isto é chamado de LABEL (Rótulo).
Um LABEL é utilizado para dar nome a um endereço da memória. Desta forma
fica mais fácil fazer o programa, pois deixamos para o compilador a tarefa de
transformar o label em um endereço correspondente.
Podemos também atribuir um valor predefinido a um label, não precisando ser
necessariamente um endereço de memória.
3.2.5 - INSTRUÇÃO CMP
Compara dois valores e atualiza o FLAG de acordo com o resultado. Esta
instrução é fundamental durante o programa. Ela é usada como base para a tomada
de decisões pelo programa. Para um exemplo prático, imagine que o programa
precisa saber se a tecla <ENTER> foi pressionada. Para chegar à conclusão sobre
esta questão, o programa faz um MOV para AX com o valor da última tecla
pressionada, então executa um CMP com AX (compara AX) e o valor da tecla
34
<ENTER>. Se os valores forem iguais, o FLAG Zero será colocado em 1 e o
programa poderá verificar isso, decidindo o que fazer.
Exemplos:
CMP
CMP
CMP
CMP
CMP
AX, BX
AX, 01
AX, [100]
[100], AX
[100], 01
; compara AX com BX
; compara AX com 1
; compara o valor de AX com o conteúdo do endereço 100
; compara o conteúdo do endereço 100 com o valor de AX
; compara o conteúdo do endereço 100 com o valor 1
A instrução CMP, causa alterações em vários BITS do FLAG. Quando uma
instrução CMP é executada, internamente o microprocessador executa uma
subtração, ou seja, ele subtrai o segundo elemento do primeiro.
Exemplificando, a instrução CMP AX, 01 será processada internamente como
"subtraia 1 de AX". Note que isto só ocorre internamente, e que na prática o valor de
AX não será modificado. Mas você deve saber disso para poder planejar o destino do
seu programa, quando for necessário basear- se no resultado de uma comparação
para tomar uma decisão.
Após uma instrução CMP, o FLAG assumirá a seguinte modificação:
BIT DA FLAG
ZERO
CARRY
PARITY
ASSUMIRÁ O VALOR
será 1, se os dois valores comparados forem iguais. Caso
contrário será 0
será 1 se o segundo elemento for maior que o primeiro. Será
0 se o segundo Elemento for menor ou igual ao primeiro.
será 1 se o número de bits 1 do valor que resultar da
operação.
Sempre que uma instrução CMP ou qualquer outra instrução aritmética é
executada, o FLAG é alterado para indicar o resultado da operação.
Através de um conjunto de instruções que operam baseadas no estado do FLAG,
será possível ao programa tomar decisões baseadas no resultado da operação. |Veja
no próximo item, que instruções são estas.
3.2.6 - INSTRUÇÕES DE SALTO CONDICIONAL
Este conjunto de instruções permite direcionar o programa, baseando- se no
estado do FLAG. Este conjunto é bem completo e permite que se obtenha um
controle total sobre o rumo a ser tomado.
35
Seu nome original é "JUMP" (salto em inglês, e de fato, elas podem causar um
salto para frente ou para trás, determinando qual será a próxima instrução a ser
executada pelo microprocessador.
Como o resultado do uso destas instruções será baseado no estado atual do
FLAG, é importante que você conheça mais um pouco sobre este registrador.
O FLAG, como já foi explicado antes, é um registrador de 16 bits que tem a
finalidade de mostrar o estado atual do microprocessador, bem como acusar qual foi
o resultado da última operação executada por ele. Para fazer isso, cada bit deste
registrador recebeu um nome e uma letra que identifica. 7 dos 16 bits foram
reservados para uso futuro do fabricante do microprocessador, portanto apenas 9 bits
nos interessam.
Cada bit pode conter o valor 0 ou 1, dependendo do resultado da última
operação. É o próprio microprocessador que atualiza o valor destes bits, durante a
execução de uma instrução.
Já explicamos, um pouco atrás, os três bits do FLAG usados para exercer algum
tipo de controle sobre o microprocessador, que são:
TRAP (T), DIRECTION (D) e INTERRUPT - ENABLE (I).
3.3 - Manipulação de Dados
Existem um conjunto de instruções específicas para a manipulação de dados. Elas
são um complemento da instrução MOV pois são ideais para manipular uma seguência de
dados. Elas permitem a manipulação de dados em forma de BYTEs ou WORDs.
Uma particularidade delas é que são utilizadas com registradores predefinidos, isto é,
você não pode especificar os registradores que serão usados. A operação sempre será feita
com DS:SI para a origem dos dados e ES:DI para o destino dos dados. Assim, você
deverá colocar os endereços nestes registradores antes de usar uma destas instruções.
3.3.1 -Instrução MOVSB e MOVSW
Estas instruções copiam um byte (MOVSB) ou uma Word (MOVSW) DS:SI
para ES:DI.
Tomando como exemplo a instrução MOVSB, podemos dizer que da copia o
byte contido no endereço apontado por DS:SI para o endereço apontado por ES:DI.
Mas baseando-se no Flag de direção os registradores SI e DI serão incrementados
ou decrementados automaticamente. Veja o exemplo:
36
Faremos um programa que transfere o valor contido no endereço: 0100:0000
para o endereço 0200:0000.
CLD
; zera o Flag de direção (seleciona o avanço)
MOV
AX,0100
;valor para o segmento DS
MOV
DS, AX
;
MOV
AX,0200
;valor para o segmento ES
MOV
ES,AX
;
MOV
SI,0000
;endereço 0000 (onde está a informação)
MOV
DI,0000
;endereço 0000 (para onde vai a informação)
MOVSB
;copia o valor de DS:DI para ES:DI e
incrementa
;os valores de SI e DI.
3.3.2 - Instrução REP
Esta instrução faz com que a instrução de manipulação de dados seja
REPETIDA o numero de vezes estabelecido através do registrador CX. Por exemplo
para copiar 10 bytes de um local para outro, coloque 10 em CX e use o comando
REP MOVSB. Aplicando esta regra no programa anterior ele ficaria assim:
CLD
MOV
MOV
MOV
MOV
MOV
MOV
MOV
REP
AX,0100
DS,AX
AX,0200
ES,AX
SI,0000
DI,0000
CX, 10
MOVSB
;zera o Flag de direção (seleciona o avanço)
;valor para o segmento DS
;
;valor para o segmento ES
;
;endereço 0000 (onde está a informação)
;endereço 0000 (para onde vai a informação)
;número de bytes a mover
;copia o valor de DS:DI para ES:DI e incrementa
;os valores de SI e DI, decrementa CX e repete
;até que CX = 0.
Também poderíamos Ter feito este programa usando CX = 5 e a instrução
MOVSW no lugar da MOVSB, pois uma Word tem 2 bytes e o resultado da rotina
seria a transferencia de 10 bytes (5*2).
3.3.3 - Instruções LODSB - LODSW e STOSB - STOSW
LODSB carrega AL com o byte apontado por DS:SI, enquanto LODSW carrega
AX com a Word apontada por DS:DI.
STOSB salva o valor de AL no endereço apontado por DS:DI, e STOSW salva
o valor de AX no endereço apontado por DS:DI.
Após qualquer uma destas instruções o registrador SI ou DI, conforme o caso, é
incrementado ou decrementado conforme o estado da Flag de DIREÇÂO. Estas
37
instruções são especialmente úteis quando é preciso realizar algum tipo de
processamento com uma seguência de informações.
Por exemplo, se tivéssemos uma tabela com 10 valores e fosse necessário somar
2 a cada um deles faríamos assim:
MOV
MOV
endereço
CLD
MOV
PRXM: LODSB
ADD
STOSB
LOOP
SI, TABELA_VALORES
DI, SI
CX, 10
AL,2
PRXM
;posiciona SI na tabela de valores
;DI também com o mesmo
;direção para frente
; a tabela tem 10 valores
;obtém um valor
; soma 2 valor
;devolve o valor à tabela
;repete até CX = 0
Neste exemplo, usando a instrução LOOP que será explicada mais adiante.
3.3.4 - Instrução CMPSB - CMPSW
Estas instruções são utilizadas para comparar dados como faz a instrução CMP,
porém são usadas para comparar seguencias de dados.
Elas comparam o byte ou Word apontado por DS:SI com o byte ou Word
apontado por ES:DI e incrementam ou decrementam SI e DI, conforme o estado da
Flag de DIREÇAÔ. Para comparar uma seguencia é necessário utiliza-las em
conjunto com a instrução REP.
Um exemplo de emprego destas instruções seria na seguinte operação: é achar o
nome de uma pessoa que está numa relação de nomes. O programa seria assim:
CLD
MOV
PRXM: MOV
MOV
MOV
REP
JZ
ADD
CMP
JNZ
Nome_ERR:.....
.
.
.
Nome_OK
BX, Lista_nomes
DI,BX
SI, Nome
CX, 25
CMPSB
Nome_OK
BX, 25
[BX], 000h
PRXM
;direção para frente
;posiciona DI na lista de nomes
;posiciona SI no nome procurado
;tamanho dos nomes
;compara um nome
;nome localizado
;posiciona no próximo nome
;final da tabela?
;não compara o próximo
; nome não está na lista
;nome está na lista
38
3.4 - Manipulação de Bits
Um conjunto de instruções que permitem a manipulação de cada bit de um byte.
Estas instruções são úteis em todas as circunstancias e são muito usadas na manipulação
de imagens gráficas, programas de comunicação, e cálculos.
Este grupo de instruções usa regras que se aplicam a todas as instruções pertencentes
a ele. Como a função delas todas é a mesma: rotaciona bits, você pode especificar quantos
bits quer rotacionar colocando o valor em CL, ou rotacionar uma vez usando o valor 1
direto. O número máximo que você pode usar em CL é 32, pois o 80286 e 80386 limitam
a este valor máximo para impedir que num ambiente multitarefa, o microprocessador
fique ocupado por muito tempo em um só programa.
Exemplos:
RCL
MOV
RCL
AX, 1
CL, 10
BX,CL
; rotaciona AX uma vez
;
;rotaciona BX dez vezes
3.4.1 - Instrução RCL
Rotaciona para esquerda usando o CARRY.
DADO
CARRY
O CARRY é colocado no bit 0 do byte ou Word empurrando todos os bit, um bit
mais para esquerda, ultimo bit do byte (o 7) ou da Word ( o 15) é colocado no
CARRY.
3.4.2 - Instrução RCR
Rotaciona para direita usando o CARRY.
DADO
CARRY
39
O CARRY é colocado no bit mais á esquerda (bit 7 do byte ou 15 da Word)
empurrando todos os bits, um bit mais para direita, o bit 0 do byte ou Word é
colocado no CARRY.
3.4.3 - Instrução ROL
Rotaciona para esquerda.
CARRY
DADO
Os bits do byte ou Word são deslocados um bit para a esquerda e o bit mais à
esquerda é colocado no bit 0. O Carry também recebe o bit mais à esquerda, porém
seu estado anterior é desprezado.
3.4.4 - Instrução ROR
Rotaciona para direita
DADO
CARRY
Os bits do byte ou Word são deslocados um bit mais para a direita e o bit 0 é
colocado no ultimo bit do byte ou Word. O CARRY também recebe o bit 0.
3.4.5 - Instruções SAL e SHL
Deslocamento aritmético á esquerda.
Estas duas instruções tem a mesma função, ou seja, é a mesma instrução com
dois nomes.
CARRY
DADO
Um bit de valor 0 é inserido no primeiro bit do byte ou Word, deslocando os
outros bits para a esquerda. O último bit ( 7 ou 15) é colocado no CARRY.
40
A instrução SAL pode ser utilizada para multiplicar um número por múltiplos
de 2. Exemplo:
MOV
SAL
SAL
AL, VALOR
AL, 1
AL, 1
;obtém o valor
;multiplica por 2
;multiplica por 4
Quando a primeira instrução SAL é executada, AL é multiplicado por 2, e na
Segunda instrução AL também é multiplicado por 2, resultando em AL= AL * 2 * 2,
ou seja, AL * 4. Veja porque:
Valor inicial: 2
Em binário : 00000010
Após um sal: 00000100 = 4
3.4.6 - Instrução SHR
Deslocamento aritmético á direita.
DADO
CARRY
CARRY
Um bit 0 é inserido à direita do byte ou Word. Os outros bits são deslocados
para a direita e o bit 0 é colocado no CARRY.
A instrução SHR pode ser usada para dividir um número por múltiplos de 2.
Exemplo:
MOV AL, VALOR
;obtém o valor
SAL
AL, 1
;divide por 2
SAL
AL, 1
;divide por 4
Quando a primeira instrução SHR é executada, AL é dividido por 2, na Segunda
instrução AL também é dividido por 2, resultando em AL = AL / 2 / 2, ou seja , AL /
4. Veja porque:
Valor inicial : 10
Em binário : 00001010
Após um SAL: 00000101 = 5
Observe que a divisão terá sempre como resultado um valor exato, ou seja, não
haverá quebrados ou restos. Para obter o resto poderíamos usar a instrução RCL,
explicada
anteriormente, copiando o CARRY para usar a instrução RCL,
explicada anteriormente, copiando o CARRY para outro registrador depois de
cada SAL, desta forma:
41
MOV
MOV
SAL
RCL
SAL
RCL
AL, VALOR
BL,000h
AL, 1
BL, 1
AL, 1
BL, 1
;obtém o valor
;zera BL para guardar o resto
;divide por 2
;copia CARRY em BL
;divide por 4
;copia CARRY em BL
No final desta rotina, AL terá o resultado da divisão e BL o resto.
3.4.7 - Instrução SAR
Deslocamento á direita com repetição.
7
6
5
4
3
2
1
0
CARRY
Desloca todos os bits do byte ou Word para a direita e não alterando o bit mais
À esquerda, ou seja, o bit 7 do byte é copiado para o 6 mas é mantido intacto.
3.4.8 - Aplicando as Instruções que Manipulam Bits
Mostraremos alguns exemplos de uso das instruções que acabamos de
apresentar:
3.4.8.1 - RCL e SAL
Podem ser usadas em conjunto para multiplicar um valor com mais de 16
bits.
Considere que AX:BX contém um valor de 32 bits que deve ser
multiplicado por 2, a rotina seria assim.
SAL
RCL
BX, 1
AX, 1
;multiplica a parte baixa
;multiplica a parte alta
O primeiro SAL multiplica a parte baixa do valor ( a primeira Word) e deixa o
bit 15 no
CARRY. A instrução RCL copia o CARRY para BX (a Segunda
Word) e multiplica-o deslocando os bits para a esquerda. Desta forma
conseguimos transferir 1 bit de um registrador para outro.
42
3.4.8.2 - RCR e SHR
Da mesma forma que o item anterior, estas instruções usadas em conjunto
podem dividir
valores maiores que 16 bits. Considerando um valor de 32
bits guardado em AX:BX, uma rotina para dividi-los por 2 seria assim:
SHR
RCR
AX, 1
AX, 1
;divide a parte alta
;divide a parte baixa
No exemplo acima, o bit 0 de AX é transferido para o bit 15 de BX,
passando antes pelo
CARRY.
3.5 - Instruções Aritméticas
Um outro conjunto de instruções é específico para cálculos. Embora outras
instruções que não pertencem a este grupo também possam ser usadas para cálculos,
como as instruções de manipulação de bits, neste conjunto incluiremos apenas as
exclusivas para cálculos.
3.5.1Instruções ADD e ADC
Usadas para somar (Adição). ADD soma dois valores sem considerar o Flag
Carry enquanto ADC considera o CARRY na soma. Exemplo:
Para apenas somar dois valores podemos fazer:
MOV
ADD
AX,Valor_1
AX,VALOR_2
;AX = AX + VALOR_2
Porém se a soma destes dois valores resultar num valor maior que 16bits ou
65535, haverá um estouro gerando um bit a mais. Este bit a mais será colocado no
Flag Carry, já que AX comporta apenas 16bits. Sendo assim o resultado desta soma
estará em Carry Flag + AX.
Se quisermos obter resultados maiores que 16 bits, precisamos utilizar dois
registradores para receber o resultado da soma e usar a instrução ADC para
considerar o estado do Carry. Exemplo: Somaremos dois valores de 16 bits e
usaremos BX:AX para guardar o resultado de 32bits.
MOV
MOV
ADD
ADC
AX,VALOR_1
BX,000h
AX,VALOR_2
BX,0
;valor inicial de AX
;BX é zerado
;soma os dois valores
;soma BX com 0 para transferir
;a ele o valor de CARRY
;BX = BX + 0 + CARRY
43
Neste exemplo, AX é carregado com o primeiro valor, BX é zerado para
posteriormente receber a parte do valor de 32 bits. Após somar AX com o segundo
valor, o CARRY será um se tiver ocorrido um estouro. Usando a instrução ADC BX,
0 o valor do CARRY 0 ou 1 será somado a BX que foi previamente zerado. O
resultado da soma será um número de 32 bits formado por BX:AX.
3.5.3 - Instrução MUL
Usada para multiplicação de valores. Pode ser usada de duas formas, para
multiplicar um valor de 8 bits por AL ou um valor de 16 bits por AX. Se a
multiplicação for por AL, o resultado estará em AX, se a multiplicação for por AX, o
resultado estará em DX:AX. Por exemplo:
Para multiplicarmos um valor de 8 bits por outro de 8 bits, fazemos:
MOV
MUL
MOV
AL, valor_1
valor_2
[resultado], AX
;valor de 8 bits
; multiplica por outro valor de 8 bits
;salva resultado de 16 bits
Para multiplicarmos um valor de 8 bits ou 16 bits por outro de 16 bits, fazemos:
MOV
MOV
MUL
MOV
MOV
AX, valor_1
CX, valor_2
CX
[resultado], AX
[resultado + 2], DX
;valor de 8 ou 16 bits
;valor de 16 bits
; multiplica
;salva resultado de 32 bits
;
O resultado da operação é automático 16 ou 32 bits conforme o operando usado.
Se for usado um operando de 8 bits, o resultado será de 16 bits e estará todo em AX.
Exemplos:
MUL
MUL
MUL
CL
DL
20
;AX = AL * CL
;AX = AL * DL
;AX = AL * 20
Se for usado um operando de 16, o resultado será de 32 bits e estará em DX:AX,
exemplos:
MUL
MUL
MUL
CX
DX
8000h
;DX:AX = AX * CX
;DX:AX = AX * DX
;DX:AX = AX * 8000h
44
3.5.4 - Instrução DIV
Usada para divisão. Seu emprego é semelhante à instrução MUL.
Ela pode dividir o valor de AX por outro de 8 bits, ou dividir o valor de DX:AX
por outro de 16 bits. Se a divisão for por 8 bits o resultado da divisão estará em AL
enquanto AH guardará o resto da divisão. Se for por 16 bits, AX terá o resultado e
DX o resto. Exemplos:
DIV
DIV
DIV
DIV
CL
10
CX
500
;AL = AX / CL (AH = resto)
;AL = AX / 10 (AH = resto)
;AX = DX:AX / CX (DX = resto)
;AX = DX:AX / 500 (DX = resto)
3.5.5 - Instrução DEC
Decrementa um resgistrador ou um valor. Decrementar significa subtrair 1. Com
toda operação aritmética o resultado da operação afeta diretamente os FLAGS de
indicação. Útil em muitas ocasiões, ela é utilizada principalmente em controle de
loops. Exemplos:
MOV [CONTADOR], 10
PRXM: MOV AX, [BX]
ADD
AX, CX
STOSW
ADD
BX, 2
DEC
[CONTADOR]
JNZ
PRXM
;contador = 10
;processa informação
;
;
;
;decrementa contador
;continua até que contador = 0
DEC pode ser usado com registradores ou endereços, exemplo:
DEC
DEC
DEC
AX
BL
[VALOR]
;AX = AX - 1
;BL = BL - 1
;VALOR = VALOR - 1
3.5.6 - Instrução INC
É o inverso da instrução DEC, ou seja, ela incrementa um registrador ou um
valor. Incrementa significa somar 1. INC, da mesma forma que DEC pode ser usado
com registrador ou endereços, exemplo:
INC
INC
INC
DX
AL
[VEZES]
;DX = DX + 1
;AL = AL + 1
;VEZES = VEZES + 1
45
3.6 - Instrução Lógicas
Assim como em todas as linguagens, no Assembly também temos valores lógicos ( e,
ou , Tc...) porém o seu conceito é um pouco diferente das outras linguagens.
3.6.1 - Instrução AND
Produz um 'e' lógico. AND faz uma comparação bit a bit entre dois valores e
gera um terceiro valor contendo apenas os bits onde os dois valores iniciais
continham 1.
Exemplo:
1
2
0
0
AND
AND
AND
AND
1=1
0=0
1=1
0=0
AND pode ser usado para isolar bits:
MOV
AND
.
.
.
AL, [INFORMAÇÃO]
AL, 03H
;obtém informação
;isola os bits 0 e 1
;continua o processamento
Pede ser usado para testar um bit:
MOV
AND
JNZ
CL,[INDICADOR]
CL, 004H
PROCESSA
;obtém indicador de estado
;testa o bit 3
;salta se o bit for 1
3.6.2 - Instrução OR
Ou lógico. Ou compara um bit a outro e caso um deles seja 1, produz como
resultado 1.
Exemplos:
1
1
0
0
OR
OR
OR
OR
1=1
0=1
1=1
0=0
De forma que o resultado só será 0 se os dois bits envolvidos forem zero.
46
OR pode ser usado para juntar dois valores em um só:
MOV AL, [DIA]
;obtém o dia
OR
AL,[MÊS]
;junta ao mês
.
;processamento
.
OR pode ser usado par mudar o valor de um bit para 1:
MOV
OR
.
.
AL, [INDICADOR]
AL, 02H
;obtém indicador
;seta o bit 1 de AL
;processa...
3.6.3 - Instrução XOR
XOR soma um bit a outro e gerando o resultado 0 se os dois bits forem 1 ou 0
Exemplos:
1 XOR 1 = 0
1 XOR 0 = 1
0 XOR 1 = 1
0 XOR 0 = 1
XOR, assim como OR e AND, são, entre outras, muito utilizadas na
manipulação de imagens gráficas.
3.7 - Instrução de Desvio e Transferencia de Controle
Neste grupo, estão as instruções que permitem ao programa chamar sub-rotinas ou
causar desvios condicionais dentro de um mesmo bloco. Apenas 3 tipos de instruções
pertencem
a ele: JUMP relativo, JUMP e CALL.
3.7.1 - Instrução JUMP relativo
JUMP relativo significa SALTO. Neste caso, um salto condicional e relativo.
Condicional porque ele só é executado se a condição estabelecida for verdadeira, e
RELATIVO porque o salto é um número de bytes para frente ou para trás em
RELAÇAO ao endereço em que está. Estas instruções são fundamentais em qualquer
programa, pois através delas é que se ireciona o processamento, adequando-o às
circunstancias. Elas são equivalentes ``a instrução IF das linguagens de alto nível.
47
Um grande conjunto de instruções integram este grupo, permitindo que se teste
qualquer condição. As condições são sempre estabelecidas pelo estado do registrador
FLAG. Algumas instruções deste grupo são:
JZ
JNZ
JC
JNC
salta se Z = 1
salta se Z = 0
salta se C = 1
salta se C = 0
Como são sempre condicionadas ao estado do FLAG, estas instruções são
sempre utilizadas após outra instrução que altere o FLAG, como: CMP, ADD,
SUB, AND, OR e Tc..., exemplo:
MOV AL, [NUMERO]
;obtém um número
AND
AL, 01
;testa o bit 1
JZ
PAR
;salta se o número é par
...
;processa o numero ímpar
PAR:. . .
O programa acima, testa se um número ´s par ou ímpar checando o bit 0 do
número. Números ímpares sempre tem o bit 0 = 1. Se o número for par, a instrução
AND AL, 01 fará o FLAG Z = 1 e a instrução JZ será válida.
A relação completa dos JUMPs relativos está no APENDICE B
3.7.2 - Instrução JUMP
Executa um desvio incondicional. A instrução JUMP não é relativa. Ao usá-la é
necessário especificar o endereço real para onde o programa deve desviar, É claro
que o programador não precisa saber o endereço, basta utilizar um LABEL e deixar o
resto por conta do compilador.
Esta instrução é muitas vezes utilizada em conjunto com os JUMPs relativos, já
que estes
são condicionais mas não podem desviar para endereços distantes (seu
limite é 128 bytes à
frente ou 127 para trás), enquanto JUMP não é condicional
mas pode ir para qualquer endereço.
Exemplo:
INÍCIO: MOV
...
MOV
CMP
JNZ
JMP
CONT: . . .
...
JMP
FIM:
...
AX, [VALOR]
AL, [SELEÇÂO]
AL, FIM
CONT
FIM
INÍCIO
;inicio do programa
;processamento do programa
;obtém seleção do usuário
;selecionou fim
;não, continua processamento
;sim, termina o programa
;processa
;volta ao início
;finaliza o programa
48
No exemplo acima, JUMP foi utilizado para voltar ao início do programa,
ficando em loop. Durante o programa é testada a condição de FIM, que se for
verdadeira permitirá que outro JMP desvie a uma sub-rotina que termina o
programa.
3.7.3 - Instrução CALL
Esta instrução, como JUMP, permite que se desvie para qualquer endereço da
memória. Porém enquanto JUMP é utilizado para mudar o rumo do programa, CALL
é especifico para executar uma sub-rotina.
Ao executar uma instrução CALL o microprocessador guarda no STACK o
endereço da instrução subsequente ao CALL no programa. A execução passa então
para o endereço especificado no CALL. Ao encontrar uma instrução RET, o
microprocessador recupera o endereço do STACK e volta a executar a instrução que
estava após o CALL.
Exemplo:
Programa
MOV
CALL
MOV
CALL
...
...
AX, NOME
IMPRIME
AX,FONE
IMPRIME
;obtém endereço do nome
;sub-rotina - imprime nome
;obtém endereço do fone
;sub-rotina - imprime o fone
;processa
Sub-rotina
IMPRIME: MOV BX, [POSIÇÃO]
...
...
;rotina para imprimir
;processa
RET
;retorna
O programa acima dá o exemplo de uma sub-rotina que imprime os dados
apontados por AX. O programa principal posiciona AX na informação desejada e
chama a sub-rotina que imprime a informação. Ao encontrar um RET o controle
volta ao programa principal. A instrução RET significa o retorno ao programa
principal, após a execução da sub-rotina.
49
3.8 - Controle de Loop
Embora já tenham sido vistas instruções que são utilizadas para controlar loops,
como as instruções de saltos condicionais, existem algumas instruções especificas para
isto.
3.8.1 - Instrução de LOOP
Esta instrução decrementa o valor do registrador CX e executa um salto relativo
se CX não for 0. Um programa que precise obter 3 números pelo teclado pode usá-la
desta forma:
MOV
PRXMNUM: CALL
CALL
LOOP
CX, 3
PEGA_NUMERO
GUARDA_NUM
PRXMNUM
;3 números
;obtém 1 numero
;guarda o número
;faz um loop ate CX = 0
A instrução LOOP usa a mesma forma de endereçamento dos JUMPS relativos.
E pode ser substituído por eles, desta forma:
...
DEC
CX
JR NZ<PRXMNUM
;programa
;decrementa CX
;executa ate CX = 0
3.8.2 - Instrução LOOPZ e LOOPNZ
Operam da mesma forma que loop, porém devem ser usadas após uma instrução
que afete o FLAG Z, pois além de decrementar CX, elas testam este FLAG.
Exemplo:
MOV
CX, 10
;serão 10 tentativas
OUTRO:
CALL
OBTEM_NUMERO ;obtém um numero em AL
CMP
AL, 100
;número = 100 ?
LOOPNZ
OUTRO
;não, loop ate CX = 0
...
;processa
O programa acima, obtém 10 números através da sub-rotina
OBTEM_NUMERO, caso um número = 100 seja obtido, o loop é encerrado antes
de completar os 10. Caso contrário ele só terminará quando tiverem sido obtidos
10 números.
3.9 – Acesso ao Stack Pointer
3.9.1 – Instruções PUSH e POP
50
A instrução PUSH salva o valor de um registrador no STACK. POP recupera este
valor. Estas intruções são normalmente utilizadas para salvar o conteúdo prévio de um ou
vários registradores, durante a execução de uma sub-rotina.
Exemplo: Um programa de banco de dados chama uma sub-rotina que tem a função
de coletar informações pelo teclado. Porém, a sub-rotina não pode alterar o valor dos
registradores AX, BX, CX e DX, pois eles contém informações utilizadas pelo corpo
principal do programa. As instruções PUSH e POP podem ser utilizadas desta maneira:
Corpo principal
…
CALL SUB_ROTINA
…
;processamento prévio
;chama a sub-rotina
;continua o processamento
Sub- rotina
SUB_ ROTINA: PUSH
PUSH
PUSH
PUSH
...
...
...
POP
POP
POP
POP
AX
BX
CX
DX
DX
CX
BX
AX
;salva AX no STACK
;salva BX no STACK
;salva CX no STACK
;salva DX no STACK
;recupera DX
;recupera CX
;recupera BX
;recupera AX
51
3.10 - Entrada e Saída
As instruções deste grupo, são utilizadas para a comunicação do microprocessador
com outros componentes do hardware do computador. Duas instruções compõe o grupo:
IN e OUT. A primeira é responsável pela leitura de informações e a segunda pelo envio
de informações.
O controle do alto falante interno do computador, por exemplo, é feito através das
instruções IN e OUT. Algumas placas de funções específicas, como placa de som, placa
de comunicação, placa de scanner e Tc..., também usam as instruções IN e OUT para se
comunicarem com o microprocessador.
O formato destas instruções é:
IN
IN
OUT
OUT
AL,PORTA
AL, DX
porta, AL
DX, AL
;lê a porta em AL
;lê em AL pela porta DX
;envia AL pela porta
;envia AL pela porta DX
A porta é um endereço de até 16 bits. Cada periférico tem seus próprios endereços de
entrada e saída que são documentados nos seus respectivos manuais técnicos.
3.11 - Interrupções
As interrupções podem ser encaradas como uma forma de chamar determinadas
rotinas que podem estar em posição variáveis da memória.
Normalmente a memória do computador do endereço 0 até o 03FFh é reservada para
guardar vetores de interrupção. Cada vetor de interrupção é formado por 4 bytes que guardam
o endereço de uma rotina. Este endereço é formado pelo segmento (2 bytes) e endereço (2
bytes).
Quando é pedida uma interrupção por algum dispositivo externo, é especificado um
número de 0 a 255. Este número é utilizado pelo microprocessador para indexar um dos
256 vetores que existem na memória. O microprocessador obtém um endereço no vetor
correspondente e passa o controle para a rotina. Ápós isto, o programa é desviado para a
rotina de atendimento da específica interrupção.
Tanto a BIOS quanto o DOS usam as interrupções como forma de acesso a suas
rotinas. Esta foi a melhor forma encontrada para que não existissem problemas de
desencontros com outros programas. No caso da BIOS, sabe-se que cada marca de
computador tem a sua própria BIOS com as suas próprias rotinas de tamanho variados. E
no caso do DOS, a cada vez que é carregado na memória pode estar em um endereço
diferente. Então como avisar aos programas quais são os endereços das diversas rotinas
do DOS e da BIOS, se a cada momento eles estão em posição diferentes da memória?
Fácil, basta usar as interrupções que nunca mudam de lugar. Por este motivo os endereços
das rotinas da BIOS e do DOS estão nos vetores de interrupção, e para acessá-los é
utilizada a instrução INT.
As interrupções também podem ser geradas por um dispositivo de hardware. Neste
caso, o funcionamento é idêntico, porém o processo é desencadeado pelo hardware que
fornece ao computador o número do vetor de interrupção desejado.
52
O indicador IE do registro da palavra de estado do processo (PSW) pode ser ligado
ou desligado para habilitar ou desabilitar as interrupções, através das instruções STI e CLI.
Quando uma interrupção é gerada por hardware, o microprocessador interrompe o
que está fazendo para executar a interrupção, passando o controle do programa à rotina
correspondente, se esta tiver maior prioridade.
Antes de passar o controle para a rotina da interrupção, o microprocessador guarda
no STACK POINTER o endereço atual sendo executado (registradores IP), e segmento
de código (registradores CS) e o indicador de estados (FLAG). A última instrução de uma
rotina de interrupção deve ser IRET e não RET. Isto porque IRET recupera os dados do
STACK e devolve o controle ao programa original.
Exemplos:
INT 021h
INT 010h
;chama interrupção 21h (DOS)
;chama interrupção 10H (BIOS)
53
Bibliografia:
SHIMIZU, T; BERLARDI, A. A - "Linguagem Assembly" - Editora Atlas, 1993
PIERE, E; SCHOLZE, R; - "Assembler - Aprenda como programar seu PC" - Editora
Érica, 1993.
INTEL CORP. ; ASM-86Macro Assembler Operating Instructions for 8086 – based
systems; ed.Inter Books, 1982.
TRIEBEL, WALTER A. ; AVTAR SINGH; The 8088 and 8086 microprocessors:
programming, interfacing, software, hardware and applications: including 80286, 80386,
80486 and pentium pr; ed.Prentice Hall, 1997, second edition.
BARRY, B. BREY; Programming the 80286, 80386, 80486 and pentium – based
personal computer; ed. MacMllan Pub Co.,1996.
54
Download