Escolar Documentos
Profissional Documentos
Cultura Documentos
Assembly Book PDF
Assembly Book PDF
LinguagemAssemblydos
MicroprocessadoresATMELAVR
por
GerhardSchmidt
http://www.avrasmtutorial.net
Dezembrode2003
Verso corrigida em Julho de 2006
Correes adicionais e atualizaes em Janeiro de 2008
Traduzido por Guilherme Groke ggroke@gmail.com
Avr-Asm-Tutorial
http://www.avr-asm-tutorial.net
Contedo
PorqueaprenderAssembler?......................................................................................................................1
Curtaefcil...........................................................................................................................................1
Veloz.....................................................................................................................................................1
Assemblerdefcilaprendizado..........................................................................................................1
AVRssoideaisparaseaprenderassembler........................................................................................1
Teste!.....................................................................................................................................................2
HardwareparaprogramaoemAssemblerAVR.....................................................................................3
AinterfaceISPdafamliadeprocessadoresAVR................................................................................3
ProgramadorparaaportaparaleladoPC..............................................................................................3
Placasexperimentais.............................................................................................................................4
PlacaexperimentalcomATtiny13...................................................................................................4
PlacaexperimentalcomumAT90S2313/ATmega2313..................................................................5
PlacasdeprogramaocomerciaisparaafamliaAVR........................................................................6
STK200.............................................................................................................................................6
STK500.............................................................................................................................................6
AVRDragon.....................................................................................................................................7
FerramentasparaprogramaoassemblyAVR........................................................................................8
Deumarquivotextoapalavrasdeinstruoparaamemriaflash......................................................8
Oeditor.............................................................................................................................................8
Oassembler......................................................................................................................................9
Programandooschips.........................................................................................................................10
Simulaonostudio............................................................................................................................11
Registrador...............................................................................................................................................13
Oqueumregistrador?......................................................................................................................13
Registradoresdiferentes......................................................................................................................14
Registradoresponteiros.......................................................................................................................14
Recomendaoparausodosregistradores..........................................................................................15
Portas........................................................................................................................................................17
OqueumaPorta?..............................................................................................................................17
DeatlhesdeportasrelevantesdoAVR................................................................................................18
Oregistradordestatuscomoaportamaisutilizada............................................................................18
Detalhesdasportas..............................................................................................................................19
SRAM......................................................................................................................................................20
UsandoSRAMemlinguagemassemblerAVR.................................................................................20
OqueSRAM?..................................................................................................................................20
ParaquepropsitospossousaraSRAM?...........................................................................................20
ComousaraSRAM?...........................................................................................................................20
UseofSRAMasstack.........................................................................................................................21
DefinindoSRAMcomopilha.........................................................................................................21
Usodapilha....................................................................................................................................22
Bugscomaoperaodepilhas.......................................................................................................22
SaltoseDesvios.......................................................................................................................................24
Controlandoaexecuoseqencialdeumprograma.........................................................................24
Oqueaconteceduranteumreset?..................................................................................................24
Execuolineardoprogramaedesvios..............................................................................................25
Temporizaoduranteaexecuodoprograma.................................................................................25
Macroseexecuodoprograma.........................................................................................................26
Subrotinas............................................................................................................................................26
Interrupeseaexecuodoprograma..............................................................................................28
Clculos....................................................................................................................................................30
Sistemasnumricosemassembler......................................................................................................30
Nmerospositivosinteiros(bytes,palavras,etc.)..........................................................................30
Nmeroscomsinal(inteiros)..........................................................................................................30
DgitosCodificadosemBinrio,BCD(BinaryCodedDigits)......................................................30
BCDscompactados.........................................................................................................................31
NmerosemformatoASCII...........................................................................................................31
Manipulaodebits.............................................................................................................................31
Avr-Asm-Tutorial
http://www.avr-asm-tutorial.net
Deslocaerotaciona..............................................................................................................................32
Somando,subtraindoecomparando....................................................................................................33
Conversodeformatosnumricos......................................................................................................35
Multiplicao.......................................................................................................................................35
Multiplicaodecimal....................................................................................................................35
Multiplicaobinria......................................................................................................................36
ProgramaemAssemblerAVR.......................................................................................................36
Binaryrotation................................................................................................................................37
Multiplicaonostudio..................................................................................................................37
Diviso.................................................................................................................................................39
Divisodecimal..............................................................................................................................39
Binarydivision...............................................................................................................................39
Passosdoprogramaduranteadiviso............................................................................................40
Divisonosimulador......................................................................................................................40
Conversonumrica............................................................................................................................43
Fraesdecimais.................................................................................................................................43
Converseslineares........................................................................................................................43
Exempl01:ConversorAD8bitparasadadecimalcompontofixo.............................................44
Exemplo2:ConversorADde10bitscomsadadecimalfixa.......................................................45
Anexo.......................................................................................................................................................46
Instruesordenadasporfuno.........................................................................................................46
ListadeDiretivaseInstruesemordemalfabtica...........................................................................48
DiretivasdeAssembleremordemalfabtica.................................................................................48
Instruesemordemalfabtica......................................................................................................48
DetalhesdasPortas..............................................................................................................................50
RegistradordeStatus,FlagsdoAcumulador.................................................................................50
Ponteirodepilha.............................................................................................................................51
SRAMecontroleexternodeinterrupes......................................................................................51
ControledeInterrupoExterno.....................................................................................................52
ControledoTimerdeInterrupo..................................................................................................52
Timer/Contador0............................................................................................................................53
Timer/Contador1............................................................................................................................54
WatchdogTimer.............................................................................................................................55
EEPROM........................................................................................................................................56
InterfacedePerifricosSeriais(SPI)..............................................................................................56
UART.............................................................................................................................................57
AnalogComparator........................................................................................................................58
PortasE/S.......................................................................................................................................59
Portas,ordemalfabtica......................................................................................................................59
Listadeabreviaes............................................................................................................................60
Avr-Asm-Tutorial
http://www.avr-asm-tutorial.net
necessrio entender a linguagem assembly, e.g., entender o que os compiladores de linguagens de alto
nvel produzem. Sem compreender a linguagem assembly, voc no ter chance de ir adiante nestes
casos.
Curta e fcil
Os comandos assembler so traduzidos um a um para serem comandos executados pela mquina. O
processador necessita apenas executar o que voc quer fazer e o necessrio para executar a tarefa.
Nenhum loop extra ou caractersticas desnecessrias poluem o cdigo. Se o espao para o seu programa
curto e limitado e voc ter que otimizar seu programa para caber na memria, assembler a escolha
nmero um. Programas mais curtos so mais fceis de depurar (debugar), cada passo faz sentido.
Veloz
Como apenas os passos necessrios so executados, os programas em assembly so to rpidos quanto
possvel. Aplicaes onde o tempo crtico, como medies de tempo que devam ter boa performance,
sem que haja um hardware de temporizao, devem ser escritas em assembler. Se voc tiver mais tempo
e no se importar que seu chip permanea 99% em um estado de espera (wait state) de operao, voc
pode escolher a linguagem que desejar.
Avr-Asm-Tutorial
http://www.avr-asm-tutorial.net
deixar na mo justamente no momento em que voc teve uma excelente idia sobre aquele bug.
Teste!
Seja paciente nos seus primeiros passos! Se voc tem familiaridade com outra linguagem (alto nvel):
esquea-a por enquanto. A maioria das caractersticas especiais de outras linguagens de computao
no fazem nenhum sentido em assembler.
As primeiras cinco instrues no so fceis de aprender, depois disso sua velocidade de aprendizado
aumentar rapidamente. Depois que voc escreveu as primeiras linhas: pegue o conjunto de instrues e
leia-o deitado em sua banheira, imaginando para que servem todas as outras instrues.
Aviso srio: No tente criar uma mega-mquina logo de incio. Isto no faz sentido algum em nenhuma
linguagem de programao, e apenas produz frustrao. Comece com pequenos exemplos tipo Ol
Mundo, e.g., ligando e desligando LEDs por algum tempo, e s ento comece a explorar as
caractersticas do hardware mais profundamente.
Recomendao: Comente suas subrotinas e armazene-as em um diretrio especial, se debugadas: voc
precisar delas em breve.
Sucesso!
Avr-Asm-Tutorial
http://www.avr-asm-tutorial.net
Avr-Asm-Tutorial
http://www.avr-asm-tutorial.net
(com pequenas mudanas no circuito). Se voc utilizar HC, no se esquea de conectar os pinos no
utilizados ao terra ou tenso de alimentao, caso contrrio os buffers podem produzir rudo capacitivo
pelo chaveamento.
Todo o algoritmo de programao necessrio feito pelo software ISP. Esteja ciente que esta interface
paralela no mais suportada pelo software Atmel Studio. Portanto, se voc desejar programar seu AVR
diretamente do studio, utilize programadores diferentes. A internet fornece diversas solues.
Se voc j tiver uma placa de programao, voc no precisar construir este programador, porque voc
encontrar a interface ISP em alguns pinos. Consulte o manual para localiz-los.
Placas experimentais
Voc provavelmente quer fazer seus primeiros programas com uma placa AVR feita em casa. Aqui
apresentamos duas verses:
uma mais complicada com um AT90S2313 ou ATmega2313, incluindo uma interface serial
RS232.
1. a fonte de alimentao com um retificador em ponte, que aplica de 9 a 15V a partir de uma fonte
AC ou DC, e um pequeno regulador de 5V.
Avr-Asm-Tutorial
http://www.avr-asm-tutorial.net
um gerador de clock a cristal (aqui com um cristal de 10 MHz, qualquer freqncia abaixo do
mximo especificado para o AT90S2313 funcionaro), os componentes necessrios para um reset
seguro durante o momento da partida da alimentao,
isto que voc precisa para iniciar. Conecte os outros perifricos e adicionais aos numerosos pinos livres
de E/S ao 2313.
O dispositivo de sada mais fcil pode ser um LED, conectado a um resistor tenso de alimentao.
Com isso, voc pode escrever o seu primeiro programa em assembler para acender e apagar o LED.
Se voc
Avr-Asm-Tutorial
http://www.avr-asm-tutorial.net
no precisar dos sinais de handshaking, ignore os pinos 14/16 e conecte RTS ao conector de 9
pinos via um resistor de 2,2k a +9V.
o cristal externo no necessrio, pois o ATmega possui um gerador de clock RC interno, basta
ignorar as conexes aos pinos 4 e 5,
se voc quiser usar um cristal externo no lugar do circuito RC interno, voc ter que programar os
fusveis do Atmega de acordo.
preo,
interface com o PC (de preferncia USB; menos conveniente ou durvel: RS232; requer software
adicional para programao: porta paralela do PC),
A seo a seguir descreve trs placas padro da ATMEL, a STK200, a STK500 e a Dragon. A seleo
baseada em minhas prprias experincias, e no uma recomendao.
STK200
A STK200 da ATMEL uma placa histrica. Se voc conseguir uma usada, voc ter
STK500
fcil obter a STK500 (e.g. direto da ATMEL). Esta placa tem o seguinte hardware:
Soquetes para programar a maioria dos tipos de AVR (e.g. Dispositivos de 14 pinos ou
encapsulamentos TQFP, exigindo algum hardware adicional),
programao serial e paralela em modo normal ou alta voltagem (programao HV traz de volta
vida dispositivos mesmo se o pino RESET foi programado para ser uma porta de entrada),
A principal desvantagem desta placa que, aps programar um dispositivo, vrias conexes tm que ser
feitas manualmente com os cabos que a acompanham.
A placa conectada ao PC usando uma porta serial (COMx). Se o seu laptop no possui uma interface
serial, voc pode utilizar um conversor USB-Serial comum com driver. Neste caso, o driver deve ser
ajustada para usar entre COM1 e COM2 e uma velocidade de 115k para ser detectada automaticamente
pelo software Studio.
Avr-Asm-Tutorial
http://www.avr-asm-tutorial.net
A programao realizada e controlada pelas verses recentes do AVR studio, que est disponvel
gratuitamente para download pela pgina da ATMEL aps o registro. Atualizaes na lista de dispositivos
e algoritmos de programao so fornecidos com as verses do Studio, ento o suporte para novos
dispositivos mais provvel do que com outras placas e softwares de programao.
Os experimentos podem comear com o AVR fornecido (verses antigas: AT90S8515, novas placas
incluem tipos diferentes). Este kit cobre todas as necessidades que o iniciante pode ter.
AVR Dragon
O AVR Dragon uma pequena placa. Ela possui uma interface USB, que alimenta a placa e a interface
ISP de 6 pinos. A interface ISP de 6 pinos acompanhada pela interface de programao HV de 20
pinos. A placa preparada para receber alguns soquetes, mas no possui soquetes para dispositivos
para gravao ou outro hardware.
O dragon suportado pelo software Studio e atualizado automaticamente.
Seu preo e design o torna um excelente presente para o amador de AVR.
Avr-Asm-Tutorial
http://www.avr-asm-tutorial.net
o editor,
o compilador,
o simulador.
Erros, que o assembler detecta depois, so reportados juntamente com o nmero da linha do
arquivo texto. Nmeros de linha so tambm uma poderosa inveno da era do computador com
respeito a discusses no seu cdigo com algum. Ento o seu editor deve ser capaz de mostrar o
nmero da linha. Infelizmente, quase todos os editores que uma poderosa empresa de software
fornece como parte dos seus sistemas operacionais, no possuem esta caracterstica.
Provavelmente o Windows 2019 reinvente esta caracterstica, e venda melhor entre os malucos
por assembler.
Erros de digitao so muito reduzidos, se estes erros forem marcados com cores. uma tima
caracteristica de um editor, destacar os componentes de uma linha em diferentes cores.
Reconhecimento inteligente dos erros facilita a escrita. Mas uma caracterstica que eu no sinto
falta.
Se seu editor permite a seleo de fonte, escolha uma fonte com espao fixo, como Courier. Os
cabealhos ficam melhor assim.
Seu editor deve ser capaz de reconhecer fim de linhas com qualquer combinao de caracteres
(carriage return, line feed, ambos) sem produzir telas inaceitveis. Outro item na lista de desejos
para o Windows 2013.
Se voc prefere matar moscas com canho, voc pode usar um software processador de texto poderodo
para escrever os seus programas em assembler. Pode parecer mais bonito, com cabealhos em fonte
grande e negritos, comentrios em cinza, avisos em vermelho, mudanas destacadas, e lembretes e todos em campos extra destacados. Algumas desvantagens, contudo: voc ter que converter o seu texto
em texto simples no final, perdendo todo o seu trabalho de design, e o seu arquivo texto resultante no
poder ter um nico byte de controle faltando. Caso contrrio, este nico byte gerar uma mensagem de
erro, quando voc tentar processar o texto. E lembre-se: Nmeros de linha estaro apenas corretos na
pgina do seu cdigo-fonte.
Avr-Asm-Tutorial
http://www.avr-asm-tutorial.net
O assembler
Agora temos um arquivo texto, com caracteres ASCII em branco. O prximo passo traduzir este cdigo
para forma orientada para mquina, que ser compreendida pelo chip AVR. Isto chamado de
assemblar, compilar, ou seja montar as palavras de comando corretas. Este programa l o arquivotexto e produz um tipo de sada chamada Assembler. O formato mais simples deste programa em linha
de comando, e quando chamado com o endereo do arquivo texto e alguns parmetros adicionais, inicia
a traduo dos comandos para um segundo arquivo-texto.
Se o seu editor permite a chamada de programas externos, uma tarefa fcil. Se no (outro item para a
lista de desejos para o editor do Windows 2010), mais conveniente escrever um arquivo batch (usando
outro editor). Este arquivo batch deve ter uma linha assim:
Path do Assembler\Assembler.exe -opes Path do Arquivo-Texto\Arquivotexto.asm
Ao clicar no boto para executar
programa externo, ou no arquivo batch,
inicia-se o compilador. Este software
reporta a traduo completa (na janela
menor), neste caso sem erros.
Se erros ocorrerem, eles so notificados,
juntamente com o seu tipo e o nmero da
linha onde ele ocorreu.
A compilao resultou em uma palavra
de cdigo que resultou da instruo
RJMP que utilizamos. Durante o
processo de assembler, nosso arquivo de
texto produziu outros quatro arquivos
(nem todos sero tratados aqui).
O primeiro destes novos quatro arquivos,
TEST.EEP, contm o que efetivamente
dever ser gravado na EEPROM do AVR.
Isto no muito interessante no nosso
Avr-Asm-Tutorial
10
http://www.avr-asm-tutorial.net
caso, porque no programamos nada para a EEPROM. O compilador, conseqentemente deletou este
arquivo quando terminou a montagem, pois era vazio.
O segundo arquivo, TEST.HEX, mais
relevante pois ele guarda os comandos que
sero posteriormente gravados no chip AVR.
Este arquivo se apresenta assim.
Os nmeros hexadecimais esto escritos em
um formato ASCII especial, juntamente com
as informaes de endereo e checksum
para cada linha. Este formato chamado
Intel-hex, muito antigo e remonta para os
primrdios da computao. Este formato
bem compreendido pelo software de programao.
O terceiro arquivo, TEST.OBJ, ser
explicado depois, este arquivo
necessrio para simular um AVR. Seu
formato hexadecimal e definido pela
ATMEL. Usando um editor hexa, seu
contedo assim. Ateno: Este
formato de arquivo no compatvel
com o software de programao, no
use este arquivo para programar um AVR (um erro muito comum no incio). Arquivos OBJ so produzidos
apenas por alguns assemblers ATMEL, no os espere de outros assemblers.
O quarto arquivo, TEST.LST, um arquivo texto. Abrao com um editor simples. Ser visto uma tela como a
mostrada aqui.
O programa com todos os seus endereos, comandos
e mensagens de erro so mostrados em uma forma
legvel. Voc precisar deste arquivo em alguns casos
para depurar erros.
Arquivos de lista so gerados apenas se a opo
especificada na linha de comando e se a diretiva
.NOLIST no suprimir a listagem.
Programando os chips
Para programar nosso cdigo hexa, como codificado no arquivo .HEX, no AVR, um software programador
necessrio. Este software l o arquivo .HEX e transfere o seu contedo, seja bit a bit (programao
serial), seja byte a byte (programao paralela) para a memria flash do AVR. Iniciamos o software de
programao e carregamos o arquivos hex que acabamos de gerar.
Em nosso exemplo, a tela
seria semelhante a esta.
Note: a janela apresentada
mostra a tela do ISP.exe,
um programa histrico no
mais
distribudo
pela
ATMEL. Outros softwares
programadores
so
semelhantes.
Este software gravar
nosso cdigo no local
designado no chip. H
algumas
precondies
necessrias para fazer
isto, e vrias razes
possveis para uma falta.
Consulte a ajuda do
software programador, se
ocorrerem problemas.
Hardware de programao e alternativas de software apropriadas para diferentes sistemas operacionais
esto disponveis na Internet. Como exemplo de um programador pela porta paralela ou serial, menciono
o PonyProg2000.
Avr-Asm-Tutorial
11
http://www.avr-asm-tutorial.net
Simulao no studio
s vezes, o cdigo escrito em assembly, mesmo que seja compilado sem erros, no faz exatamente o
que deveria depois de gravado no chip. Testar o software no chip pode ser complicado, especialmente se
voc tem um hardware mnimo e no tem oportunidade de visualizar resultados intermedirios ou sinais
de debug. Nestes casos, o pacote de software Studio da ATMEL fornece oportunidades perfeitas para
depurao. Testar o software ou somente partes possvel, e o cdigo do programa pode ser testado
passo a passo mostrando os resultados.
As imagens mostradas aqui so
tiradas da Verso 3 do Studio. A
Verso 4 atual visualmente
diferente, mas faz praticamente a
mesma coisa.
Primeiramente abriremos um arquivo
(menu
FILE
OPEN).
Demonstraremos utilizando o arquivo
tutorial test1.asm, pois nele h mais
alguns comandos e aes do que em
nosso programa de um nico
comando acima.
Abra o arquivo TEST1.OBJ, que resultou da compilao do TEST1.asm. Lhe perguntado que opes
voc gostaria de usar (se no voc
pode alterar atravs do menu
SIMULATOR OPTIONS). Selecione
as seguintes opes:
Dispositivo um AT90S8515,
Agoa iniciaremos a execuo do programa. Usaremos o modo de passo a passo (TRACE INTO ou F11).
Usando GO resultaria em uma execuo contnua e nada seria visto devido alta velocidade da
simulao.
Avr-Asm-Tutorial
12
http://www.avr-asm-tutorial.net
mostrado
em
cor
vermelha.
Podemos
alterar o valor de um
registrador a qualquer
momento para checar
o que acontece.
Agora o passo 3 foi executado, a sada direcionada ao registrador da porta B. Para mostrar, abrimos
uma nova janela de visualizao de E/S e selecionamos porta B. A imagem deve ser como a seguir.
O registrador de direo
de dados na janela de
visualizao de E/S na
porta B agora mostra o
novo valor. Os valores
podem
ser
alterados
manualmente,
se
desejado, pino a pino.
Os prximos dois passos
so simulados usando
F11. Eles no sero
mostrados aqui. Setando
as portas de sada para
nvel um com a instruo
LDI mp, 0xFF e OUT PORTB, mp resulta na seguinte figura na visualizao de E/S. Agora todos os bits
de sada da porta esto em nvel um, a visualizao de E/S mostra isso.
Este o nosso
pequeno passeio
atravs do mundo
do software de
simulao.
O
simulador capaz
de muito mais,
devendo portanto
ser utilizado extensivamente nos casos de erro de projeto. Visite os diferentes itens de menu, h muito
mais do que o mostrado aqui.
Avr-Asm-Tutorial
13
http://www.avr-asm-tutorial.net
Registrador
O que um registrador?
Registradores so locais especiais de armazenagem com capacidade de 8 bits e so da seguinte forma:
Bit 7
Bit 6
Bit 5
Bit 4
Bit 3
Bit 2
Bit 1
Bit 0
Note a numerao destes bits: o bit menos significativo inicia com zero (20 = 1).
Um registrador pode tanto armazenar nmeros de 0 a 255 (somente nmeros positivos), ou nmeros de 128 a +127 (nmero inteiro com o bit 7 indicando o sinal), ou o valor que representa um caractere ASCII
(e.g. 'A'), ou apenas oito bits que no tm nada a ver um com outro (e.g., para oita flags usados para
sinalizar oito decises sim/no diferentes).
A caracterstica especial dos registradores, comparada a outros locais de armazenagem, que
H 32 registradores em um AVR. Eles so originalmente chamados R0 a R31, mas voc pode escolher
nome-los com nomes que faam sentido em uma diretiva assembler. Um exemplo:
.DEF MeuRegistradorPreferido = R16
As diretivas de assembler sempre iniciam com um ponto na coluna 1 do texto. Instrues NUNCA iniciam
na coluna 1, eles sempre sero precedidos por um caractere vazio ou de tabulao!
Note que as diretivas de assembler como esta significam alguma coisa apenas para o compilador
assembler mas no produzem nenhum cdigo executvel no chip destino AVR. No lugar de utilizar o
registrador com nome R16, podemos utilizar nosso prprio nome MeuRegistradorPreferido, quando
quisermos usar R16 com algum comando. Ento escrevemos um pouco mais cada vez que queremos
utilizar este registrador, mas temos uma associao ao que pode ser o contedo deste registrador.
Usando a linha de comando
LDI
MeuRegistradorPreferido, 150
significa: carregue o nmero 150 imediatamente para o registrador R16, LoaD Immediate, carregar
imediato. Isto carrega um valor fixo ou uma constante neste registrador. Se observarmos a traduo deste
cdigo no programa escrito no AVR, veremos o seguinte:
000000 E906
O comando load, bem como o registrador destino (R16), assim como o valor da constante (150) parte
do valor hexa E906, mesmo que voc no os veja diretamente. No tenha medo: voc no tem que
lembrar esta codificao porque o compilador sabe traduzir tudo isto para o esquisito E906.
Dentro de um nico comando, dois diferentes registradores podem desempenhar um papel. O comando
mis fcil teste tipo o comando de cpia MOV. Ele copia o contedo de um registrador em outro. Assim:
.DEF MeuRegistradorPreferido = R16
.DEF OutroRegistrador = R15
LDI MeuRegistradorPreferido, 150
MOV OutroRegistrador, MeuRegistradorPreferido
As duas primeiras linhas deste programa monstruoso so diretivas que definem os novos nomes dos
registradores R16 e R15 para o compilador assembler. Novamente, estas linhas no produzem nenhum
cdigo para o AVR. As linhas de comando com LDI e MOV produzem o cdigo:
000000 E906
000001 2F01
Os comandos escrevem 150 no registrador R16 e copiam o seu contedo para o registrador destino R15.
NOTA IMPORTANTE:
O primeiro registrador sempre o registrador destino onde o resultado ser escrito!
(Isto infelizmente diferente da forma normalmente esperada ou de como falamos. uma conveno
simples que foi definida certa vez para confundir os iniciantes aprendendo assembler. por isso que
assembler to complicado.)
Avr-Asm-Tutorial
14
http://www.avr-asm-tutorial.net
Registradores diferentes
O iniciante pode querer escrever os comandos acima assim:
.DEF OutroRegistrador = R15
LDI OutroRegistrador, 150
E: voc falha. Apenas os registradores de R16 a R31 carregam uma constante imediamente com o
comando LDI, R0 a R15 no fazem isso. Esta restrio no muito interessante, mas no pde ser
evitada durante a construo do conjunto de comandos dos AVRs.
H uma exceo a esta regra: escrever Zero em um registrador. O comando
CLR MeuRegistradorPreferido
ANDI Rx,K ; Operao And dos bits do registrador Rx com os bits do valor constante K,
CBR Rx,M ; zera todos os bits no registrador Rx que esto em um dentro do valor de mscara
constante M.
SBCI Rx,K ; Subtrai a constante K e o valor atual da flag de carry (transporte) do registrador Rx e
armazena o resultado no registrador Rx,
SBR Rx,M ; Seta todos os bits no registrador Rx para um, que so um na mscara constante M,
Em todos estes comandos o registrador deve ser entre R16 e R31! Se voc planeja utilizar estes
comandos, voc deve selecionar um destes registradores para a operao. mais fcil de programar. H
uma razo adicional pela qual voc deve definir o nome dos registradores, porque voc pode facilmente
alterar a localizao dos registradores posteriormente.
Registradores ponteiros
Um papel muito especial desempenhado pelos pares de registradores R27:R26, R29:R28 e R31:R32.
Este papel to importante que estes pares tm nomes extra curtos em AVR assembler: X, Y e Z. Estes
nomes curtos so compreendidos pelo compilador. Estes pares so registradores ponteiros de 16 bits,
capazes de apontar endereos da SRAM com at 16 bits (X, Y ou Z) ou localizaes na memria do
programa (Z).
O byte menor do endereo de 16 bits est localizado no registrador inferior, o byte superior na registrador
superior. Ambas partes tm seu prprio nome, e.g., o byte mais alto de Z chamado de ZH (=R31), e o
byte mais baixo ZL (=R30). Estes nomes so definidos no arquivo de cabealho padro para os chips.
Dividir estes dois ponteiros de 16 bits em dois bytes diferentes feito da seguinte forma:
.EQU endereco = RAMEND ; RAMEND o endereo de 16 bits mais alto da SRAM (fim da memria)
LDI YH,HIGH(endereco) ; Seta o MSB
LDI YL,LOW(endereco) ; Set the LSB
Acessos via ponteiros so feitos com comandos especialmente designados. A leitura feita pelo
comando chamado LD (LoaD, carregar), e a escrita pelo comando chamado ST (STore, armazenar), e.g.
Com o ponteiro X:
Ponteiro
Seqncia
Exemplos
LD R1,X ou ST X,R1
X+
LD R1,X+ ou ST X+,R1
-X
Avr-Asm-Tutorial
15
http://www.avr-asm-tutorial.net
LDI ZH,HIGH(2*endereco)
LDI ZL,LOW(2*endereco)
LPM
Seguindo este comando, o endereo deve ser incrementado para apontar o prximo byte na memria do
programa. Como isto usado freqentemente, um comando de incremento de pointeiro foi definido para
fazer isto:
ADIW ZL,1
LPM
ADIW significa ADd Immediate Word, adicione palavra imediato, e um mximo de 63 pode ser adicionado
desta forma. Note que o compilador espera o mais baixo do par de registradores ZL como primeiro
parmetro. Isto pode causar confuso, pois a adio realizada como uma operao de 16 bits.
O comando complementar, subtrair um valor constante entre 0 e 63 de um ponteiro de 16 bits chamado
de SBIW (SuBtract Immediate Word, subtrair palavra imediato). ADIW e SBIW so possveis para os
pares de registradores X, Y e Z e para o par de registradores R25:R24, que no tm um nome extra e no
permitem acesso SRAM ou a localizaes da memria do programa. R25:R24 so ideais para
manipular valores de 16 bits.
Como inserir uma tabela de valores na memria do programa? Isto feito atravs das diretivas do
assembler .DB e .DW. Com elas voc pode inserir uma lista de bytes ou uma lista de palavras. Listas de
bytes organizados ficam assim:
.DB 123,45,67,89 ; uma lista de quatro bytes, escritos em formato decimal
.DB "Isto e um texto. " ; uma lista de caracteres byte, escritos como texto
Voc deve sempre colocar um nmero par de bytes em cada linha. Caso contrrio o compilador
adicionar um byte zero ao final, que pode ser indesejado.
Uma lista similar de valores ficaria assim:
.DW 12345,6789 ; uma lista de duas palavras
No lugar de constantes, voc pode tambm colocar labels (destinos para salto) nesta lista, como:
Label1:
[ ... aqui vo alguns comandos ... ]
Label2:
[ ... aqui vo mais alguns comandos ... ]
Tabela:
.DW Label1,Label2 ; uma lista de labels
Labels SEMPRE iniciam na coluna 1! Note que ler os labels com LPM primeiro traz o byte inferior da
palavra.
Uma aplicao muito especial para os ponteiros acessar os prprios registradores. Os registradores
esto localizados nos primeiros 32 bytes do espao do chip (do endereo 0x0000 a 0x001F). Este acesso
til se voc tiver que copiar o contedo dos registradores para a SRAM ou EEPROM ou ler estes
valores destes locais de volta para os registradores. O uso mais comum dos ponteiros para acessar
tabelas com valores fixos na memria do programa. Aqui est um exemplo, uma tabela com 10 diferentes
valores de 16 bits, onde o quinto valor da tabela lido para R25:R24:
MinhaTabela:
.DW 0x1234,0x2345,0x3456,0x4568,0x5678 ; Os valores da tabela
.DW 0x6789,0x789A,0x89AB,0x9ABC,0xABCD ; organizados em palavras
Read5: LDI ZH,HIGH(MinhaTabela*2) ; endereo do ponteiro Z
LDI ZL,LOW(MinhaTabela*2) ; multiplicado por 2 para acesso tabela
ADIW ZL,10 ; Aponta para o quinto valor da tabela
LPM ; L o byte menos significativo da memria do programa
MOV R24,R0 ; Copia o LSB para o registrador de 16 bits
ADIW ZL,1 ; Aponta para o MSB na memria do programa
LPM ; L o MSB da tabela de valores
MOV R25,R0 ; Copia MSB para o registrador de 16 bits.
Este apenas um exemplo, Voc pode calcular o endereo da tabela em Z a partir de algum valor de
entrada, levando os respectivos valores na tabela. As tabelas podem ser organizadas por byte ou
caracteres tambm.
Defina nomes para os registradores com a diretiva .DEF, nunca os use diretamente com o seus
nomes diretos Rx.
Se voc precisar acesso aos ponteiros, reserve R26 a R31 para este propsito.
Se precisar ler da memria do programa, e.g. Tabelas fixas, reserve Z (R31;R30) e R0 para isso.
Se voc pretende acessar bits dentro de certos registradores (flags), use R16 a R23 para isso.
Avr-Asm-Tutorial
16
http://www.avr-asm-tutorial.net
Portas
O que uma Porta?
As portas do AVR so caminhos entre a unidade central de processamento e os componentes externos
de hardware e software. A CPU se comunica com estes componentes, lendo deles ou escrevendo neles,
e.g. timers ou portas paralelas. A porta mais utilizada o registrador de flag, onde os resultados das
operaes anteriores so escritos e de onde as rvores de condies (decises) so lidas.
H 64 portas diferenentes, que no esto disponveis em todos tipos de AVR. Dependendo do espao de
armazenamento e outros hardwares internos, as portas podem estar disponveis e acessveis ou no. A
lista de portas que podem ser usadas est listada nos data sheets do processador.
As portas tm endereo fixo, pelo qual a CPU se comunica. O endereo independente do tipo de AVR.
Assim, por exemplo, o endereo da porta B sempre 0x18 (0x indica notao hexadecimal). Voc no
tem que lembrar destes endereos das portas, elas tm apelidos convenientes. Estes nomes so
definidos nos arquivos include (cabealhos) para os diferentes tipos de AVR, fornecidos pelo fabricante.
Os arquivos include tm uma linha definindo o endereo da porta B como a seguir:
.EQU PORTB, 0x18
Ento temos que lembrar apenas o nome da porta B, no sua localizao no espao de E/S do chip. O
arquivo de inclde 8515def.inc est envolvido atravs da diretiva do assembler
.INCLUDE "C:\Somewhere\8515def.inc"
O comando Out envia o contedo do meu registrador preferido, um bit Sleep-Enable chamado SE, para a
porta MCUCR e seta o AVR imediatamente para entrar em repouso, se houver uma instruo SLEEP
sendo executada. Como todos os outros bits do MCUCR foram setados pelas instrues acima, e o bit
SM (Sleep Mode) ficou zero, ocorrer um modo chamado meio-repouso: no haver execuo de
nenhum outro comando, mas o chip ainda reage a timers e outras interrupes de hardware. Estes
eventos externos interrompero o sono da CPU se eles acharem que devem notific-la.
Ler o contedo de uma porta possvel na maioria dos casos utilizando o comando IN. A sequncia
.DEF MeuRegistradorPreferido = R16
IN MeuRegistradorPreferido, MCUCR
l os dados da porta MCUCR para o registrador. Como muitas portas so usadas parcialmente ou no
utilizadas, normalmente os dados lidos so zeros.
Mais freqentemente do que ler todos os 8 bits de uma porta, deve-se reagir a certos status de uma porta.
Neste caso, no precisamos ler a porta toda e isolar o bit de interesse. Certos comandos permitem
executar comandos dependendo do estado de certo bit (veja a seo JUMP). Setar ou zerar certos bits
tambm possvel sem ter que ler e escrever os outros bits da porta. Os dois comandos so SBI (Set Bit
I/o, setar bit E/S) e CBI (Clear Bit I/o, zerar bit E/S). A execuo assim:
.EQU BitAtivo=0 ; O bit que ser mudado
SBI PortB, BitAtivo ; O bit ser setado para um
CBI PortB, BitAtivo ; O bit ser setado para zero
Estas duas instrues tm uma limitao: somente portas com endereo inferior a 0x20 podem ser
manipuladas desta forma.
Para programadores mais exticos: as portas podem ser acessadas utilizando comandos de acesso
SRAM, como ST e LD. Apenas some 0x20 ao endereo da porta (os primeiros 32 endereos so os
registradores) e acesse a porta desta forma. Vamos demonstrar aqui:
.DEF MeuRegistradorPreferido = R16
LDI ZH,HIGH(PORTB+32)
LDI ZL,LOW(PORTB+32)
Avr-Asm-Tutorial
17
http://www.avr-asm-tutorial.net
LD MeuRegistradorPreferido,Z
Isto faz sentido apenas em certos casos, mas possvel. por esta razo que o primeiro endereo da
SRAM sempre 0x60.
Nome da porta
Registrador da Porta
Acumulador
SREG
Registrador de Status
Pilha (stack)
SPL/SPH
Interrupo Externa
GIMSK
GIFR
TIMSK
TIFR
TCCR0
TCNT0
Timer/Contador 0
TCCR1A
TCCR1B
TCNT1
Timer/Contador 1
OCR1A
OCR1B
ICR1L/H
Timer Watchdog
WDTCR
EEPROM
EEAR
EEDR
EECR
SPCR
SPSR
SPDR
UDR
USR
UCR
UBRR
Comparador analgico
ACSR
Portas de E/S
PORTx
DDRx
PINx
Interrupo de Timer
Timer 0
Timer 1
SPI
UART
Avr-Asm-Tutorial
Bit
18
Clculo
Lgico
http://www.avr-asm-tutorial.net
Comparao
Bits
Rolagem
Outro
CLR
COM, NEG
CLR
CLR
SBIW
BCLR S,
BSET S,
CLS, SES
NEG
BCLR T,
BSET T,
BST, CLT,
SET
BCLR I,
BSET I,
CLI, SEI
RETI
ASR, LSL,
LSR, ROL,
ROR
Avr-Asm-Tutorial
19
http://www.avr-asm-tutorial.net
SRAM
Usando SRAM em linguagem assembler AVR
Praticamente todos os MCUs AVR tipo AT90S tm RAM esttica (SRAM, Static RAM) (alguns no).
Somente compiladores muito simples evitam a utilizao deste espao da memria, colocando tudo nos
registradores. Se os seus registradores acabarem, voc dever ser capaz de programar a SRAM para
obter mais espao.
O que SRAM?
SRAM so memrias que no so diretamente acessveis da unidade de processamento central (Unidade
Aritmtica e Lgica ALU
(Arithmetic and Logical Unit),
algumas vezes chamada de
acumulador),
como
os
registradores o so. Para
acessar estas localidades de
memria, voc normalmente
usa um registrador como
armazm intermedirio. No
exemplo a seguir, um valor na
SRAM ser copiado para o
registrador
R2
(primeiro
comando),
um
clculo
utilizando o valor de R3 feito
e o resultado escrito em R3
(comando2). Depois disso, o
valor escrito de volta na SRAM (comando 3, no mostrado aqui).
evidente que operaes com valores armazenados na SRAM so mais lentas do que aquelas utilizando
apenas os registradores. Por outro lado: o menor AVR tem 128 bytes de SRAM disponvel, muito mais do
que os 32 registradores podem guardar.
Os tipos mais recentes do que AT90S8515 oferecem a possibilidade de conectar RAM externa,
expandindo a interna de 512 bytes. Do ponto de vista do assembler, a SRAM externa acessada da
mesma forma que a interna. No existe nenhum comando extra para SRAM externa.
o contedo da SRAM no endereo 0x0060 copiado para o registrador. Este o acesso direto atravs do
endereo definido pelo programador.
Nomes simblicos devem ser evitados para evitar manipular endereos fixos, pois requerem muito
trabalho se voc depois quiser alterar a estrutura da SRAM. Estes nomes so mais fceis de lembrar do
que os nmeros hexa, ento voc pode nomear um endereo da seguinte forma:
Avr-Asm-Tutorial
20
http://www.avr-asm-tutorial.net
Sim, fica mais longo, mas mais fcil de lembrar. Use o nome que voc achar conveniente.
Outro tipo de acesso SRAM com o uso de ponteiros. Voc precisa de dois registradores para este
propsito, para acomodar o endereo em 16 bits. Como aprendemos na diviso dos ponteiros, os
registradores ponteiros so os pares X (XH:XL, R27:R26), Y (YH:YL, R29:R28) e Z (ZH:ZL, R31:R30).
Eles permite acesso localizao que apontam diretamente (e.g., com ST X, R1), antes da
decrementao do endereo por um (e.g., ST -X, R1) ou antes do incremento deste endereo (e.g., ST
X+, R1). Um acesso completo a trs endereos em seguida ficaria ento da seguinte forma:
.EQU MeuEnderecoPreferido= 0x0060
.DEF MeuRegistradorPreferido = R1
.DEF OutroRegistrador= R2
.DEF MaisUmRegistrador = R3
LDI XH, HIGH(MeuEnderecoPreferido)
LDI XL, LOW(MeuEnderecoPreferido)
LD MeuRegistradorPreferido, X+
LD OutroRegistrador, X+
LD MaisUmRegistrador, X
Fceis de operar, estes ponteiros. E to fcil quanto em outras linguagens diferentes do assembler, que
dizem ser fcil de aprender.
A terceira construo um pouco mais extica e somente utilizada por programadores experientes.
Vamos assumir que precisamos acessar trs localizaes da SRAM com freqncia. Vamos tambm
assumir que temos um par de registradores ponteiros sobrando, ento podemos utiliz-lo exclusivamente
para nosso propsito. Se usssemos as instrues ST/LD, teramos que alterar o ponteiro a cada vez que
precisssemos acessar outra localizao. No muito conveniente.
Para evitar isso, e confundir o iniciante, o acesso com offset foi inventado. Durante este acesso, o valor do
registrador no alterado. O endereo calculado adicionando temporariamente um offset fixo. No
exemplo acima, o acesso localizao 0x0062 ficaria assim. Primeiro, o ponteiro setado para nossa
localizao central 0x0060:
.EQU MeuEnderecoPreferido = 0x0060
.DEF MeuRegistradorPreferido = R1
LDI YH, HIGH(MeuEnderecoPreferido)
LDI YL, LOW(MeuEnderecoPreferido)
Note que 2 no realmente adicionado a Y, apenas temporariamente. Para confundi-lo mais, isto pode
ser feito apenas com os pares de registradores Y e Z, no com o ponteiro X!
A instruo correspondente para ler a SRAM com um offset
LDD MeuRegistradorPreferido, Y+2
tambm possvel.
Esta a SRAM, mas espere: o uso mais interessante como pilha ainda deve ser aprendido.
O valor RAMEND (que indica o endereo final da memria) , obviamente, especfico para o tipo de
Avr-Asm-Tutorial
21
http://www.avr-asm-tutorial.net
progrssador. Ele definido no arquivo INCLUDE para o tipo de processador.O arquivo 8515def.inc tem a
linha:
.equ RAMEND =$25F ; Last On-Chip SRAM Location (n.t.: ltima localizao da SRAM no chip)
Uso da pilha
Usar a pilha fcil. O contedo dos registradores so empurrados na pilha assim:
PUSH MeuRegistradorPreferido ; Coloca aquele valor no topo da pilha
Para onde o valor vai, no nos interessa. O ponteiro de pilha foi decrementado aps colocarmos este
valor, e no temos que nos preocupar. Se precisarmos deste contedo de volta, simplesmente usamos a
seguinte instruo:
POP MeuRegistradorPreferido ; L o valor de volta
Com POP simplesmente pegamos o ltimo valor colocado no topo da pilha. Empurrar e pegar
registradores faz sentido, se
Se nenhuma destas condies se verificarem, o uso da pilha para guardar registradores intil e apenas
desperdia tempo do processador.
Faz mais sentido usar a pilha em subrotinas, onde voc tem que retornar localizao do programa que
chamou a rotina. Neste caso, o cdigo que chama a subrotina deve guardar o endereo de retorno (o
valor atual do contador de programa, PC, program counter) na pilha e salta para a subrotina. Aps a sua
execuo, a subrotina pega o endereo de retorno da pilha e carrega no contador de programa. A
execuo do programa ento continua exatamente uma instruo aps a instruo de chamada:
RCALL AlgumLugar ; Salta para o label AlgumLugar:
[...] aqui continuamos o programa
Durante a execuo da instruo RCALL, o contador de programa (PC) j incrementado, com 16 bits,
colocado na pilha usando dois pushes. Quando a instruo RET executada, o contedo anterior do
contador de programa recarregado usando dois pops e a execuo continua.
Voc no precisa se preocupar sobre o endereo da pilha, ou onde o contador est gravado. O endereo
gerado automaticamente. Mesmo se voc chamar uma subrotina dentro de uma subrotina, a funo da
pilha perfeita. Os dois endereos so colocados no topo da pilha, a subrotina dentro da primeira remove
o primeiro endereo, e a subrotina de chamada remove o segundo. Enquanto haja SRAM suficiente, tudo
funciona.
A utilizao de interrupes de hardware no possvel sem a pilha. A interrupo pra a execuo
normal do programa, onde quer que ele esteja. Aps a execuo do servio como reao quela
interrupo, a execuo deve retornar localizao anterior, antes da interrupo. Isto no seria possvel
se a pilha no fosse capaz de armazenar o endereo de retorno.
As enormes vantagens de se ter uma pilha para interrupes so as razes de mesmo o menor dos AVRs
que no tenham SRAM, tenham ao menos uma pequena pilha de hardware.
Avr-Asm-Tutorial
22
http://www.avr-asm-tutorial.net
Outra possibilidade de ter bug esquecer de fazer o pop em um valor armazenado anteriormente, ou
fazer pop sem fazer push antes.
Em alguns poucos causos, a pilha estoura para abaixo do primeiro endereo da SRAM. Isto ocorre no
caso de uma chamada recursiva infinita. Aps alcanar o endereo mais baixo da SRAM, os prximos
pushes escrevem nas portas (0x005F at 0x0020), e ento os registradores (0x001F a 0x0000). Coisas
engraadas e imprevisveis podem ocorrer com o chip, se isto ocorrer. Evite este bug, ele pode destruir o
seu hardware!
Avr-Asm-Tutorial
23
http://www.avr-asm-tutorial.net
Saltos e Desvios
Agora discutiremos todos os comandos que controlam a execuo seqencial de um programa, iniciando
com a seqncia inicial de partida do processador, continuando com saltos, interrupes, etc.
Se o contador Watchdog alcana a sua contagem mxima, um reset iniciado. O timer witchdog
um temporizador interno que deve ser resetado de tempos em tempos pelo programa, caso
contrrio ele reinicia o processador.
Voc pode chamar o reset fazendo um salto direto a este endereo (veja a seo de saltos abaixo).
O terceiro caso no um reset real, pois o reincio de registradores e valores de porta a valores
conhecidos, no executado. Portanto, esquea-o por enquanto.
A segunda opo, o reset watchdog, deve ser habilitado pelo programa. Se estiver desabilitado por
padro, a habilitao requer escrever comandos na porta do watchdog. Zerar o contador watchdog requer
a execuo do comando
WDR
A primeira diretiva diz ao compilador que a sada deve ser para a seo de cdigos. Tudo que se segue
ser traduzido como cdigo, e ser escrito memria de programa do processador. Tambm possvel
direcionar a sada para a seo EEPROM do chip, onde voc pode escrever bytes e palavras.
.ESEG
Diferente do contedo para EEPROM, que realmente gravado no EEPROM durante a programao, o
segmento DSEG no programado no chip. utilizado somente para clculo dos labels durante o
processo de compilao.
A diretiva ORG indica a origem e manipula os endereos dentro do segmento de cdigo, onde as palavras
montadas so gravadas. Como nosso programa sempre inicia a 0x0000, as diretivas CSEG/ORG so
triviais, voc poder ignor-las sem obter um erro. Poderamos comear, por exemplo, a 0x0100, mas no
faz sentido, visto que o processador inicia a execuo em 0000. Se voc quiser colocar uma tabela
exatamente em uma certa localizao no segmento de cdigo, voc pode usar ORG. Se voc quiser
demarcar onde realmente comea o seu programa, aps definir outras coisas com diretivas .DEF e .EQU,
use a seqncia CSEG/ORG para sua orientao, mesmo sabendo que no necessrio utiliz-las.
Como a primeira palavra de cdigo sempre inicia no endereo zero, esta localizao tambm chamada
de vetor de reset. Procedendo os prximos endereos, 0x0001, 0x0002 etc., temos os vetores de
interrupo. Estas so as posies para onde a execuo salta se uma interrupo externa ou interna foi
habilitada e ocorre. Estas posies chamadas vetores so especficas para cada tipo de processador, e
dependem do hardware interno disponvel (veja abaixo). Os comandos para reagir s interrupes devem
ser colocadas nas localizaes de vetor apropriados. Se voc usar interrupes, o primeiro cdigo, no
vetor de reset, deve ser um comando de salto (jump), para saltar por cima dos outros vetores. Cada vetor
de interrupo deve possuir um comando de salto para a respectiva rotina para tratar a interrupo. A
tpica seqncia do programa no incio como se segue:
Avr-Asm-Tutorial
24
http://www.avr-asm-tutorial.net
.CSEG
.ORG 0000
RJMP Inicio
RJMP TrataInterrupcao1
[...] aqui colocamos os outros comandos no vetor de interrupo
[...] e aqui um bom lugar para colocar as prprias rotinas de tratamento da interrupo
Inicio: ; aqui que o programa inicia
[...] Aqui colocamos o programa principal
O comando RJMP resulta em um salto para o label Inicio:, localizado algumas linhas abaixo. Lembre-se,
labels sempre iniciam na coluna 1 do cdigo fonte e terminam com um :. Labels que no atendam esta
condies no so interpretadas corretamente pelo compilador. Labels faltantes resultam em uma
mensagem de erro (Label indefinido, Undefined Label), e a compilao interrompida.
s isso. A condio oposta a BRNE BREQ ou Branch EQual, desviar se for igual.
Para saber quais os bits de status, tambm chamados de flags do processador so alterados durante a
execuo de um comando, olhe a Lista de Instrues. Da mesma forma que o bit Zero, voc pode usar
outros bits como:
BRCC label/BRCS label; Carry-flag 0 (BRCC) ou 1 (BRCS)
BRSH label; Igual ou maior
BRLO label; Menor
BRMI label; Menos
BRPL label; Mais
BRGE label; Maior ou igual (com bit de sinal)
BRLT label; Smaller (with sign bit)
BRHC label/BRHS label; Flag de meio-overflow 0 ou 1
BRTC label/BRTS label; T-Bit 0 ou 1
BRVC label/BRVS label; Flag de complemento de dois 0 ou 1
BRIE label/BRID label; Interrupes habilitadas ou desabilitadas
para reagir a diferentes condies. Desvios sempre ocorrem quando as condies so cumpridas. No
tenha medo, a maioria destes comandos raramente usada. Para o iniciante, apenas Zero e Carry so
importantes.
Avr-Asm-Tutorial
25
http://www.avr-asm-tutorial.net
Esta instruo no faz nada alm de desperdiar tempo do processador. A 4 MHz, precisamos de 4
instrues desta para desperdiar 1 s. No h outros significados ocultos na instruo NOP. Para um
gerador de sinal de 1 kHz no precisamos adicionar 4000 instrues destas em nosso cdigo fonte, mas
utilizamos um contador por software e algumas instrues de desvio. Com isso, construmos um elo que
executado por um certo nmero de vezes, provocando retardo. Um contador por ser um registrador de 8
bits que decrementado pela instruo DEC, e.g. Desta forma:
CLR R1
Conta:
DEC R1
BRNE Conta
Contagem em 16 bit tambm pode ser usada para um retardo exato, assim:
LDI ZH,HIGH(65535)
LDI ZL,LOW(65535)
Conta:
SBIW ZL,1
BRNE Conta
Se voc usar mais registradores para construir contadores compostos, voc pode conseguir qualquer
retardo. E este absolutamente exato, mesmo sem um hardware de temporizao.
A definio da macro no produz ainda nenhum cdigo, silenciosa. O cdigo produzido quando voc
chama a macro pelo seu nome:
[...] em algum lugar no cdigo fonte
Retardo1
[...] o cdigo vai aqui
Isto resulta em quatro instrues NOP inseridas no cdigo nesta localizao. Um Retardo1 adicional
insere mais 4 instrues NOP.
Ao chamar um macro por seu nome voc pode adicionar alguns parmetros para manipular o cdigo
produzido. Mais isto mais que um iniciante precisa saber sobre macros.
Se seu macro tem longas sequncias de cdigo, ou se voc est com pouco espao de armazenamento,
deve evitar o uso de macros e usar subrotinas no lugar.
Subrotinas
Ao contrrio das macros, uma subrotina economiza espao de armazenamento. A seqncia respectiva
apenas armazenada uma vez no cdigo e chamada de qualquer parte. Para assegurar a execuo
continuada da sequencia, voc deve retornar ao cdigo que chamou a subrotina. Para um retardo de 10
ciclos voc precisa escrever esta subrotina:
Retardo10:
NOP
NOP
NOP
RET
Subrotinas sempre iniciam com um label, caso contrrio voc no seria capaz de saltar para elas, no
nosso caso, Retardo10:. Trs NOPs seguem a instruo RET. Se voc contar os ciclos necessrios,
voc descobrir que so 7 (3 para os NOPs, 4 para o RET). Os 3 que faltam esto contidos nesta rotina:
[...] algum lugar do cdigo fonte:
RCALL Retardo10
Avr-Asm-Tutorial
26
http://www.avr-asm-tutorial.net
RCALL uma chamada relativa. A chamada codificada como um salto relativo, a distncia relativa da
rotina de chamada para a subrotina calculada pelo compilador. A instruo RET volta rotina de
chamada. Note que antes de voc usar chamadas de subrotina, voc deve setar o ponteiro de pilha (veja
Pilha), porque o endereo para retorno deve ser colocado na pilha pela instruo RCALL.
Se voc quiser saltar diretamente a algum outro lugar no cdigo, voc tem que usar a instruo jump:
[...] em algum lugar do cdigo fonte
RJMP Retardo10
Retorno:
[...] continuando com o cdigo fonte
A rotina para onde voc pulou no pode usar o comando RET neste caso. Para voltar localizao de
onde voc chamou, requer outro label e que a rotina que voc chamou, salte de volta para este label. Este
tipo de salto no chamado de subrotina, porque voc no pode cham-la de diferentes localidades do
cdigo.
RCALL e RJMP so desvios incondicionais. Para pular para uma localidade, dependendo de alguma
condio, voc ter que combinar com instrues de desvio. A chamada condicional de uma subrotina
pode ser feita com os seguintes comandos. Se voc quiser chamar uma subrotina dependendo de um
certo bit em um registrador, use a sequncia seguinte:
SBRC R1,7 ; Pule a prxima instruo se o bit 7 for 0
RCALL OutroLabel ; Chame a subrotina
SBRC quer dizer Pule a prxima instruo se o Bit 7 no Registrador R1 for zero, skip next instruction if Bit
7 in Register R1 is Clear). A instruo RCALL para o OutroLabel: somente ser executada se o bit 7 no
registrador R1 for 1, pois a prxima instruo ser pulada se for 0. Se voc desejar chamar a subrotina
caso o bit seja 0, voc pode utilizar a instruo correspondente SBRS. A instruo que se segue a SBRS/
SBRC pode ser de um ou dois bytes, o processador sabe quanto ele tem que pular. Note que os tempos
de execuo so diferentes neste caso. Para pular sobre mais de uma instruo, estes comandos no
podem ser usados.
Se voc tiver que pular uma instruo se dois registradores tiverem o mesmo valor, voc pode usar a
instruo extica
CPSE R1,R2 ; Compara R1 e R2, pula se forem iguais
RCALL AlgumaSubrotina ; Chama alguma subrotina
um comando raramente utilizado, esquea-o no comeo. Se voc quiser pular a instruo seguinte
dependendo de um certo bit em uma porta, use as instrues SBIC e SBIS. Elas querem dizer Pule se o
Bit no espao E/S estiver zero (ou Setado), Skip if the Bit in I/o space is Clear (ou Set), assim:
SBIC PINB,0 ; Pule se o Bit 0 na porta B for 0
RJMP DestinoA ; Pule para o label DestinoA
A instruo RJMP ser executada apenas se o bit 0 na porta B for 1. de alguma forma confuso para o
iniciante. O acesso aos bits da porta limitado metade inferior, as 32 portas superiores no podem ser
usadas aqui.
Agora, outra aplicao extica para o expert. Pule esta parte se voc for iniciante. Imagine que temos 4
chaves, uma para cada bit, conectados porta B. Dependendo do estado destes 4 vits, gostaramos de
pular para 16 diferentes localizaes no cdigo. Agora podemos ler a porta e usar diversas instrues de
desvio para descobrir para onde teremos que pular hoje. Como alternativa, voc pode escrever uma
tabela contendo os 16 endereos, assim:
MinhaTabela:
RJMP Routine1
RJMP Routine2
[...]
RJMP Routine16
Agora podemos saltar s localidades na tabela, da mesma forma que chamamos uma subrotina:
ICALL
Avr-Asm-Tutorial
27
http://www.avr-asm-tutorial.net
Se a condio de interrupo ocorre, e.g. uma mudana no bit da porta, o processador coloca o contador
de programa atual na pilha (que deve ser habilitada primeiro! Veja a inicializao do ponteiro de pilha na
seo Pilha da descrio da SRAM). Sem isso, o processador no seria capaz de retornar ao ponto onde
estava quando ocorreu a interrupo (o que pode ocorrer a qualquer momento em qualquer lugar da
execuo do programa). Depois, o processamento salta para a localizao predefinida, o vetor de
interrupo, e a executa as instrues.
Normalmente a instruo um JUMP para a rotina de tratamento da interrupo, localizado em algum
lugar do cdigo. A localizao do vetor de interrupo especfico do processador, e dependente dos
componentes de hardware e da condio que levou interrupo. Quanto mais componentes de
hardware e mais condies, mais vetores. Os diferentes vetores para alguns tipos de AVR esto listados
na tabela a seguir (o primeiro vetor no uma interrupo, mas sim o vetor de reset, que no faz
operao com a pilha!)
Nome
Endereo do vetor de
interrupo
Disparado por
2313
2323
8515
RESET
0000
0000
0000
INT0
0001
0001
0001
INT1
0002
0002
TIMER1CAPT
0003
0003
TIMER1COMPA
0004
TIMER1 COMPB
0005
TIMER1 COMP1
0004
TIMER1 OVF
0005
0006
TIMER0 OVF
0006
0002
0007
SPI STC
0008
UART TX
0007
0009
UART UDRE
0008
000A
UART TX
0009
000B
000C
Comparador Analgico
ANA_COMP
Note que a capacidade de reagir a eventos muito diferente para os diferentes tipos. Os endereos so
sequenciais, mas no idnticos para diferentes tipo. Consulte o datasheet para cada tipo de AVR.
Quanto mais alto um vetor na lista, maior sua prioridade. Se dois ou mais componentes tm uma
condio de interrupo ao mesmo tempo, o vetor com o menor endereo vence. A interrupo inferior
tem que esperar at que a primeira tenha sido tratada. Para evitar que as interrupes inferiores
interrompam a execuo do tratamento de uma interrupo superior, a primeira interrupo desabilita a
flag I (interrupo) do processador. A rotina deve reabilitar esta flag aps o trmino do trabalho.
Para reabilitar o bit de status I h duas formas. O tratamento da interrupo para terminar com o comando
RETI
Este comando retorna o bit I depois do contador de programa ter sido restabelecido com o valor do
endereo de retorno.
Avr-Asm-Tutorial
28
http://www.avr-asm-tutorial.net
Isto no faz a mesma coisa do RETI, pois interrupes subsequentes estaro habilitadas antes do
contador de programa ser recarregado com o endereo de retorno. Se outra interrupo estiver pendente,
sua execuao j inicia antes que o endereo de retorno seja removido da pilha. Dois ou mais endereos
de retorno permanecem na pilha. Isto no causa bug imediato, mas um risco desnecessrio. Portanto,
use a instruo RETI para evitar fluxo desnecessrio na pilha.
Um vetor de interrupo tem capacidade para apenas uma instruo de salto para a rotina de servio. Se
certa interrupo no usada ou indefinida, colocamos simplesmente uma instruo RETI ali, no caso de
uma falsa interrupo ocorrer. o caso da execuo do servio respectivo no resetar automaticamente a
condio de interrupo do perifrico. Neste caso, um simples RETI causaria um loop contnuo de resets.
Este o caso com algumas interrupes da UART.
Quando uma interrupo est em tratamento, a execuo de outras interrupes de menor prioridade
bloqueada. Por este motivo, todas as rotinas de tratamento de interrupo devem ser to curtas quanto
possvel. Se voc precisar de uma longa rotina de tratamento da interrupo, use um dos seguintes
mtodos. O primeiro permitir interrupes com SEI dentro da rotina de tratamento, enquanto voc
executa as tarefas mais urgentes. No muito inteligente. Mais conveniente seria executar as tarefas
urgentes, setar uma flag em algum lugar em um registrador para as reaes mais lentas, e retornar da
interrupo imediatamente.
Uma regra muito importante para o tratamento de interrupes : A primeira instruo sempre tem que
guardar o registrador de status na pilha, antes de voc utilizar instrues que possam alterar as flags do
registrador de status. O programa principal, que foi interrompido, pode precisar utilizar uma flag que
estava setada, para tomar alguma deciso, e a interrupo alterou justamente esta flag. Coisas
engraadas podem acontecer de tempos em tempos. A ltima instruo antes de RETI dever ser
recuperar o contedo do registrador de status da pilha e restaurar seu contedo original.
Pela mesma razo, todos os registradores usados no tratamento da interrupo devem ser reservados
exclusivamente para aquele propsito, ou salvos na pilha e restaurados ao fim da rotina. Nunca altere o
contedo de um registrador dentro de uma tratamento de interrupo que for usado em outras partes do
programa, sem restaur-lo antes.
Devido a todas estas necessidades, um exemplo mais sofisticado de tratamento de interrupo,
mostrado aqui.
.CSEG ; Segmento de cdigo comea aqui
.ORG 0000 ; Endereo zero
RJMP Inicia; O vetor de reset no endereo 0
RJMP ServicoInt ; 0001: Primeiro vetor de interrupo, tratamento de INT0
[...] aqui outros vetores
Inicia: ; Aqui o programa principal inicia
[...] aqui h espao suficiente para definir pilha e outras coisas
ServicoInt: ; Aqui iniciamos a rotina de tratamento da interrupo
PUSH R16 ; salvamos um registrador na pilha
IN R16,SREG ; lemos o registrador de status (n.t. e colocamos em R16)
PUSH R16 ; e o colocamos na pilha
[...] Aqui a rotina de tratamento da interrupo faz alguma coisa e usa R16
POP R16 ; obtemos o registrador de flags de volta da pilha (n.t. Para R16)
OUT SREG,R16 ; e o restauramos na flag de status
POP R16 ; obtemos o contedo anterior de R16 na pilha
RETI ; e retornamos da interrupo
Parece um pouco complicado, mas um pr-requisito para usar interrupes sem produzir srios bugs.
Ignore PUSH R16 e POP R16 se voc pode reservar este registrador exclusivamente para uso no
tratamento das interrupes. Como o tratamento da interrupo no pode ser interrompido (a no ser que
voc permita, no cdigo), todas as rotinas de tratamento de interrupo podem usar o mesmo registrador.
isso para o iniciante. H mais algumas coisas com interrupes, mas o suficiente para comear e no
o confundir.
Avr-Asm-Tutorial
29
http://www.avr-asm-tutorial.net
Clculos
Agora discutiremos os comandos necessrios para calcular em linguagem assembler AVR. Isto inclui
sistemas numricos, setar e zerar bits, deslocar e rotacionar, e adicionar/subtrair/comparar e converso
de formatos numricos.
BCDs compactados,
dw0 a dw3 esto em ordem nos registradores. Se quisermos iniciar esta palavra dupla no incio de uma
aplicao, devemos fazer da seguinte forma:
.EQU dwi = 4000000 ; definimos a constante
LDI dw0,LOW(dwi) ; Os 8 bits mais baixos em R16
LDI dw1,BYTE2(dwi) ; bits 8 .. 15 em R17
LDI dw2,BYTE3(dwi) ; bits 16 .. 23 em R18
LDI dw3,BYTE4(dwi) ; bits 24 .. 31 em R19
Ento, convertemos este nmero decimal, chamado dwi, em suas pores binrias e as quebramos em
quatro pacotes de bytes. Agora voc pode fazer clculos com esta palavra dupla.
Avr-Asm-Tutorial
Valor do bit
30
http://www.avr-asm-tutorial.net
128
64
32
16
R16, Dgito 1 =2
R17, Dgito 2 = 5
R18, Dgito 3 = 0
Voc pode calcular com estes nmeros, mas um pouco mais complicado em assembler do que calcular
com valores binrios. A vantagem dste formato que voc pode manipular nmeros to grandes quanto
voc quiser, desde que haja espao suficiente. Os clculos so to precisos quanto voc quiser (se voc
programa AVRs para aplicaes de banco), e voc pode convert-los facilmente para cordes (strings) de
caracteres.
BCDs compactados
Se voc comprimir dois dgitos decimais dentro de um byte, voc no perder tanto espao de
armazenagem. Este mtodo chamado de dgitos codificados em binrio compactados (packed binary
coded digits). As duas partes de um byte so chamados de nibble superior e inferior. O nibble superior
normalmente guardo o dgito mais significativo, o que tem vantagens no clculo (instrues especiais na
linguagem assembler do AVR). O nmero decimal 250 ento ficaria assim formatado em BCD
compactado:
Byte
Dgitos
Valor
4&3
02
2&1
50
Para fazer isto corretamente, voc pode usar a notao binria (0b...) ou a notao hexadecimal (0x...)
para colocar os bits na posio correta dentro dos nibbles.
O clculo com BCDs compactados um pouco mais complicado comparado com a forma binria. Para
converter em cordes de caracteres, to fcil quanto com BCDs. O comprimento dos nmeros e a
preciso dos clculos limitado somente pelo espao de armazenagem.
Manipulao de bits
Para converter um dgito codificado em BCD para sua representao em ASCII, temos que setar os bits 4
e 5 para um. Em outras palavras, precisamos fazer uma operao OR no BCD com um valor hexa de
0x30. Em assembler isto feito da seguinte forma:
Avr-Asm-Tutorial
31
http://www.avr-asm-tutorial.net
ORI R16,0x30
Se temos um registrador que j tem o valor hexa 0x30, podemos fazer OR com este registrador para
convert-lo para BCD:
OR R1,R2
isola os quatro bits mais baixos (= o nibble inferior). Note que ORI e ANDI so possveis apenas com
registradores acima de R15. Se precisar utiliz-los, use um dos registradores entre R16 e R31!
Se o valor hexa 0x0F j estiver no registrador R2, voc pode fazer AND o caractere ASCII com este
registrador:
AND R1,R2
As outras instrues para manipular bits em um registrador so tambem limitados para os registradores
acima de R15. Eles podem ser formulados assim:
SBR R16,0b00110000 ; Seta bits 4 e 5 para um
CBR R16,0b00110000 ; zera bits 4 e 5 para zero
Se um ou mais bits de um byte tm que ser invertidos, voc pode usar a seguinte instruo (que no
possvel usar com uma constante):
LDI R16,0b10101010 ; Inverte todos os bits pares
EOR R1,R16 ; do registrador R1 e armazena o resultado em R1
inverte o contedo do registrador R1 e substitui zeros por uns e vice versa. Isto diferente do
Complemento de Dois, que converte um nmero com sinal positivo pelo seu complemento negativo
(subtraindo de zero). Isto feito com a instruo
NEG R1
Ento +1 (decimal: 1) vira -1 (binrio 1.1111111), +2 vira -2 (binrio 1.1111110), e assim por diante.
Alm da manipulao de bits em um registrador, a cpia de apenas um bit possvel usando a bit T do
registrador de status. Com
BLD R1,0
O bit T carregado com uma cpia do bit 0 do registrador R1. O bit T pode ser setado ou zerado, e seu
contedo pode ser copiado para qualquer bit em qualquer registrador:
CLT ; zera bit T, ou
SET ; seta bit T, ou
BST R2,2 ; copia bit T para o bit 2 do registrador R2
Desloca e rotaciona
Deslocamento e rotao de nmeros binrios significa multiplicao ou diviso por 2. O deslocamento
tem vrias sub-instrues.
A multiplicao por 2 facilmente feita deslocando todos os bits de um byte um dgito binrio esquerda
e escrevendo um zero no bit menos significativo. Isto chamado desvio esquerda lgico (Logic Shift
Left). O antigo bit 7 do byte ser deslocado para o carry no registrador de status.
LSL R1
O inverso, diviso por 2 a instruo chamada desvio direita lgico (Logic Shift Right)
LSR R1
O antigo bit 7, agora deslocado para o bit 6, preenchido com 0, enquanto o antigo bit 0 deslocado para
o carry do registrador de status. Este carry poderia ser usado para arredondar para cima e para baixo (se
estiver setado, adicionar um ao resultado). Exemplo, diviso por quatro com arredondamento:
LSR R1 ; diviso por 2
BRCC Div2 ; Pula se no arredondar
INC R1 ; arredonda para cima
Div2:
LSR R1 ; Mais uma diviso por 2
BRCC DivE ; Pula se no arredondar
INC R1 ; Arredonda
DivE:
Avr-Asm-Tutorial
32
http://www.avr-asm-tutorial.net
Assim, dividir fcil com binrios, contanto que voc divida por mltiplos de 2.
Se inteiros com sinal forem usados, o desvio direito sobrescreveria o bit de sinal 7. A instruo desvio
direita aritmtico (arithmetic shift right) ASR deixa o bit 7 intocado e desloca os 7 bits inferiores, inserindo
um bit zero na localizao 6.
ASR R1
Da mesma forma que o desvio lgico, o antigo bit 0 vai para o carry no registrador de status.
Que tal multiplicarmos uma palavra de 16 bits por 2? O bit mais significativo do byte inferior tem que ser
deslocado para se tornar o bit inferior do byte superior. Neste passo, um desvio setaria o bit mais baixo
para zero, mas precisamos deslocar o carry do deslocamento anterior do byte mais baixo para o bit 0. Isto
chamado rotao. Durante a rotao, o carry no registrador de status alterado para bit 0, e o antigo bit
7 deslocado para o carry durante a rotao.
LSL R1 ; Desvio Esquerda Lgico do byte mais baixo
ROL R2 ; Rotaciona para esquerda (ROtate Left) do byte superior
O desvio esquerda lgico da primeira instruo desloca o bit 7 para o carry, a instruo ROL rola o carry
para o bit 0 do byte superior. Aps a segunda instruo, o carry tem o antigo bit 7. O carry pode ser usado
tanto para indicar um estouro (se for feito um clculo de 16 bits) ou para ser rolado para bytes superiores
(se est sendo feito clculo com mais de 16 bits).
A rolagem para a direita tambm possvel, dividindo por 2 e deslocando o carry para o bit 7 do
resultado:
LSR R2 ; Desvio lgico direita, bit 0 vai para o carry
ROR R1 ; Rotaciona para direita (ROtate Right) e desvia o carry para o bit 7
Esta instruo troca os nibbles superior e o inferior entre si. Note que o contedo do nibble superior ser
diferente aps aplicar estes dois mtodos.
No lugar do segundo ADD, usamos ADC na segunda instruo. Isso significa somar com o carry (Add
with Carry), que setado ou zerado durante a primeira instruo, dependendo do resultado. J est
apavorado o suficiente por essa matemtica complicada? Se no: tome isso!
Subtrairemos R3:R4 de R1:R2.
SUB R2,R4 ; primeiro o byte inferior
SBC R1,R3 ; depois o byte superior
Novamente o mesmo truque: durante a segunda instruo subtramos outro 1 do resultado caso o
resultado da primeira instruo teve um estoruo. Ainda respirando? Se sim, siga adiante!
Agora comparemos uma palavra de 16 bits em R1:R2 com outro em R2:R4 para avaliar se maior do que
o segundo. No lugar de SUB, usamos uma instruo de comparao CP, e no lugar de SBC usamos
CPC:
CP R2,R4 ; compara bytes inferiores
CPC R1,R3 ; compara bytes superiores
Avr-Asm-Tutorial
33
http://www.avr-asm-tutorial.net
CPI R16,0xAA
Se o bit de Zero do registrador de status for 1 depois disso, sabemos que R16 0xAA. Se o carry for 1,
sabemos que menor. Se nem o carry nem o Zero forem 1, sabemos que maior.
E agora o teste mais complicado. Avaliamos se R1 zero ou negativo:
TST R1
Se o bit Z estiver setado, o registrador R1 zero e podemos utilizar uma das seguintes instrues: BREQ,
BRNE, BRMI, BRPL, BRLO, BRSH, BRGE, BRLT, BRVC or BRVS para desviarmos um pouco.
Ainda conosco? Se sim, h alguns clculos para BCD compactados. Somar dois BCDs compactados
pode resultar em dois estouros diferentes. O carry usual mostra um overflow, se o nibble superior resultar
em mais do que 15 decimal. Outro estouro ocorre do nibble inferior para o superior, se a soma dos dois
nibbles der mais do que 15 decimal.
Para servir de exemplo, vamos somar os BCDs compactados 49 (=hexa 49) e 99 (=hexa 99) para chegar
a 148 (=hexa 0x0148). Som-los usando matemtica binria resultaria em um byte com o hexa 0xE2, e
no ocorreria estouro. O mais baixo dos nibbles deveria ter dado um overflow, pois 9+9=18 (mais que 9) e
o nibble inferior pode somente manipular nmeros at 15. O estouro foi somado ao bit 4, o bit menos
significativo do nibble superior. O que est correto! Mas o nibble inferior deveria ser 8 e somente 2 (18 =
0b0001.0010). Deveramos adicionar 6 a este nibble para chegarmos ao resultado correto. O que lgico,
porque sempre que o nibble inferior passar de 9, temos que adicionar 6 para corrigi-lo.
O nibble superior est totalmente incorreto, porque est 0xE e deveria ser 3 (com um 1 estourando para o
prximo dgito do BCD compactado). Se adicionarmos 6 a este 0xE, conseguiremos 0x4 e o carry
setado (=0x14). Ento o truque primeiro somarmos estes dois nmeros e depois adicionarmos 0x66
para corrigir os dois dgitos do BCD compactado. Mas espere: e se a soma do primeiro e do segundo
dgitos no resultarem em estouro para o prximo nibble e no resultar em um nmero maior do que 9 no
nibble inferior? Somar 0x66 ento resultaria em um resultado totalmente incorreto. O 6 inferior deve ser
adicionado se o nibble inferior estoura para o nibble superior, ou resulta em um dgito maior que 9. O
mesmo com o nibble superior.
Como sabemos, se ocorre um estouro do nibble inferior para o superior? A MCU seta o bit H no
registrador de status, o bit meio-carry (half-carry). A seguir mostramos o algoritmo para diferentes casos
que so possveis aps somar dois nibbles e somar o hexa 0x6 a eles.
1. Some os nibbles. Se ocorrer estouro (C para os nibbles superiores, ou H para os inferiores),
adicione 6 para corrigir. Se no, passe para o passo 2.
2. Some 6 ao nibble. Se ocorrer estouro (C ou H), est terminado. Se no, subtraia 6.
Para programar um exemplo, vamos assimir que dois BCDs compactados esto em R2 e R3, R1 ficar
com o estouro, e R16 e R17 esto disponveis para clculos. R16 o registrador de soma para adicionar
0x66 (o registrador R2 no pode receber um valor constante), R17 usado para corrigir o resultado
dependendo das diferentes flags. Somar R2 com R3 fica assim:
LDI R16,0x66 ; para somar 0x66 ao resultado
LDI R17,0x66 ; para depois subtrai-lo do resultado
ADD R2,R3 ; soma os dois BCDs de dois dgitos
BRCC NoCy1 ; pula se no ocorrer estouro
INC R1 ; incrementa o prximo byte superior
ANDI R17,0x0F ; no subtraia 6 do nibble inferior
NoCy1:
BRHC NoHc1 ; pula se no ocorrer meio-carry
ANDI R17,0xF0 ; no subtraia 6 do nibble inferior
NoHc1:
ADD R2,R16 ; some 0x66 ao resultado
BRCC NoCy2 ; pule se no ocorreu carry
INC R1 ; incremente o prximo byte superior
ANDI R17,0x0F ; no subtraia 6 do nibble superior
NoCy2:
BRHC NoHc2 ; pule se no ocorreu meio-carry
ANDI R17,0xF0 ; no subtraia 6 do nibble inferior
NoHc2:
SUB R2,R17 ; correo da subtrao
Pergunta para pensar: porque ambos esto corretos, e a segunda verso ocupa metade do tamanho e
Avr-Asm-Tutorial
34
http://www.avr-asm-tutorial.net
E ento voc desloca os bits do binrio para que este desloque dos registradores para o carry. Se for um,
voc adiciona o nmero na tabela ao resultado, lendo on nmeros da tabela usando LPM. Isto mais
complicado para programar e um pouco mais lento do que o mtodo acima.
O terceiro mtodo calcular o valor da tabela, iniciando com 000001, adicionando-o ao BCD, cada vez
que voc desloca um bit do seu binrio para a direita e adiciona ao BCD.
Muitos mtodos, muito a ser otimizado.
Multiplicao
A multiplicao de nmeros binrios ser explicada aqui.
Multiplicao decimal
Para multiplicarmos dois nmeros binrios de 8 bits, vamos lembrar como fazemos com os nmeros
decimais:
1234 * 567 = ?
-----------------------1234 * 7 =
8638
+ 1234 * 60 = 74040
+ 1234 * 500 = 617000
-----------------------1234 * 567 = 699678
========================
Passo a passo, em decimal:
Avr-Asm-Tutorial
35
http://www.avr-asm-tutorial.net
Multiplicamos o primeiro nmero por 10 e pelo prximo dgito do segundo nmero e adicionamos ao
resultado.
Multiplicao binria
Agora em binrio. A multiplicao com dgitos simples no nececssria, pois h somente os dgitos 1
(some o nmero) e 0 (no some o nmero). A multiplicao por 10 em decimal equivale multiplicao
por 2 em modo binrio. Multiplicao em 2 feita facilmente, adicionando o nmero a si mesmo, ou
deslocando todos os bits uma posio para a esquerda e escrevendo um 0 para a posio vazia direita.
Veja que matemtia binria muito mais fcil que decimal. Porque a humanidade no a usou desde o
comeo?
Avr-Asm-Tutorial
36
http://www.avr-asm-tutorial.net
Rotao binria
Para entender a operao de multiplicao,
necessrio entender os comandos de rotao
binria ROL e ROR. Estas instrues
deslocam todos os bits de um registrador uma
posio esquerda (ROL) ou direita (ROR).
A posio vazia no registrador recebe o
contedo do carry do registrador de status, e o
bit que rola para fora do registrador vai para o
carry. Esta operao demonstrada usando
0xAA como exemplo de ROL e 0x55 como
exemplo de ROR.
Multiplicao no studio
A tela abaixo mostra o programa de multiplicao no simulador.
Avr-Asm-Tutorial
37
http://www.avr-asm-tutorial.net
Os registradores R0 e R2 so
setados para 0xAA e 0x55,
nossos binrios de teste, para
serem multiplicados.
R2 rotacionado
direita, para rolar o
bit
menos
significativo para o
carry,
0x55
(0101.0101)
vira
0x2A (0010.1010).
Avr-Asm-Tutorial
38
http://www.avr-asm-tutorial.net
Agora o par de
registradores R1:R0
rotacionado uma
posio esquerda
para multiplicar este
binrio por 2. A partir
de
0x00AA,
a
multiplicao por 2
resulta 0x0154.
O
ciclo
de
multiplicao
repetido
enquanto
haja ao menos um
binrio
1
no
registrador R2. Os
passos
seguintes
no so mostrados
aqui.
Usando a tecla F5
no studio podemos
pular estes loops
at um ponto de
parada no fim da
rotina
de
multiplicao.
O
resultado no par de
registradores
R4:R3 mostra o
resultado
da
multiplicao
de
0xAA por 0x55:
0x3872.
Diviso
Diviso decimal
Novamente comeamos com diviso decimal, para compreender melhor a diviso binria. Vamos assumir
uma diviso de 5678 por 12. Isto feito assim:
5678 : 12 = ?
-------------------------- 4 * 1200 = 4800
---878
- 7 * 120 = 840
--38
- 3 * 12 = 36
-2
Resultado: 5678 : 12 = 473 Resto 2
Avr-Asm-Tutorial
39
http://www.avr-asm-tutorial.net
===================================
Diviso binria
Em binrio, a multiplicao do segundo nmero (4 * 1200, etc) no necessria, devido ao fato que
temos apenas 0 e 1 como dgitos. Infelizmente, nmeros binrios tm muito mais dgitos do que seu
equivalente decimal, ento transferir a diviso decimal em binria um pouco inconveniente. Assim, o
programa trabalha de forma um pouco diferente.
A diviso de um nmero binrio de 16 bits por um nmero de 8 bits em assembler AVR est listado na
seo seguinte.
; Div8 divide um nmero de 16 bits por um nmero de 8 bits (Testee: nmero de 16 bits: 0xAAAA, nmero de 8 bits: 0x55)
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
; Registradores
.DEF rd1l = R0 ; LSB do nmero de 16 bits a ser dividido (dividendo)
.DEF rd1h = R1 ; MSB do nmero de 16 bits a ser dividido (dividendo)
.DEF rd1u = R2 ; registrador intermedirio
.DEF rd2 = R3 ; nmero de 8 bits divisor
.DEF rel = R4 ; LSB do resultado
.DEF reh = R5 ; MSB do resultado
.DEF rmp = R16; registrador multi-propsito para carregamento
;
.CSEG
.ORG 0
rjmp start
start:
; Carregamos os nmeros do teste para os registradores apropriados
ldi rmp,0xAA ; 0xAAAA o dividendo
mov rd1h,rmp
mov rd1l,rmp
ldi rmp,0x55 ; 0x55 o divisor
mov rd2,rmp
; Divide rd1h:rd1l por rd2
div8:
clr rd1u ; zera registrador intermedirio
clr reh ; zera resultado (os registradores de resultado)
clr rel ; tambm usados para contar at 16 para
inc rel ; os passos da diviso, setado em 1 no incio)
; Aqui o loop de diviso inicia
div8a:
clc
; zera carry
rol rd1l ; rotaciona o prximo bit superior do nmero
rol rd1h ; para o registrador intermedirio (multiplica por 2)
rol rd1u
brcs div8b ; um foi rolado para a esquerda, portanto subtraia
cp rd1u,rd2 ; Resultado da diviso 1 ou 0?
brcs div8c ; pule sobre a subtrao, se for menor
div8b:
sub rd1u,rd2; subtraia os nmeros para dividir
sec
; set carry, o resultado 1
rjmp div8d ; pule para o desvio do bit de resultado
div8c:
clc
; zere o carry, o bit resultado 0
div8d:
rol rel ; rotacione o carry para dentro dos registradores de resultado
rol reh
brcc div8a ; enquanto zero rotacionar para fora dos registradores de resultado: v para o loop de diviso
; Fim da diviso
stop:
rjmp stop ; loop sem fim
O contedo do registrador intermedirio comparado com o binrio de 8 bits em rd2. Se rd2 for
menor, ele subtrado do registrador intermedirio e o carry setado 1, se rd2 for maior, a
subtrao pulada e um zero setado na flag de carry.
Avr-Asm-Tutorial
40
http://www.avr-asm-tutorial.net
Se um zero foi rotacionado para fora do registrador de resulltado, temos que repetir o loop de
diviso. Se foi um 1, a diviso est completa.
Se voc no entende rotao ainda, voc encontrar esta operao discutida na seo de multiplicao.
Diviso no simulador
A tela a seguir demonstra os passos do
programa no studio. Para fazer isto, voc
tem que compilar o cdigo fonte e abrir o
arquivo objeto resultante no studio.
O cdigo objeto foi iniciado, o cursor est
na primeira instruo executvel. F11
executa passo a passo.
O registrador intermedirio R2
e o par de registradores do
resultado so setados para
seus valores predefinidos.
Avr-Asm-Tutorial
41
http://www.avr-asm-tutorial.net
No houve estouro da
rotao para o carry e 0x01
em R2 era menor que 0x55
em R3, ento a subtrao foi
pulada. Um zero no carry foi
rotacionado
para
o
registrador de resultado
R5:R4. O contedo anterior
destes registradores, um bit
na posio 0 foi rotacionado
para a posio 1 (contedo
agora: 0x0002). Como um
zero foi rotacionado para
fora do registrador de
resultados, o prximo passo
a ser executado um desvio
para o incio do loop de
diviso e o loop repetido.
Aps executar o loop 16
vezes, chegamos ao
ponto de parada no final
da rotina de diviso. O
registrador de resultado
R5:R4 tem 0x0202, o
resultado da diviso. Os
registradores R2:R1:R0
esto vazios, portanto
no temos resto. Se
houvesse
resto,
poderamos us-lo para
decidir um incremento
do
resultado,
arredondando-o
para
cima. Este passo no foi
codificado aqui.
Avr-Asm-Tutorial
42
http://www.avr-asm-tutorial.net
Toda
a
diviso
precisou
de
60
microssegundos do tempo do processador
(abra o processor view do menu studio).
Um tempo bastante grande para uma
diviso.
Converso numrica
Rotinas de converso numricas no so includas aqui. Por favor visite o website, se precisar do cdigo
fonte ou uma melhor compreenso.
Fraes decimais
Primeiro: No use pontos flutuantes, a menos que voc realmente precise deles. Pontos flutuantes so
vorazes consumidores de recursos em um AVR, e precisam de muito tempo de execuo. Voc estar
neste dilema, se voc pensa que assembler muito complicado, e preferir Basic ou outras linguagens
como C e Pascal.
Mas no, se voc usa assembler. Lhe ser demonstrado aqui, como voc pode realizar uma multiplicao
de um nmero real em menos de 60 microssegundos, em casos especiais at com 18 microssegundos,
usando uma freqncia de clock de 4 MHz. Sem quaisquer extenses para ponto flutuante ou outros
truques caros para pessoas preguiosas demais para usar o seu crebro.
Como fazer isto? De volta razes de matemtica! A maioria das tarefas com reais usando ponto
flutuante pode ser feita usando nmeros inteiros. Inteiros so fceis de programar em assembler, e so
velozes. O ponto decimal est somente no crebro do programador, e adicionado depois no fluxo digital.
Ningum se d conta disso, este o truque.
Converses lineares
Como um exemplo, a tarefa seguinte: um conversor AD de 8 bits mede a entrada de um sinal de entrada
variando de 0,00 a 2,55 Volts, e retorna como resultado um binrio entre $00 e $FF. O resultado uma
voltagem, para ser mostrada em um display LCD. Exemplo to simples quanto fcil: O binrio
convertido em uma string ASCII decimal entre 000 e 255, e logo depois do primeiro dgito, o ponto
decimal tem que ser inserido. Pronto!
O mundo eletrnico mais complicado. E. g., o conversor AD retorna um hexa de 8 bits para tenses de
entrada entre 0,00 e 5,00 Volt. Agora complicou e no sabemos como fazer. Para mostrar o valor correto
no LCD, teramos que multiplicar o binrio por 500/255, que 1,9608. Este um nmero complicado, pois
quase 2, mas apenas quase. E no queremos este tipo de impreciso de 2%, j que temos um
conversor AD com cerca de 0,25% de preciso.
Para resolver isso, multiplicamos a entrada por 200/255*256 ou 501,96 e dividimos o resultado por 256.
Porque primeiro multiplicar por 256 e depois dividir por 256? apenas para maior preciso. Se
multiplicarmos a entrada por 502 ao invs de 501,96, o erro da ordem de 0,008%. Isto est bom para
nosso conversor AD, podemos conviver com isso. E dividir por 256 uma tarefa fcil, pois uma potncia
de 2 bem conhecida. Dividir nmeros que so potncia de 2, o AVR se sente muito confortvel e realiza
de forma muito rpida. Para dividir por 256, o AVR ainda mais rpido, pois basta pularmos o ltimo byte
do nmero binrio. No precisamos nem mesmo deslocar e rotacionar!
Na multiplicao de um binrio de 8 bits com o binrio de 9 bits 502 (hex 16F), podemos obter um valor
maior do que 16 bits. Portanto temos que reservar 24 bits ou 3 registradores para o resultado. Durante a
multiplicao, a constante 502 tem que ser deslocada esquerda (multiplicao por 2) para somar estes
nmeros ao resultado cada vez que um 1 rola para fora do nmero de entrada. Como podem ser
necessrios 8 desvios esquerda, precisamos de mais trs bytes para esta constante. Ento escolhemos
a seguinte combinao dos registradores para multiplicao:
Nmero
Valor (exemplo)
Registrador
Valor de entrada
255
R1
Multiplicador
502
R4 : R3 : R2
128,010
R7 : R6 : R5
Resultado
Avr-Asm-Tutorial
43
http://www.avr-asm-tutorial.net
Aps colocar o valor 502 (00.01.F6) em R4:R3:R2 e zerar os registradores de resultado R7:R6:R5, a
multiplicao segue da seguinte forma:
1. Testar, se o nmero da entrada j zero. Se for, terminamos.
2. Se no, um bit do nmero de entrada deslocado para fora do registrador para a direita, no carry,
enquanto um bit zero colocado no bit 7. Esta instruo chamada desvio direta lgico ou LSR
(Logical Shift Right)
3. Se o bit no carry for um, somamos o multiplicador (durante o passo 1 o valor 502, no passo 2
1004 e assim por diante) ao resultado. Durante a adio, tomamos o cuidado com qualquer carry
(somando R2 a R5 por ADD, somando R3 a R6 e R4 a R7 com instruo ADC!). Se o bit no carry
era zero, no adicionamos o multiplicador ao resultado e pulamos para o prximo passo.
4. Agora o multiplicador foi multiplicado por 2, pois o prximo bit deslocado para fora do nmero de
entrada vale o dobro. Ento deslocamos R2 para a esquerda (inserindo um zero no bit 0) usando
LSL. O bit 7 deslocado para o carry. Ento rotacionamos este carry para R3, rotacionando seu
contedo um bit esquerda, e o bit 7 para o carry. O mesmo com R4.
5. Agora terminamos com um dgito do nmero de entrada, e prosseguimos no passo 1 novamente.
O resultado da multiplicao por 502 agora est nos registradores de resultado R7:R6:R5. Se
simplesmente ignorarmos o registrador R5 (diviso por 256), temos o nosso resultado desejado. Para
aumentar a preciso, podemos usar o bit 7 em R5 para arredondar o resultado. Agora temos que
converter o resultado de sua forma binria para o ASCII decimal (veja a tabela de converso para
decimal-ASCII no website). Se colocarmos um ponto decimal no local correto na string ASCII, nossa string
de tenso est pronta para ser mostrada.
O programa todo, desde o nmero de entrada at a ASCII resultado, requer entre 79 e 228 ciclos de
relgio, dependendo do nmero de entrada. Aqueles que quiserem vencer com rotinas de ponto flutuante
de uma linguagem de programao mais sofisticada que assembler, sinta-se vontade para me escrever
o seu tempo de converso (e a utilizao de memria flash e de programa).
Avr-Asm-Tutorial
44
http://www.avr-asm-tutorial.net
fpconv8:
rcall fpconv8m ; multiplica pot 502
rcall fpconv8r ; arredonda e divide por 256
rcall fpconv8a ; converte para string ASCII
ldi rmp,'.' ; seta caractere decimal
mov R6,rmp
ret ; tudo pronto
; Subrotina de multiplicao por 502
fpconv8m:
clr R4 ; seta o multiplicador como 502
ldi rmp,$01
mov R3,rmp
ldi rmp,$F6
mov R2,rmp
clr R7 ; zera o resultado
clr R6
clr R5
fpconv8m1:
or R1,R1 ; checa se o nmero zero
brne fpconv8m2 ; ainda tem um, continuamos com a verso
ret ; pronto, retorne
fpconv8m2:
lsr R1 ; desloca nmero direita (divide por 2)
brcc fpconv8m3 ; se o nmero mais baixo era 0, pula adio
add R5,R2 ; some o nmero em R6:R5:R4:R3 ao resultado
adc R6,R3
adc R7,R4
fpconv8m3:
lsl R2 ; multiplica R4:R3:R2 por 2
rol R3
rol R4
rjmp fpconv8m1 ; repete para o prximo bit
; Arredonda o valor em R7:R6 com o valor do bit 7 de R5
fpconv8r:
clr rmp ; coloca zero em rmp
lsl R5 ; rotaciona bit 7 para o carry
adc R6,rmp ; soma LSB com carry
adc R7,rmp ; soma MSB com carry
mov R2,R7 ; copia o valor para R2:R1 (divide por 256)
mov R1,R6
ret
; Converte a palavra em R2:R1 para uma string ASCII em R5:R6:R7:R8
fpconv8a:
clr R4 ; Seta o valor do divisor decimal para 100
ldi rmp,100
mov R3,rmp
rcall fpconv8d ; obtm o dgito ASCII por subtraes repetidas
mov R5,rmp ; seta caractere como sendo da centena
ldi rmp,10 ; Seta o valor do divisor decimal para 10
mov R3,rmp
rcall fpconv8d ; obtm o prximo dgito ASCII
mov R7,rmp ; seta caractere como sendo da dezena
ldi rmp,'0' ; converte o resto para dgito ASCII
add rmp,R1
mov R8,rmp ; seta caractere como sendo da unidade
ret
; Converte palavra binria em R2:R1 para dgito decimal subtraindo o valor do divisor decimal em R4:R3 (100,10)
fpconv8d:
ldi rmp,'0' ; inicia com o valor decimal '0'
fpconv8d1:
cp R1,R3 ; Compara palabra com o valor do divisor decimal
cpc R2,R4
brcc fpconv8d2 ; zera carry, subtrai valor do divisor
ret ; subtrao feita
fpconv8d2:
sub R1,R3 ; subtrai valor do divisor
sbc R2,R4
inc rmp ; soma um
rjmp fpconv8d1 ; de novo
; Fim da rotina de converso
Avr-Asm-Tutorial
45
http://www.avr-asm-tutorial.net
Anexo
Instrues ordenadas por funo
Para as abreviaes usadas, veja a lista de abreviaes.
Funo
Registrador
Cpia
Soma
Subtrao
Desvio
Binrios
Sub funo
Comando
Flags
ZNV
Clk
CLR r1
255
SER rh
Constante
LDI rh,c255
MOV r1,r2
LDS r1,c65535
LD r1,rp
LD r1,rp+
LD r1,-rp
LDD r1,ry+k63
IN r1,p1
POP r1
LPM
STS c65535,r1
ST rp,r1
ST rp+,r1
ST -rp,r1
STD ry+k63,r1
OUT p1,r1
PUSH r1
8 Bit, +1
INC r1
ZNV
8 Bit
ADD r1,r2
ZCNVH 1
8 Bit + carry
ADC r1,r2
ZCNVH 1
16 Bit, constante
ADIW rd,k63
ZCNVS 2
8 Bit, -1
DEC r1
ZNV
8 Bit
SUB r1,r2
ZCNVH 1
8 Bit, constante
SUBI rh,c255
ZCNVH 1
8 Bit - carry
SBC r1,r2
ZCNVH 1
SBCI rh,c255
ZCNVH 1
16 Bit
SBIW rd,k63
ZCNVS 2
Lgico, esquerda
LSL r1
ZCNV
Lgico, direita
LSR r1
ZCNV
ROL r1
ZCNV
ROR r1
ZCNV
Aritmtica, direita
ASR r1
ZCNV
Troca de nibbles
SWAP r1
E (And)
AND r1,r2
ZNV
E, constante
ANDI rh,c255
ZNV
Ou (Or)
OR r1,r2
ZNV
Ou, constante
ORI rh,c255
ZNV
Ou-Exclusivo (XOR)
EOR r1,r2
ZNV
Complemento de Um
COM r1
ZCNV
Complemento de Dois
NEG r1
ZCNVH 1
Avr-Asm-Tutorial
46
Funo
Troca
Bits
Sub funo
http://www.avr-asm-tutorial.net
Comando
SBR rh,c255
ZNV
Registrador, zera
CBR rh,255
ZNV
BST r1,b7
BLD r1,b7
Porta, seta
SBI pl,b7
Porta, zera
CBI pl,b7
Flag de Zero
SEZ
Flag de carry
SEC
Flag de Negativo
SEN
Flag de Sinal
SES
Flag de Transferncia
SET
SEI
Flag de Zero
CLZ
Flag de carry
CLC
Flag de Negativo
CLN
Salto
Imediato
Clk
Registrador, seta
Compara
Flags
Flag de Sinal
CLS
Flag de Transferncia
CLT
CLI
Registrador, Registrador
CP r1,r2
ZCNVH 1
CPC r1,r2
ZCNVH 1
Registrador, constante
CPI rh,c255
ZCNVH 1
Registrador, 0
TST r1
ZNV
Relativo
RJMP c4096
Indireto, Endereo em Z
IJMP
Subrotina, relativo
RCALL c4096
Subrotina, Endereo em Z
ICALL
Retorna da Subrotina
RET
Retorna da Interrupo
RETI
Avr-Asm-Tutorial
47
Funo
http://www.avr-asm-tutorial.net
Sub funo
Comando
Flags
Clk
BRBS b7,c127
1/2
BRBC b7,c127
1/2
Salta se igual
BREQ c127
1/2
Salta se diferente
BRNE c127
1/2
BRCS c127
1/2
BRCC c127
1/2
BRSH c127
1/2
Salta se menor
BRLO c127
1/2
Salta se negativo
BRMI c127
1/2
BRPL c127
1/2
BRGE c127
1/2
BRLT c127
1/2
BRHS c127
1/2
BRHC c127
1/2
BRTS c127
1/2
BRTC c127
1/2
1/2
1/2
BRIE c127
1/2
BRID c127
1/2
Bit do registrador=0
SBRC r1,b7
1/2/3
Bit do registrador=1
Salto
Bit da porta=0
condcionado
Bit da porta=1
SBRS r1,b7
1/2/3
SBIC pl,b7
1/2/3
SBIS pl,b7
1/2/3
CPSE r1,r2
1/2/3
Sem Operao
NOP
Repouso
SLEEP
Watchdog Reset
WDR
Salta se positivo
Salto
Salta se igual ou maior (com sinal)
Condicional
Salta se menor que zero (com sinal)
Outros
.CSEG
.DB
.DEF
.DW
.ENDMACRO
.ESEG
.EQU
.INCLUDE
Inserir o contedo de um arquivo neste local como se fosse parte deste arquivo
.MACRO
.ORG
ADC r1,r2
ADD r1,r2
ADIW rd,k63
Soma a palavra constante imediata k63 ao registrador duplo rd+1:rd (rd = R24, R26, R28, R30)
Avr-Asm-Tutorial
48
http://www.avr-asm-tutorial.net
AND r1,r2
ANDI rh,c255
Faz operao and com o registrador superior rh com a constante c255 e armazena o resultado em rh
ASR r1
BLD r1,b7
BRCC c127
BRCS c127
BREQ c127
BRGE c127
BRHC c127
BRHS c127
BRID c127
BRIE c127
BRLO c127
BRLT c127
BRMI c127
BRNE c127
BRPL c127
BRSH c127
BRTC c127
BRTS c127
BRVC c127
BRVS c127
BST r1,b7
CBI pl,b7
CBR rh,k255
Zera todos os bits no registrador superior rh, que esto setados na constante k255 (mscara)
CLC
CLH
CLI
CLN
CLR r1
Zera o registrador r1
CLS
CLT
CLV
CLZ
COM r1
CP r1,r2
CPC r1,r2
CPI rh,c255
CPSE r1,r2
DEC r1
EOR r1,r2
ICALL
IJMP IN r1,p1
INC r1
LD r1,(rp,rp+,-rp) Carrega o registrador r1 com o contedo localizado no endereo apontado pelo par de registradores rp
(X, Y ou Z) (rp+ incrementa o par de registradores depois da carga, -rp decrementa o par antes da
carga)
LDD r1,ry+k63
Carrega o registrador r1 com o contedo localizado no endereo apontado pelo par de registradores ry
(Y ou Z), deslocado pela constante k63
LDI rh,c255
LDS r1,c65535
LPM
LPM r1
LPM r1,Z+
LPM r1,-Z
Carrega o registrador R0 com o contedo da memory flash localizado no endereo apontado pelo par
de registradores Z (ZH:ZL, R31:R30), dividido por 2, bit 0 em Z aponta para o byte inferior (0) ou
superior (1) no flash (Carrega registrador r1, Z+ incrementa Z depois da carga, -Z decrementa Z antes
da carga).
LSL r1
LSR r1
Avr-Asm-Tutorial
49
http://www.avr-asm-tutorial.net
MOV r1,r2
NEG r1
NOP
Sem operao
OR r1,r2
ORI rh,c255
OUT p1,r1
POP r1
PUSH r1
RCALL c4096
Coloca o contador de programa na pilha e adiciona a constante com sinal c4096 ao contador de
programa (chamada relativa)
RET
RETI
RJMP c4096
ROL r1
ROR r1
SBC r1,r2
SBCI rh,c255
SBI pl,b7
SBIC pl,b7
SBIS pl,b7
SBIW rd,k63
Subtrai a constante k63 do par de registradores rd (rd+1:rd, rd = R24, R26, R28, R30)
SBR rh,c255
SBRC r1,b7
SBRS r1,b7
SEC
SEH
SEI
SEN
SER rh
SES
SET
SEV
SEZ
SLEEP
ST (rp/rp+/-rp),r1 Armazena o contedo do registrador r1 na localizao da memria indicada pelo par de registradores
rp (rp = X, Y, Z; rp+: incrementa o par de registradores depois do armazenamento; -rp: decrementa o
par de registradores antes do armazenamento)
STD ry+k63,r1
STS c65535,r1
SUB r1,r2
SUBI rh,c255
SWAP r1
TST r1
WDR
Watchdog reset
Avr-Asm-Tutorial
50
http://www.avr-asm-tutorial.net
Endereo da
porta
Funo
Acumulador do registrador
0x3F
de status
Endereo da
RAM
0x5F
Bit Nome
Significado
Indica
Comando
CLI
Flag
de
Global
Armazm de bits
Flag de Meio-Carry
Flag de Sinal
Flag de Negativo
Flag de Zero
Flag de Carry
SEI
0: O bit armazenado 0
CLT
1: O bit armazenado 1
SET
0: No ocorreu meio-carry
CLH
1: Ocorreu meio-carry
SEH
0: Sinal positivo
CLS
1: Sinal negativo
SES
CLV
SEV
CLN
SEN
CLZ
SEZ
CLC
SEC
Ponteiro de pilha
Porta
Endereo da
porta
Funo
SPL/SPH
Ponteiro de
003D/0x3E
pilha
Nome
Significado
Endereo da
RAM
0x5D/0x5E
Disponibilidade
SPL
Byte baixo do
ponteiro de pilha
SPH
Byte alto do
ponteiro de pilha
Endereo da
RAM
0x55
SRE
SRW
SE
SM
ISC11
ISC10
ISC01
ISC00
Bit Nome
7
Endereo da
porta
Funo
SRE
Significado
Habilita SRAM Externa
Indica
0=No h SRAM externa conectada
1=H SRAM externa conectada
Avr-Asm-Tutorial
51
Bit Nome
Significado
http://www.avr-asm-tutorial.net
Indica
SRW
SE
SM
Modo de respouso
ISC11
2
1
ISC01
Endereo da
Porta
Funo
Registrador mascarado
Interrupo Geral
de
0x3B
Endereo da
RAM
0x5B
INT1
INT0
Bit Nome
Significado
Indica
INT1
INT0
0...5
(No usados)
Porta
Endereo
da Porta
Funo
0x3A
Endereo da
RAM
0x5A
INTF1
INTF0
Bit
Name
0...5
Significado
Indica
Zera o bit pela execuo da rotina de
tratamento ou por comando
(No usados)
Avr-Asm-Tutorial
52
http://www.avr-asm-tutorial.net
Endereo da
Porta
Funo
Registrador mascarado do
0x39
timer de interrupo
Endereo da
RAM
0x59
TOIE1
OCIE1A
OCIE1B
TICIE1
TOIE0
Avr-Asm-Tutorial
Bit
7
53
Nome
TOIE1
http://www.avr-asm-tutorial.net
Significado
Indica
0: Sem
estouro
int
no
1: Int no estouro
6
(No usado)
TICIE1
0: Sem
captura
int
na
1: Int na captura
2
(No usado)
TOIE0
0: Sem
estouro
int
no
1: Int no estouro
0
(No usado)
Port
Endereo
da Porta
Funo
Registrador
interrupo
TIFR
de
timer
de
0x38
Endereo da
RAM
0x58
TOV1
OCF1A
OCF1B
ICF1
TOV0
Bit
Nome
Significado
Indica
TOV1
Modo-Interrupo:
(No usado)
ICF1
2
1
0
Timer/Contador 1 estourou
TOV0
Timer/Contador 0 estourou
(No usado)
OU
Zero por comando
Avr-Asm-Tutorial
54
http://www.avr-asm-tutorial.net
Timer/Contador 0
Port
Endereo da
Porta
Funo
Endereo da
RAM
TCCR0
0x53
CS02
CS01
CS00
Bit
Nome
Significado
Indica
000: Pra timer
001: Clock = clock do chip
010: Clock = clock do chip / 8
3..7
(No usado)
Port
Endereo da
Porta
Funo
TCNT0
Registrador de Controle de
0x32
Timer/Contador 0
Endereo da
RAM
0x52
Timer/Contador 1
Port
TCCR1A
Endereo da
Porta
Funo
Nome
COM1A1
COM1A0
5
4
3
2
Significado
Endereo da
RAM
0x4F
PWM11
PWM10
Indica
PWM11
1..0
PWM10
Avr-Asm-Tutorial
55
Port
http://www.avr-asm-tutorial.net
Endereo da
Porta
Funo
TCCR1B
Endereo da
RAM
0x4E
ICNC1
ICES1
CTC1
CS12
CS11
CS10
Bit
Nome
Significado
Indica
ICNC1
ICES1
CTC1
Limpa quando a
comparao
for 1: Contador zera se for igual
igual a A
Port
Funo
Port
Funo
Endereo da
Porta
0x2C/0x2D
Endereo da
RAM
0x4C/0x4D
Endereo da
Porta
Port
Funo
OCR1BL/H
Port
ICR1L/H
Endereo da
Porta
Funo
Endereo da
Porta
Endereo da
RAM
0x4A/0x4B hex
Endereo da
RAM
0x48/0x49
Endereo da
RAM
0x44/0x45
Avr-Asm-Tutorial
56
http://www.avr-asm-tutorial.net
Watchdog-Timer
Port
Endereo da
Porta
Funo
Registrador de
Watchdog Timer
WDTCR
Controle
do
Endereo da
RAM
0x21
0x41
WDTOE
WDE
WDP2
WDP1
WDP0
Bit
Nome
Significado
7..5
(No usado)
WDTOE
WDE
Habilita Watchdog
1: Watchdog ativo
000: 15 ms
001: 30 ms
010: 60 ms
011: 120 ms
100: 240 ms
101: 490 ms
110: 970 ms
111: 1,9 s
EEPROM
Port
Endereo da
Porta
Funo
EEARL/H
Registrador de Endereo da
0x1E/0x1F
EEPROM
Endereo da
RAM
0x3E/0x3F
EEARH apenas nos tipo com EEPROM com mais de 256 Bytes (do AT90S8515 para frente)
Port
EEDR
0x3D
Endereo da
Porta
Funo
EECR
Endereo da
RAM
Registrador de Dados da
0x1D
EEPROM
Port
Bit
Endereo da
Porta
Funo
Registrador de Controle da
0x1C
EEPROM
Endereo da
RAM
0x3C
EEMWE
EEWE
EERE
Nome
Significado
7..
3
Funo
(No usado)
EEMWE
Habilita
EEPROM
Escrita
Master
EEWE
EERE
Avr-Asm-Tutorial
57
http://www.avr-asm-tutorial.net
Endereo da
Porta
Funo
Registrador
Controle SPI
de
Endereo da
RAM
0x0D
0x2D
SPIE
SPE
DORD
MSTR
CPOL
CPHA
SPR1
SPR0
Bit Nome
Significado
Funo
0: Interrupes desabilitadas
SPIE
Interrupes SPI
SPE
Habilita SPI
SPR1
SPR0
1: Interrupes habilitadas
0: SPI desabilitado
1: SPI habilitado
0: MSB primeiro
1: LSB primeiro
0: Slave
1: Master
0: Fase positiva do Clock
1: Fase negativa do Clock
0: Amostragem no incio da fase do clock
1: Amostragem no fim da fase do clock
00: Clock / 4
Port
SPSR
Endereo da
Porta
Funo
Registrador
Status SPI
de
0x0E
Endereo da
RAM
0x2E
SPIF
WCOL
Bit Nome
Significado
Indica
SPIF
Flag de Interrupo
Requisita Interrupo
SPI
WCOL
5..0
Port
SPDR
coliso
na
(No usado)
Endereo da
Porta
Funo
Registrador
Dados da SPI
de
0x0F
Endereo da
RAM
0x2F
Avr-Asm-Tutorial
58
http://www.avr-asm-tutorial.net
UART
Port
Endereo da
Porta
Funo
UDR
Registrador de Dados da
0x0C
E/S UART
Port
0x2C
Endereo da
Porta
Funo
Endereo da
RAM
Registrador de Status
0x0B
da UART
USR
Endereo da
RAM
0x2B
RXC
TXC
UDRE
FE
OR
Bit Nome
Significado
Funo
RXC
1: Caractere recebido
TXC
Transmisso
Completa
UDRE
Registrador de Dados da 1:
Registrador
UART Vazio
transmisso disponvel
FE
Erro de
(framing)
OR
Perda (Overrun)
UART
enquadramento
2..0
de
(No usado)
Port
UCR
Endereo da
Porta
Funo
Registrador de Controle
0x0A
da UART
Endereo da
RAM
0x2A
RXCIE
TXCIE
UDRIE
RXEN
TXEN
CHR9
RXB8
TXB8
Bit Nome
Significado
Funo
RXCIE
Habilita Interrupo
terminada
quando
RX 1: Interrupo
caractere
TXCIE
Habilita
Interrupo
completo
quando
UDRIE
Habilita
Interrupo
Registrador de Dados vazio
RXEN
Recepo Habilitada
1: Receptor habilitado
TXEN
Transmisso Habilitada
1: Transmissor habilitado
CHR9
Caracteres de 9 bits
RXB8
TXB8
Port
UBRR
Funo
recebe
Endereo da
Porta
Registrador de velocidade
0x09
da UART (Baud Rate)
quando
Endereo da
RAM
0x29
Avr-Asm-Tutorial
59
http://www.avr-asm-tutorial.net
Analog Comparator
Port
ACSR
Registrador de Status
Comparador Analgico
de
Controle
do
0x08
0x28
ACD
ACO
ACI
ACIE
ACIC
ACIS1
ACIS0
ACD
Significado
Funo
Desabilita
Desabilita Comparadores
(No usado)
ACO
ACI
Flag de Interrupo
1: Interrupo requisitada
ACIE
Habilita Interrupo
1: Interrupo habilitada
ACIC
Habilita Captura de
1: Conecta a Captura do Timer1
entrada
ACIS1
em
borda
de
em
borda
de
Portas E/S
Port Register
Endereo da
RAM
Bit Nome
7
Endereo da
Porta
Funo
Funo
Endereo da
Porta
Endereo da
RAM
PORTA
Registrador de Dados
0x1B
0x3B
DDRA
Registrador da Direo
dos Dados
0x1A
0x3A
PINA
0x19
0x39
PORTB
Registrador de Dados
0x18
0x38
DDRB
Registrador da Direo
dos Dados
0x17
0x37
PINB
0x16
0x36
PORTC
Registrador de Dados
0x15
0x35
DDRC
Registrador da Direo
dos Dados
0x14
0x34
PINC
0x13
0x33
PORTD
Registrador de Dados
0x12
0x32
DDRD
Registrador da Direo
dos Dados
0x11
0x31
PIND
0x10
0x30
Avr-Asm-Tutorial
60
http://www.avr-asm-tutorial.net
Lista de abreviaes
As abreviaes usadas foram escolhidas para inclurem a faixa de valores. Pares de registradores so
nomeadas pelo menor dos dois registradores. Constantes em comandos de salto so automaticamente
calculadas das respectivas labels durante a compilao.
Categ.
Register
Constant
Bit
Port
Abrev.
Significa ...
origem
Faixa de Valores
r1
Registradores
comuns
destino
r2
rh
R16..R31
rd
Registrador gmeo
rp
Registrador de ponteiro
ry
Registrador
de
deslocamento
k63
Constante ponteiro
0..63
c127
-64..+63
c255
Constante de 8 bits
0..255
c4096
-2048..+2047
c65535
Endereo de 16 bits
0..65535
b7
Posio do bit
0..7
p1
Porta comum
0..63
pl
0..31
R0..R31
ponteiro
com
Y=R28(R29), Z=R30(R31)