Você está na página 1de 63

Introduoparaoiniciante

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

Porque aprender Assembler?


Assembler ou outras linguagens, esta a questo. Porque eu deveria aprender mais uma linguagem, se
eu j conheo outras linguagens de programao? O melhor argumento: enquanto voc viver na Frana,
poder sobreviver falando Ingls, mas voc nunca se sentir em casa, e a vida fica difcil. Voc pode
apenas continuar desta forma, mas isto no apropriado. Se as coisas ficarem complicadas, voc dever
usar a linguagem corrente do pas
Muitas pessoas j experientes em programao de AVRs e que usam linguagens de alto nvel em seu
trabalho normal, recomendam que os iniciantes comecem aprendendo linguagem assembly. A razo para
isto que, algumas vezes, podem ocorrer certas situaes, como:

se bugs tm que ser analizados,

se o programa faz coisas diferentes das que foram escritas e so esperadas,

se linguagens de alto nvel no suportam o uso de certas caractersticas do hardware,

se rotinas em que a temporizao crtica requerem pores de linguagem assembly,

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.

Assembler de fcil aprendizado


No verdade que a linguagem assembly mais complicada ou no to fcil de compreender quanto
outras linguagens. Aprender linguagem assembly para qualquer tipo de hardware facilita a compreenso
de conceitos de qualquer outro dialeto da linguagem assembly. Aprender outros dialetos depois mais
fcil. Algumas caractersticas so dependentes do hardware, e isto requer alguma familiaridade com os
conceitos de hardware e seus dialetos. O que faz o assembler parecer complicado algumas vezes que
ele requer uma compreenso das funes do controlador do hardware. Linguagens de alto nvel no
permitem a utilizao de caractersticas especiais do hardware, e escondem estas funes.
O primeiro cdigo assembly no parece muito interessante, mas depois de 100 linhas adicionais
programadas, parecer melhor. Programas perfeitos requerem apenas alguns milhares de linhas de
cdigo de exerccio, e otimizao requer bastante trabalho. Os primeiros passos so difceis em qualquer
linguagem. Aps algumas semanas programando, voc dar risada se analisar seu primeiro cdigo.
Alguns comandos em assembler requerem meses de experincia.

AVRs so ideais para se aprender assembler


Programas em assembler so um pouco tolos: o chip executa tudo que voc disser a ele para fazer, e no
pergunta se voc tem certeza se quer sobrescrever isso ou aquilo. Todas as caractersticas de proteo
devem ser programadas por voc, o chip faz exatamente aquilo que lhe comandado, mesmo que no
faa sentido algum. Nenhuma janela o alertar, a menos que voc a tenha programado anteriormente.
Para corrigir erros de digitao to fcil ou complicado como qualquer outra linguagem. Existem erros
bsicos ou mais complicados. Porm: testar os programas nos chips ATMEL muito fcil. Se o chip no
faz o que voc espera, voc pode facilmente adicionar algumas linhas de diagnstico ao cdigo,
reprogram-lo e test-lo. Adeus, programadores de EPROM, lmpadas UV usadas para apagar o
programa, pinos que no se encaixam mais no soquete aps t-los removido uma dzia de vezes.
As mudanas agora so programadas rapidamente, compiladas imediatamente, ou mesmo simuladas no
studio ou checadas no prprio circuito. Nenhum pino tem que ser removido, e nenhuma lmpada de UV te

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

Hardware para programao em Assembler


AVR
Aprender assembler requer um equipamento simples para testar seus programas e ver se eles funcionam
na prtica.
Est pgina mostra dois esquemas fceis que permitem a voc construir em casa o hardware necessrio.
Este hardware realmente fcil de construir. Desconheo qualquer esquema mais fcil do que este para
o seus primeiros passo em software. Se voc quiser fazer mais experimentos, reserve espao para
expanses futuras em sua placa de experimentos.
Se voc no gosta do cheiro de solda, voc pode comprar uma placa pronta para uso. As placas
disponveis esto listadas na seo abaixo.

A interface ISP da famlia de processadores AVR


Antes de entrarmos na prtica, temos que aprender alguns conceitos essenciais no modo de
programao serial da famlia AVR. No, voc no precisa trs diferentes voltagens para programar e ler
a memria flash do AVR. No, voc no precisa de outro microprocessador para programar os AVRs.
No voc no precisa de 10 linhas de E/S para dizer ao chip o que voc gostaria que ele fizesse. E voc
no tem sequer que remover o AVR da sua placa de experimentos, antes de program-lo. fcil assim.
Tudo isto feito pela interface embutida em cada chip AVR, que permite a voc escrever e ler o contedo
da memria flash e EEPROM embutidas. Esta interface trabalha serialmente e precisa de trs linhas de
sinal:
SCK: Um sinal de clock que move os bits a serem escritos na memria para um shift register
interno, que move os bits para serem lidos por outro shift register.
MOSI: Um sinal de dados que envia os bits para serem escritos no AVR,
MISO: Um sinal de dados que recebe os bits lidos do AVR.
Estes trs pinos de sinal so internamente conectados ao sistema de programao apenas se voc deixar
o sinal RESET (algumas vezes chamado de RST ou restart) em nvel zero. Caso contrrio, durante a
operao normal do AVR, estes pinos so portas de E/S programveis como todas as outras. Se voc
quiser usar estes pinos para outros propsitos durante a operao normal, e para programao ISP, voc
ter que faz-lo de forma que estes dois propsitos no conflitem. Normalmente voc deve desacoplar os
sinais por um resistor ou utilizar um multiplexador. O necessrio para o seu caso, depende do seu uso
dos pinos no modo de operao normal. Se voc tiver sorte, pode deixar estes
pinos exclusivamente paa a programao ISP. No necessrio, porm
recomendado para a programao ISP, que voc tenha uma tenso de
alimentao para o hardware no prprio circuito de programao. Isto torna a
programao mais fcil, e requer apenas duas linhas adicionais entre o
programador e a placa AVR. GND o terra comum, VTG (target voltage) a
tenso de alimentao (normalmente 5.0 Volts). Isto totaliza 6 linhas entre o
programador e a placa AVR. A conexo ISP6 , conforme definida pela ATMEL,
mostrada esquerda.
Padres sempre tm padres alternativos. Esta a base tcnica que constitui a
empresa de adaptadores. No nosso caso, o padro alternativo foi projetado
utilizando um ISP10 e foi utilizado na placa STK200. um padro bastante
disseminado, e mesmo o STK500 est equipado com este padro. O padro
ISO10 tem um sinal adicional que aciona um LED vermelho. Este LED sinaliza
que o programador est fazendo o seu trabalho. Uma boa idia. Conecte o LED a
um resistor e fonte de tenso.

Programador para a porta paralela do PC


Agora, aquea o seu ferro de soldar e construiremos seu programador. um esquema bastante fcil e
funciona com peas facilmente encontrveis na sua caixa de experimentos.
Sim, tudo que voc precisa para programar um AVR. O plugue de 25 pinos se liga porta paralela do
seu PC, e o conector ISP de 10 pinos se conecta placa de experimentos AVR. Se voc no tiver um
72LS245, voc pode utilizar tambm o 74HC245 (sem mudanas no circuito) ou um 74LS244/74HC244

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 bem pequena com um ATtiny13, ou

uma mais complicada com um AT90S2313 ou ATmega2313, incluindo uma interface serial
RS232.

Placa experimental com ATtiny13


Esta uma placa bem pequena que permite experimentos com o hardware interno do Attiny13. A figura
mostra

A interface de programao ISP10 esquerda, com o LED de programao ligado a um resistor


de 390 ohms,

o ATtiny13 com um resistor pull-up de10k no pino RESET (pino 1),

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

O ATtiny13 no requer cristal


externo ou gerador de clock, pois
trabalha com o seu gerador RC
interno de 9,6 Mcs/s e, por padro,
com um divisor de clock em 8
(freqncia de clock de 1,2 Mcs/s).
O hardware pode ser construido
em uma pequena placa como a
mostrada na figura. Todos os pinos
do tiny13 so acessveis, e
componentes
externos
ao
hardware, como o LED mostrado,
so facilmente conectados.
Esta placa permite o uso dos
componentes de hardware do
Attiny13, como portas E/S, timers,
conversores AD, etc.

Placa experimental com um AT90S2313/ATmega2313


Para fins de teste, ou se mais pinos de E/S ou comunicao serial forem necessrios, podemos utilizar
um AT90S2313 ou Atmega2313 em uma placa experimental. O esquema mostra

uma pequena fonte de alimenao para coneco a um transformador AC e um regulador de


tenso 5V/1A,

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,

a interface de programao ISP (com o conector ISP10).

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

no precisar da interface de comunicao serial, simplesmente ignore o hardware conectado aos


pinos 2/3 e 14/16,

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.

Se voc usar um ATmega2313 no lugar do AT90S2313, sero feitas as seguintes mundanas:

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.

Placas de programao comerciais para a famlia AVR


Se voc no gosta de hardware feito em casa, e tem algum dinheiro extra e no sabe o que fazer com
ele, voc pode comprar uma placa de programao comercial pronta. Dependendo da quantidade de
dinheiro extra que voc gostaria de gastar, voc pode escolher entre verses mais baratas ou mais caras.
Para o amador, a critrio de seleo deve ser baseado em:

preo,

interface com o PC (de preferncia USB; menos conveniente ou durvel: RS232; requer software
adicional para programao: porta paralela do PC),

suporte a novos dispositivos (atualizaes so necessrias de tempos em tempos, caso contrrio


voc montar em um cavalo morto),

caractersticas do hardware (depende de suas necessidades para os prximos cinco anos).

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

uma placa com alguns soquetes (para dispositivos de 8, 20, 28 e 40 pinos),

oito chaves e LEDs, conectados permanentemente s portas D e B,

um LCD com interface padro de 14 pinos,

uma opo para conectar uma SRAM de 28 pinos,

uma interface RS232 para comunicao,

um cabo de interface com a porta paralela do PC em um lado e um ISP de 10 pinos do outro.

Programao em HV (alta voltagem) no suportada.


A placa no pode ser programada do Studio, o software de programao no mais suportado, e voc
deve usar programas externos capazes de programar via porta paralela.
Se algum lhe oferecer esta placa, pegue-a apenas de graa, e se voc estiver acostumado a utilizar os
softwares necessrios.

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),

Conexes ISP6 e ISP10 para programao ISP,

oscilador com freqncia e tenses de alimentao programveis,

chaves e LEDs configurveis,

um conector RS232C (UART),

uma EEPROM-Flash serial (somente as placas mais antigas),

acesso a todas as portas via conectores de 10 pinos.

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

Ferramentas para programao assembly


AVR
Quatro ferramentas bsicas so necessrios para programao em assembly. Estas ferramentas so:

o editor,

o compilador,

a interface para programao do chip, e

o simulador.

Para realizar estas tarefas, existem dois caminhos:


1. todos as ferramentas em um s programa,
2. cada tarefa realizada por um programa especfico, e os resultados so armazenados em
arquivos especficos.
Normalmente a primeira opo escolhida. Porm, como isto um tutorial, e voc deve compreencer o
mecanismo primeiro, comearemos descrevendo a segunda opo.

De um arquivo texto a palavras de instruo para a


memria flash
O editor
Os programas assembler so escritos com um editor. O editor simplesmente tem que criar e editar texto
ASCII. Ento, basicamente, qualquer editor simples serve.
Algumas caractersticas do editor podem ter efeitos positivos:

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

Assim, qualquer programa de texto que


voc quiser, escolha sua. Os
exemplos a seguir foram escritos no
wavrasm, um editor fornecido pela
ATMEL h algum tempo.
No
campo
do
editor
simples,
escrevemos as nossas diretivas e
comandos de assembler. altamente
recomendado que estas linhas sejam
acompanhadas por alguns comentados
(comeando por ;). Entender o que
voc havia planejado aqui so
importantes na depurao posterior.
Agora armazene o arquivo texto,
chamado TEST.ASM, em um diretrio
dedicado, usando o menu File. O
programa assembly est completo
agora
Se voc gostaria de ver o que destaque pela sintaxe significa, coloquei a captura de uma tela do AVR
editor aqui.
O
editor
reconhece
os
comandos automaticamente e
usa diferentes cores (destaque
da sintaxe) para sinalizar ao
usurio constantes e erros de
digitao nestes comandos (em
preto). O cdigo armazenado
no arquivo .asm basicamente
o mesmo, pois as cores no so
armazenadas no arquivo.
No tente encontrar este editor
ou seu autor; o editor virou
histria e no mais mantido.

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,

Freqncia do clock 4 MHz.

Na seo de seleo de dispositivos,


selecionamos o tipo de chip desejado.
A frequncia correta deve ser
selecionada, se voc deseja simular
temporizao correta.
Para podermos ver o contedo de
alguns registradores e o que o status
atual do processador, selecionamos
VIEW PROCESSOR e REGISTERS.
Agora a imagem deve ser a seguinte.
A janela do processador mostra vrios
valores, como onde o contador de
comando est, os registradores de
flag de status, e a informao sobre
temporizao (aqui a um clock de 1
MHz). O cronmetro por ser usado
para fazer uma medida exata do
tempo necessrio para executar
rotinas etc.

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

Aps o primeiro passo ser executado, a janela do processador


ficaria como ao lado.
O contador de programa (Program Counter), mostrado na janela
do processador, est no passo 1, o contador de ciclo em 2
(RJMP precisa de dois ciclos para executar). Com clock de 1
MHz, dois microssegundos foram gastos, os flags e
registradores no foram alterados. A janela com a arquivo texto
fonte mostra um ponteiro no prximo comando a ser executado.
Pressionar F11 novamente executa o prximo comando, o
registrador mp (=R16) ser setado para 0xFF. Agora a janela de
registradores deve destacar esta mudana.
O novo valor do
registrador
R16

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

eles podem ser usados diretamente por comandos assembler,

operaes com o seu contedo requerem somente uma palavra de comando,

eles so conectados diretamente unidade central de processamento chamada acumulador,

eles so origem e destino para clculos.

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

vlido para todos os registradores.


Alm do comando LDI, voc descobrir que esta restrio de classes de registradores ocorre tambm
com os seguintes comandos:

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.

CPI Rx,K ; Compara o contedo do registrador Rx com o valor constante K,

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,

SER Rx ; Seta todos os bits no registrador Rx para um (igual a LDI Rx,255),

SUBI Rx,K ; Subtrai a constante K do contedo do registrador Rx e armazena o resultado no


registrador Rx.

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

L/Escreve do endereo X, no altera o ponteiro

LD R1,X ou ST X,R1

X+

L/Escreve de/para endereo X e incrementa o ponteiro por um

LD R1,X+ ou ST X+,R1

-X

Decrementa o ponteiro em um e l/escreve de/para o novo endereo LD R1,-X ou ST -X,R1

De forma similar, voc pode usar Y e Z para este propsito.


H somente um comando para acesso leitura dos dados do programa. Ele definido pelo par de
ponteiros Z e chamado LPM (Load from Program Memory, carregar da memria do programa). O
comando copia o byte no endereo Z da memria do programa para o registrador R0. Como a memria
do programa organizada na forma de palavras (um comando em um endereo consiste de 16 bits ou
dois bytes ou uma palavra), o bit menos significativo seleciona o byte inferior ou superior (0=inferior,
1=superior). Por causa disto, o endereo original deve ser multiplicado por 2 e o acesso limitado a 15
bits ou 32kb da memria do programa. Desta forma:

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.

Recomendao para uso dos registradores

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.

A melhor localizao para contadores de 16 bits R25:R24.

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"

e todos os registradores de 8515 estaro definidos e facilmente acessveis.


As portas normalmente so organizadas como nmeros de 8 bits, mas podem manipular 8 bits individuais
que no tm a ver uns com os outros. Se estes bits tm um significado, eles podem ter seu prprio nome
associado no arquivo include, para permitir a manipulao deste bit. Graas conveno dos nomes,
voc no tem que lembrar a posio destes bits. Estes nomes so definidos nos data sheets e esto
includos nos arquivos include, tambm. Eles so fornecidos aqui nas tabelas das portas.
Como exemplo, o registrador de controle geral MCU, chamado MCUCR, consiste de um nmero de bits
de controle individuais que controlam algumas caractersticas gerais do chip (veja a descrio em
MCUCR para maiores detalhes). uma porta, com 8 bits de controle e seus prprios nomes (ISC00,
ISC01, ...). Quem quiser mandar o seu AVR para um sono mortal precisa saber pelo data sheet como
setar os bits respectivos. Assim:
.DEF MeuRegistradorPreferido = R16
LDI MeuRegistradorPreferido, 0b00100000
OUT MCUCR, MeuRegistradorPreferido
SLEEP

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.

Deatlhes de portas relevantes do AVR


A tabela a seguir mostra as portas mais usadas. Nem todas portas esto listadas aqui, algumas do MEGA
e AT90S4434/8535 foram omitidas. Se houver dvida, verifique as referncias originais.
Componente

Nome da porta

Registrador da Porta

Acumulador

SREG

Registrador de Status

Pilha (stack)

SPL/SPH

Stackpointer (apontador de pilha)

SRAM Externa/Interrupo Externa MCUCR

Registrador de Controle Geral MCU

Interrupo Externa

GIMSK

Registrador de Interrupo Mascarado

GIFR

Registrador de Flag de Interrupo

TIMSK

Registrador de Interrupo de Timer Mascarada

TIFR

Registrador de Interrupo de Flag de Timer

TCCR0

Registrador controle de de Timer/Contador 0

TCNT0

Timer/Contador 0

TCCR1A

Registrador controle de de Timer/Contador 1 A

TCCR1B

Registrador controle de de Timer/Contador 1 B

TCNT1

Timer/Contador 1

OCR1A

Registrador Comparador de Sada 1 A

OCR1B

Registrador Comparador de Sada 1 B

ICR1L/H

Registrador de Captura de Entrada

Timer Watchdog

WDTCR

Registrador de Controle do Timer Watchdog

EEPROM

EEAR

Registrador de endereo da EEPROM

EEDR

Registrador de dados da EEPROM

EECR

Registrador de controle da EEPROM

SPCR

Registrador de controle de perifricos Seriais

SPSR

Registrador de status de perifricos Seriais

SPDR

Registrador de dados de perifricos Seriais

UDR

Registrador de dados da UART

USR

Registrador de status da UART

UCR

Registrador de controle da UART

UBRR

Registrador de velocidade (baud rate) da UART

Comparador analgico

ACSR

Registrador de status e controle do comparador


analgico

Portas de E/S

PORTx

Registrador de porta de sada

DDRx

Registrador de direo da porta

PINx

Registrador de porta de entrada

Interrupo de Timer
Timer 0
Timer 1

SPI

UART

O registrador de status como a porta mais utilizada


De longe, a porta mais freqentemente usada o registrador de status com seus 8 bits. Normalmente o
acesso a esta porta feito somente por alterao dos bits pela CPU ou acumulador, alguns acessos so
por leitura ou alterao dos bits na porta, e em raros casos possvel manipular estes bits diretamente
(utilizando os comandos assembler SEx ou CLx, onde x a abreviao do bit). A maioria destes bits
alterada por operaes de teste de bit, comparao ou clculos. A seguinte lista tem todos os comandos
em assembler que podem alterar os bits de status, dependendo do resultado da execuo.

Avr-Asm-Tutorial

Bit

18

Clculo

Lgico

http://www.avr-asm-tutorial.net

Comparao

Bits

Rolagem

Outro

ADD, ADC, ADIW, DEC,


INC, SUB, SUBI, SBC,
SBCI, SBIW

AND, ANDI, OR, CP, CPC, CPI BCLR Z,


ASR, LSL,
ORI, EOR, COM,
BSET Z,
LSR, ROL,
NEG, SBR, CBR
CLZ, SEZ, ROR
TST

CLR

ADD, ADC, ADIW, SUB,


SUBI, SBC, SBCI, SBIW

COM, NEG

ADD, ADC, ADIW, DEC,


INC, SUB, SUBI, SBC,
SBCI, SBIW

AND, ANDI, OR, CP, CPC, CPI BCLR N,


ASR, LSL,
ORI, EOR, COM,
BSET N,
LSR, ROL,
NEG, SBR, CBR
CLN, SEN, ROR
TST

CLR

ADD, ADC, ADIW, DEC,


INC, SUB, SUBI, SBC,
SBCI, SBIW

AND, ANDI, OR, CP, CPC, CPI BCLR V,


ASR, LSL,
ORI, EOR, COM,
BSET V,
LSR, ROL,
NEG, SBR, CBR
CLV, SEV, ROR
TST

CLR

SBIW

BCLR S,
BSET S,
CLS, SES

ADD, ADC, SUB, SUBI,


SBC, SBCI

NEG

CP, CPC, CPI BCLR H,


BSET H,
CLH, SEH

BCLR T,
BSET T,
BST, CLT,
SET

BCLR I,
BSET I,
CLI, SEI

RETI

CP, CPC, CPI BCLR C,


BSET C,
CLC, SEC

Detalhes das portas


Detalhes das portas mais comuns so mostrados na tabela extra (veja anexo).

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.

Para que propsitos posso usar a SRAM?


Alm de simples armazenagem de valores, a SRAM oferece outras possibilidades de uso. No apenas o
acesso com endereos fixos pssvel, como tambm o uso de ponteiros, de forma que o acesso flutuante
a localizaes subsequentes pode ser programado. Desta forma voc pode construir buffers em anel para
armazenagem temporria de valores ou tabelas calculadas. Isto no feito frequentemente com
registradores, pois eles so muito poucos e acesso fixo preferido.
Outra forma de acesso utilizando um offset para um endereo de incio fixo em um dos ponteiros. Neste
caso, o endereo fixo armazenado no ponteiro, e um valor constante adicionado a este endereo e os
acesso de leitura e escrita so feitos a esse endereo com um offset. Com este tipo de acesso, as tabelas
so melhores utilizadas.
O uso mais interessande para a SRAM a chamada pilha (stack). Voc coloca (empurra, push) valores
para a pilha, seja um registrador, um endereo de retorno aps o fim de uma sub-rotina, ou o endereo de
retorno aps uma interrupo disparada por hardware.

Como usar a SRAM?


Para copiar um valor para uma localizao da memria SRAM, voc tem que definir o endereo. O
endereamento da SRAM comea em 0x0060 (notao hexa) at o fim da SRAM fsica no chip (no
AT90S8515, o endereo mais alto da SRAM 0x025F). Com o comando
STS 0x0060, R1

o contedo do registrador R1 copiadao para o primeiro endereo da SRAM. Com


LDS R1, 0x0060

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

.EQU MeuEnderecoPreferido= 0x0060


STS MeuEnderecoPreferido, R1

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)

Em algum lugar depois no programa, para acessar o endereo 0x0062:


STD Y+2, MeuRegistradorPreferido

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 uso da SRAM como pilha


O uso mais comum da SRAM como pilha. A pilha uma torre de blocos de madeira. Cada bloco
adicional vai no topo da torre, e cada chamada remove o bloco superior da torre. Esta estrutura
chamada de Last-In-First-Out (o primeiro a entrar o ltimo a sair LIFO), ou mais fcil: o ltimo a ir no
topo, ser o primeiro a sair.

Definindo SRAM como pilha


Para usar a SRAM como pilha, devemos ajustar o ponteiro de pilha (stack pointer) primeiro. O ponteiro de
pilha um ponteiro de 16 bits, acessvel como uma porta. O registrador duplo chamado de SPH:SPL.
SPH armazena o byte mais significativo, e o SPL, o menos significativo. Isto verdadeiro apenas se o
AVR tiver mais de 256 bytes de SRAM. Caso contrrio, SPH indefinido, no pode e no deve ser usado.
Vamos assumir que temos mais de 256 bytes nos exemplos a seguir.
Para contruir a pilha, o ponteiro de pilha carregado com o endereo mais alto da SRAM. (No nosso
caso, a torre cresce para baixo, em direo aos endereos menores!)
.DEF MeuRegistradorPreferido = R16
LDI MeuRegistradorPreferido, HIGH(RAMEND) ; Byte Superior
OUT SPH,MeuRegistradorPreferido ; para o ponteiro de pilha
LDI MeuRegistradorPreferido, LOW(RAMEND) ; Byte inferior
OUT SPL,MeuRegistradorPreferido ; para o ponteiro de pilha

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)

O arquivo 8515def.inc includo atravs da diretiva de assembler


.INCLUDE "C:\algumlugar\8515def.inc"
no incio do nosso cdigo fonte em assembler.
Ento definimos a pilha agora, e no temos mais que nos preocupar sobre o ponteiro da pilha, porque as
manipulaes do ponteiro so automticas.

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

o contedo ser necessrio novamente algumas linhas de cdigo depois,

todos os registradores esto em uso, e se

no h como armazenar aquele valor em nenhum outro lugar.

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

Aqui a execuo para para o label AlgumLugar em algum lugar do cdigo,


AlgumLugar: ; este o endereo de salto
[...] Aqui fazemos alguma coisa
[...] e aqui terminamos o que queramos fazer e saltamos de volta para o local onde essa rotina foi chamada:
RET

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.

Bugs com a operao de pilhas


Para o iniciante, h uma grande possibilidade de bugs, aps aprender a usar a pilha.
Muito inteligente o uso da pilha sem setar primeiro o ponteiro da pilha. Como o valor deste ponteiro
zero no incio do programa, o ponteiro aponta para o registrador R0. Colocar algo na pilha resulta em
escrever neste registrador, sobrescrevendo qualquer contedo que ali estivesse. Um outro push na pilha,
e a pilha vai gravar em 0xFFFF, uma posio indefinida (se voc no tiver SRAM externa). RCALL e RET
retornaro um endereo estranho na memria. E tenha certeza: no haver nenhum aviso, nenhuma
janela indicando Acesso ilegal memria localizao xxxx.

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.

Controlando a execuo seqencial de um programa


O que acontece durante um reset?
Quando a tenso de trabalho de um AVR sobe e o processador inicia o seu trabalho, o hardware dispara
uma seqncia de reset. O contador de passos do programa zerado. Neste endereo, a execuo
sempre inicia. Aqui temos que ter nossa primeira palavra de cdigo. Mas este endereo pode ser ativado
tambm de outras formas:

Durante um reset externo via pino de reset, o processador reiniciado.

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

para evitar o reset.


Aps a execuo de um reset, e restabelecimento dos registradores e portas para seus valores padro, o
cdigo no endereo 0000 lido pela parte de execuo do processador, e executado. Durante esta
execuo o contador de programa (PC, program counter) j incrementado em um e a prxima palavra
do cdigo j lida para o buffer de busca de cdigo (Busca durante Execuo). Se o comando executado
no requer um salto para outra localidade no programa, o prximo comando executado imediatamente.
por isso que os AVRs executam extremamente rpido, cada ciclo de clock executa um comando (se
no ocorrerem saltos).
O primeiro comando de um executvel est sempre localizado no endereo 0000. Para dizer ao
compilador que nosso cdigo fonte inicia aqui e agora, uma diretiva especial pode ser colocada no incio,
antes do primeiro cdigo:
.CSEG
.ORG 0000

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

O terceiro segmento a poro SRAM do chip.


.DSEG

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.

Execuo linear do programa e desvios


A execuo de um programa sempre linear, se nada mudar a execuo sequencial. Estas mudanas
so a execuo de uma interrupo, ou instrues de desvio.
Os desvios normalmente so dependentes de alguma condio, chamados portanto desvios condicionais.
Como exemplo, vamos imaginar que construmos um contador de 32 bits utilizando os registradores R1 a
R4. O byte menos significativo R1 incrementado. Se o registrador estoura (overflow) durante esta
operao (255 + 1 = 0), temos que incrementar R2 similarmente. Se R2 estoura, incrementamos R3, e
assim por diante.
O incremento por um feito pela instruo INC. Se um estouro (overflow) ocorre durante esta execuo
de INC R1, o bit zero do registrador de status setado para um (o resultado da operao zero). O carry
do registrador de status, usualmente setado em overflows, no alterado durante um INC. Isto no para
confundir o iniciante, mas o carry usado para outros propsitos. A flag de Zero ou bit de zero neste caso
suficiente para detectar um estouro. Se no ocorrer nenhum estouro, mantemos a seqncia de
contagem.
Se o bit-Zero for setado, devemos executar um incremento adicional nos outros registradores. Para
confundir o iniciante, o comando de desvio que temos que usar no chamado BRNZ mas BRNE
(Branch if Not Equal, Desviar se no for igual). Uma questo de gosto...
A seqncia de contagem inteira do contador de 32 bits ento deve ficar assim:
INC R1
BRNE Continue32
INC R2
BRNE Continue32
INC R3
BRNE Continue32
INC R4
Continue32:

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.

Temporizao durante a execuo do programa


Como mencionado anteriormente, o tempo necessrio para executar uma instruo igual ao tempo de
ciclo do clock do processador. Se o processador roda a 4 MHz. Ento uma instruo requer 1/4 s ou
250 ns, e a 10 MHz, apenas 100 ns. O clculo do tempo to preciso quanto o cristal do clock. Se voc
precisa temporizao exata, um AVR a melhor soluo. Note que h poucos comandos que necessitam
de dois ou mais ciclos, e.g. As instrues de desvio (se este ocorre) ou seqncias de leitura/escrita na

Avr-Asm-Tutorial

25

http://www.avr-asm-tutorial.net

SRAM. Veja a tabela de instrues para detalhes.


Para definir o tempo exato, deve haver uma oportunidade para no fazer nada e retardar a execuo do
programa. Voc pode utilizar outras instrues para fazer nada, mas mais inteligente a utilizao do
comando NOP (NO oPeration, sem operao). Esta a instruo mais intil:
NOP

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.

Macros e execuo do programa


Freqentemente voc tem que escrever seqncias de cdigo idnticas ou similares em diferentes
ocasies no seu cdigo fonte. Se voc no quiser escrev-la uma vez e saltar para ela via chamada de
subrotina, voc pode usar um macro para evitar escrever a mesma seqncia diversas vezes. Macros so
sequncias de codigos, escritas e testadas uma vez, e inseridas no cdigo por seu nome macro. Como
exemplo, vamos imaginar que precisamos retardar a execuo do programa vrias vezes de 1 S com
clock de 4 MHz. Ento definimos uma macro em algum lugar do cdigo:
.MACRO Retardo1
NOP
NOP
NOP
NOP
.ENDMACRO

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

[...] continuando com o cdigo fonte

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

Em nosso cdigo, copiamos o endereo da tabela para o ponteiro Z:


LDI ZH,HIGH(MinhaTabela)
LDI ZL,LOW(MinhaTabela)

e adicionar o estado atual da porta B (em R16) a este endereo.


ADD ZL,R16
BRCC SemEstouro
INC ZH
SemEstouro:

Agora podemos saltar s localidades na tabela, da mesma forma que chamamos uma subrotina:
ICALL

ou pular, sem possibilidade de retorno:


IJMP

Avr-Asm-Tutorial

27

http://www.avr-asm-tutorial.net

O processador carrega o contedo do par de registradores Z no contador de programa e continua a


operao a partir da. Mais inteligente que fazer desvios e mais desvios?

Interrupes e a execuo do programa


Frequentemente temos que reagir a condies do hardware e outos eventos. Uma exemplo, uma
alterao em um pino de entrada. Voc pode programar uma reao como um loop, sempre verificando
se houve alterao em um pino. Este mtodo chamado de busca, como uma abelha voando em crculos
procurando por novas flores. Se voc tem que detectar pulsos curtos com durao inferior a
microssegundos, este mtodo intil. Neste caso, voc ter que programar uma interrupo.
Uma interrupo disparada por alguma condio de hardware. Esta condio tem que ser habilitada
primeiro, todas as interrupes de hardware so disabilitadas por padro, no momento do reset. Os bits
respectivos da porta que habilitam a resposta interrupo devem ser habilitados primeiro. O
processador tem um bit no seu registrador de status que o habilita a responder interrupo de qualquer
componente, a flag de habilitao de interrupo (Interrupt Enable Flag). Habilitar a resposta s
interrupes requer o seguinte comando:
SEI ; Seta bit de habilitao de Interrupo

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

Hardware Reset, Power-On-Reset, Watchdog Reset

INT0

0001

0001

0001

Mudana de nvel no pino externo INT0

INT1

0002

0002

Mudana de nvel no pino externo INT1

TIMER1CAPT

0003

0003

Evento de captura no Timer/Contador 1

TIMER1COMPA

0004

Timer/Contador 1 = Valor de comparao A

TIMER1 COMPB

0005

Timer/Contador 1 = Valor de comparao B

TIMER1 COMP1

0004

Timer/Contador 1 = Valor de comparao 1

TIMER1 OVF

0005

0006

Estouro (overflow) de Timer/Contador 1

TIMER0 OVF

0006

0002

0007

Estouro (overflow) de Timer/Contador 0

SPI STC

0008

Transmisso Serial Completa

UART TX

0007

0009

Caractere UART disponvel no buffer de recepo

UART UDRE

0008

000A

Transmisso UART esgotada

UART TX

0009

000B

UART totalmente enviada

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

A segunda forma habilitar o bit I pela instruo


SEI ; Habilita bit de Interrupo
RET ; Retorna

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.

Sistemas numricos em assembler


Os seguintes formatos numricos so comuns em assembler:

Nmeros positivos inteiros (Bytes, Palavras, etc.),

Nmeros com sinal (inteiros),

Dgitos codificados em binrio (BCD, Binary Coded Digits)

BCDs compactados,

Nmeros formatados em ASCII.

Nmeros positivos inteiros (bytes, palavras, etc.)


O menor nmero inteiro a ser manipulado em assembler um byte com oito bits. Ele codifica nmeros
entre 0 e 255. Tais bits encaixam perfeitamente em um registrador da MCU. Todos os nmeros maiores
devem ser baseados neste formato bsico, usando mais do que um registrador. Dois bytes formam uma
palavra, word, (que vai de 0 a 65.535), trs bytes formam uma palavra maior (vai de 0 a 16.777.215) e
quatro bytes formam uma palavra dupla, double word (de 0 a 4.294.967.295).
Os bytes de uma palavra ou palavra dupla podem ser armazenados no registrador que voc quiser.
Operaes com estes bytes so programados byte por byte, ento voc no tem que se preocupar em
coloc-los em ordem. Para formar um conjunto de uma palavra dupla, podemos armazenar assim:
.DEF r16 = dw0
.DEF r17 = dw1
.DEF r18 = dw2
.DEF r19 = dw3

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.

Nmeros com sinal (inteiros)


Algumas vezes, mas em raros casos, voc precisa calcular com nmeros negativos. Um nmero negativo
definido interpretando o bit mais significativo de um byte como um bit de sinal. Se for 0, o nmero
positivo. Se for 1, o nmero negativo. Se for negativo, usualmente no armazenamos o nmero em sua
forma normal, mas usamos seu valor invertido. Invertido significa que -1 como um byte inteiro no
escrito 1000.0001 mas 1111.1111. Isto significa: subtraia 1 de 0 e esquea o estouro (overflow). O
primeiro bit o bit de sinal, sinalizando que este um nmero negativo. O porqu deste formato diferente
(subtrair o nmero negativo de 0) ser usado fcil de entender. Somar -1 (1111.1111) e +1 (0000.0001)
d exatamente zero, se voc esquecer o estouro que ocorre durante esta operao (o nono bit).
Em um byte, o maior nmero inteiro +127 (binrio 0,111111), o menor -128 (binrio 1,0000000). Em
outras linguagens de computador, este formato numrico chamado de inteiro curto (short integer). Se
voc precisar de uma faixa de valores maior, voc pode adicionar outro byte para formar um nmero
inteiro, indo de +32.767 at -32.768, enquanto que quatro bytes fornecem uma faixa de +2.147.483.647
at -2.147.483.648, usualmente chamado de Inteiro longo (LongInt) ou Inteiro Duplo (DoubleInt).

Dgitos Codificados em Binrio, BCD (Binary Coded Digits)


Nmeros inteiros positivos ou com sinal nos formatos assima utilizam o espao disponvel da forma mais
eficiente. Outra formato numrico, menos denso, mas fcil de trabalhar, armazenar os nmeros
decimais em um byte para cada dgito. O dgito decimal armazenado em sua forma binrio em um byte.
Cada dgito de 0 a 9 precisa de quatro bits (0000 a 1001), os quatro bits superiores so zeros,
desperdiando muito espao em cada byte). Por exemplo, para mostrarmos o nmero 250, precisamos de
no mnimo trs bytes:

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

;Instrues para codificar:


LDI R16,2
LDI R17,5
LDI R18,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

; Instrues para codificar


LDI R17,0x02 ; Byte superior
LDI R16,0x50 ; Byte inferior

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.

Nmeros em formato ASCII


Muito similar ao formato BCD a armazenagem de nmeros em formato ASCII. Os dgitos 0 a 9 so
armazenados utilizando sua representao ASCII (ASCII = American Standard Code for Information
Interchange, Padro de Cdigos Americanos para Intercmbio de Informao). O ASCII um formato
muito antigo, desenvolvido e otimizado para escritores de teletipo, desnecessariamente complicado para
utilizao em computadores (voc sabe o que um caractere chamado End Of Transmission (fim da
transmisso) EOT significava quando foi inventado?), muito limitado para outras lnguas que no o ingls
(somente 7 bits por caractere), ainda usado em comunicaes hoje devido aos esforos limitados de
programadores de sistemas operacionais no sentido de mudar para sistemas de caracteres mais efetivos.
Este sistema antigo s ultrapassado pelo conjunto de caracteres de 5 bit Europeu chamado conjunto
Baudot ou o cdigo Morse, ainda em uso por algumas pessoas com dedos rpidos.
Dentro do sistema de codificao ASCII, o dgito decimal 0 representado pelo nmero 48 (hexa 0x30,
binrio 0b0011.0000), dgito 9 57 (hexa 0x39, binrio 0b0011.1001). O ASCII no foi projetado para ter
estes nmeros no incio do conjunto de cdigo, pois j h alguns caracteres de comando como o EOT
mencionado para teletipo. Ento temos que adicionar 48 a um BCD (ou setar os bit 4 e 5 para 1) para
converter BCD para ASCII. Os nmeros formatados em ASCII precisam do mesmo espao de
armazenagem que o BCD. Carregar 250 para um conjunto de registradores representando este nmero
ficaria desta forma:
LDI R18,'2'
LDI R17,'5'
LDI R16,'0'

A representao ASCII destes caracteres so escrito nos registradores.

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

Converter um ASCII de volta para BCD fcil. A instruo


ANDI R16,0x0F

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

Inverter todos os bits de um byte chamado de Complemento de Um.


COM 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

fcil dividir nmeros grandes. Voc v que aprender assembler no TO complicado.


A ltima instruo que desloca quatro bits em um nico passo normalmente usado em BCDs
compactados. Esta instruo desloca um nibble inteiro da posio superior para a inferior e vice-versa.
Em nosso exemplo, precisamos deslocar o nibble superior para o nibble inferior. No lugar de usarmos
ROR R1
ROR R1
ROR R1
ROR R1

podemos fazer isso com um simples


SWAP R1

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.

Somando, subtraindo e comparando


As seguintes operaes de clculo so complicadas demais para os iniciantes e demonstram que
assembler apenas para experts extremos. Leia por seu prprio risco!
Para comear a complicar, somaremos dois nmeros de 16 bits, em R1:R2 e R3:R4. (Nesta notao,
queremos dizer que o primeiro registrador o byte mais significativo, o segundo o menos significativo).
ADD R2,R4 ; primeiro soma os dois bytes inferiores
ADC R1,R3 ; depois os dois bytes superiores

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

Se a flag de carry estiver setada agora, R1:R2 maior que R3:R4


Agora adicionamos coisas mais complicadas. Comparemos o contedo de R16 com a constante
0b10101010.

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

Um pouco mais curto:


LDI R16,0x66
ADD R2,R16
ADD R2,R3
BRCC NoCy
INC R1
ANDI R16,0x0F
NoCy:
BRHC NoHc
ANDI R16,0xF0
NoHc:
SUB R2,R16

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

menos complicado, onde est o truque?

Converso de formatos numricos


Todos os formatos numricos podem ser convertidos. A converso entre BCD e ASCII e vice-versa j foi
mostrada acima (Manipulao de bits).
A converso para BCDs compactados no muito complicada tambm. Primeiro temos que copiar o
nmero para outro registrador. Com o valor copiado, trocamos os nibbles usando a instruo SWAP
(trocar) para trocar o superior com o inferior. A parte superior zerada, e.g. Fazendo AND com 0x0F.
Agora temos o BCD do nibble superior e podemos us-lo como BCD ou setar bit 4 e 5 para convert-lo
em um caractere ASCII. Depois disso, copiamos novamente o byte e tratamos o nibble inferior sem fazer
SWAP para obter o BCD inferior.
Um pouco mais complicada a converso de dgitos BCD para binrio. Dependendo dos nmeros a
serem manipulados, primeiramente liberamos os bytes necessrios que recebero o resultado da
converso. Ento iniciamos com o dgito BCD mais alto. Antes de adicionar este resultado, multiplicamos
o resultado por 10. (Note que no primeiro passo isto no necessrio, pois o resultado zero).
Para fazermos esta multiplicao por 10, copiamos o resultado para algum lugar. Depois multiplicamos o
resultado por 4 (duas rolagens esquerda). Adicionar o nmero anteriormente copiado resulta na
multiplicao por 5. Agora uma multiplicao por 2 (uma rolagem esquerda) chega ao resultado
decaduplicado. Finalmente adicionamos o BCD e repetimos este algoritmo at todos os dgitos estarem
convertidos. Se, em uma destas operaes, ocorrer um carry (transporte) do resultado, o BCD grande
demais para ser convertido. Este algoritmo funciona com nmeros de qualquer comprimento, desde que
haja registradores suficientes.
A converso de binrios para BCD um pouco mais complicada. Se convertermos um binrio de 16 bits
podemos subtrair 10.000 (0x2710) at que ocorra um estouro, obtendo o primeiro dgito. Ento repetimos
com 1000 para obtermos os segundo dgito. E assim por diante com 100 (0x0064) e 10 (0x000A), e ento
o que remanescente o ltimo dgito. As constantes 10.000, 1.000, 100 e 10 podem ser colocados na
memria do programa em uma tabela de palavras, organizada da seguinte forma:
DezTab:
.DW 10000, 1000, 100, 10

e podem ser lidas as palavras com uma instruo LPM da tabela.


Uma alternativa uma tabela que contm o valor decimal de cada bit do binrio de 16 bits, e.g.,
.DB 0,3,2,7,6,8
.DB 0,1,6,3,8,4
.DB 0,0,8,1,9,2
.DB 0,0,4,0,9,6
.DB 0,0,2,0,4,8 ; e assim por diante at
.DB 0,0,0,0,0,1

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 com o dgito menos significativo do segundo nmero e


adicionamos ao resultado.

Multiplicamos o primeiro nmero por 10 e pelo prximo dgito do segundo nmero e adicionamos ao
resultado.

Multiplicamos o primeiro nmero por 100, e ao terceiro dgito, 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?

Programa em Assembler AVR


O cdigo fonte a seguir demonstra a realizao de multiplicao em assembler.
; Mult8.asm multiplica dois nmeros de 8 bit para chegar a um resultado de 16 bits.
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
; Fluxo da multiplicao
;
; 1. O binrio a ser multiplicado deslocado no sentido do carry. Se for um, o nmero adicionado ao resultado, se no for
um, o nmero no adicionado.
; 2. O nmero binrio multiplicado por 2, rotacionando uma posio esquerda, e preenchendo a posio vazia com 0.
; 3. Se o binrio com que ser multiplicado no for zero, o ciclo de multiplicao repetido. Se for zero, a multiplicao est
terminada.
;
; Registradores usados
;
.DEF rm1 = R0 ; Nmero binrio a ser multiplicado (8 Bit)
.DEF rmh = R1 ; Armazm intermedirio
.DEF rm2 = R2 ; Nmero binrio com que o primeiro ser multiplicado (8 Bit)
.DEF rel = R3 ; Resultado, LSB (16 Bit)
.DEF reh = R4 ; Resultado, MSB
.DEF rmp = R16 ; Registrador multi propsitos para carregamento
;
.CSEG
.ORG 0000
;
rjmp START
;
START:
ldi rmp,0xAA ; exemplo binrio 1010.1010
mov rm1,rmp ; para o primeiro registrador
ldi rmp,0x55 ; examplo binrio 0101.0101
mov rm2,rmp ; para o segundo registrador
;
; Aqui iniciamos a multiplicao de um dos binrios em rm1 e rm2, o resultado vai para reh:rel (16 bits)
;
MULT8:
;
; Zera valores de incio
clr rmh ; zera armazm intermedirio
clr rel ; zera registradores de resultado
clr reh
;
; Aqui iniciamos o ciclo de multiplicao
;
MULT8a:
;
; Passo 1: Rotaciona o bit mais baixo do nmero 2 para a flag de carry (divide por 2, rotaciona um zero no bit 7)
;
clc ; zera carry
ror rm2 ; bit 0 vai para o carry, bit 1 a 7 vo uma posio para direita, carry vai para o bit 7
;
; Passo 2: Deciso dependendo se foi 0 ou 1 que foi rotacionado para o carry
;
brcc MULT8b ; pula por cima da adio, se o carry for 0
;
; Passo 3: Soma 16 bits em rmh:rml ao resultado, com estouro do LSB para o MSB
;
add rel,rm1 ; soma o LSB de rm1 ao resultado
adc reh,rmh ; soma carry e MSB de rm1
;
MULT8b:
;

Avr-Asm-Tutorial

36

http://www.avr-asm-tutorial.net

; Passo 4: Multiplicar rmh:rm 1 por 2 (16 bits, desvio esquerda)


;
clc ; zera carry (clear carry bit)
rol rm1 ; rotaciona o LSB esquerda (multiplica por 2)
rol rmh ; rotaciona o carry para o MSB e o MSB uma casa esquerda
;
; Passo 5: Checa se h ainda nmeros 1 no binrio 2, se sim, continua multiplicando
;
tst rm2 ; todos os bits zero?
brne MULT8a ; se no, v para o loop
;
; Fim da multiplicao, resultado em reh:rel
;
; Loop sem fim
;
LOOP:
rjmp loop

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.

O cdigo-objeto foi aberto, e o


cursor colocado na primeira
instruo executvel. F11
executa um passo.

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).

Com o carry era 1, o


contedo
dos
registradores R2:R1
somado ao par de
registradores R4:R3
(vazio),
resultando
em 0x00AA nestes.

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.

No foi to complicado, basta lembrar na similaridade com as operaes decimais. A multiplicao em


binrio muito mais fcil do que decimal.

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

Passos do programa durante a diviso


Durante a execuo do programa os seguintes passos so seguidos

Definio e pr-ajuste dos registradores com os binrios de teste,

pr-ajuste do registrador intermedirio e o par de registradores de resultado (os registradores de


resultado so pr-ajustados para 0x0001! Aps 16 rotaes, a rolagem do 1 para fora interrompe as
divises.),

o binrio de 16 bits em rd1h:rd1l rotacionado para o registrador intermedirio rd1u (multiplicao


por 2), se um 1 for rotacionado para fora de rd1u, o programa desvia para o passo de subtrao no
passo 4 imediatamente.

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.

O contedo da flag de carry rotacionada no registrador de resultado reh:rel da direita.

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 teste, binrios 0XAAAA e


0x55, sero divididos, e so
escritos nos registradores
R1:R0 e R3.

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

R1:R0 foi rotacionado


esquerda para R2, a partir
do valor 0xAAAA chegamos
ao valor dobrado 0x015554.

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).

Exemplo 1: Conversor AD 8-bit para sada decimal com ponto fixo


; Demontra converso de ponto flutuante em Assembler, 2003 www.avr-asm-tutorial.net
;
; A tarefa: Voc l um resultado de 8 bits de um conversor analgico-digital, o nmero est na faixa de hex 00 a FF.
; Voc precisa convert-lo em um nmero com ponto flutuante na faixa de 0,00 a 5,00 Volts.
; O esquema do programa:
; 1. Multiplicao por 502 (hex 01F6). Este passo multipllica por 500, 256 e divide por 255 em um passo!
; 2. Arredondar e cortar o ltmo byte do resultado. Este passo divide por 256 ao ignorar o ltimo byte do resultado.
;
Antes de fazer isso, o bit 7 usado para arredondar o resultado.
; 3. Converter a palavra resultante para ASCII e setar o sinal decimal correto. A palavra resultante que varia de 0 a 500
;
mostrada em caracteres ASCII como 0.00 a 5.00.
; Os registradores usados:
; As rotinas usam os registradores R8..R1 sem salv-los antes. Tambm necessrio um registrador multipropsito rmp,
; localizado na metade superior dos registradores. Assegure-se que estes registradores no conflitem com registradores
; em uso no restante do programa.
; O nmero de 8 bits esperado no registrador R1. A multiplicao usa R4:R3:R2 para guardar o multiplicador 502
; ( deslocado esquerda at oito vezes durante a multiplicao). O resultado da multiplicao calculado nos
; registradores R7:R6:R5. O resultado da diviso por 256 feita ignorando R5 no resultado, usando somente R7:R6.
; R7:R6 arredondado, depenendo do bit mais alto de R5, e o resultado copiado para R2:R1.
; A converso para ASCII-string usa a entrada em R2:R1, o par de registradores R4:R3 como divisor para conveso, e
; coloca o resultado ASCII em R5:R6:R7:R8 (R6 o caractere decimal).
; Outras convenes:
; A converso usa subtotinas e a pilha. A pilha deve estar funcionando para uso de trs nveis (seis bytes de SRAM).
; Temos de converso:
; A rotina inteira requer 228 ciclos de relgico no mximo (convertendo $FF), e 79 no mnimo (convertendo $00).
; A 4 Mhz os tempos so 56,75 microssegundos e 17,75 microssegundos, respectivamente.
; Definies:
; Registradores
.DEF rmp = R16 ; usado como registrador multipropsito
; tipo de AVR: Testado em AT90S8515, necessrio para pilha, as rotinas devem funcionar com outros tipos AT90S-.
.NOLIST
.INCLUDE "8515def.inc"
.LIST
; Incio do programa de teste
; Escreve um nmero em R1 e inicia a converso da rotina, para propsitos de teste somente
.CSEG
.ORG $0000
rjmp main
main:
ldi rmp,HIGH(RAMEND) ; Inicia a pilha
out SPH,rmp
ldi rmp,LOW(RAMEND)
out SPL,rmp
ldi rmp,$FF ; Converte $FF
mov R1,rmp
rcall fpconv8 ; chama a rotina de converso
no_end: ; loop infinito, quando terminar
rjmp no_end
; Rotina de converso, chama diferentes passos da converso

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

Exemplo 2: Conversor AD de 10 bits com sada decimal fixa


Este exemplo um pouco mais complicado. Veja o website se precisar dele.

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

Registrador => Registrador

MOV r1,r2

SRAM => Registrador, direto

LDS r1,c65535

SRAM => Registrador

LD r1,rp

SRAM => Registrador e INC

LD r1,rp+

DEC, SRAM => Registrador

LD r1,-rp

SRAM, deslocado => Registrador

LDD r1,ry+k63

Porta => Registrador

IN r1,p1

Pilha => Registrador

POP r1

Program storage Z => R0

LPM

Registrador => SRAM, direto

STS c65535,r1

Registrador => SRAM

ST rp,r1

Registrador => SRAM e INC

ST rp+,r1

DEC, Registrador => SRAM

ST -rp,r1

Registrador => SRAM, deslocado

STD ry+k63,r1

Registrador => Porta

OUT p1,r1

Registrador => Pilha

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

8 Bit - carry, constante

SBCI rh,c255

ZCNVH 1

16 Bit

SBIW rd,k63

ZCNVS 2

Lgico, esquerda

LSL r1

ZCNV

Lgico, direita

LSR r1

ZCNV

Rotao, esquerda sobre carry

ROL r1

ZCNV

Rotao, direita sobre carry

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

de Registrador, copia para Flag T


Registrador, copia da Flag T

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

Flag de Habilitao de Interrupo

SEI

Flag de Zero

CLZ

Flag de carry

CLC

Flag de Negativo

CLN

Flag de carry de Complemento de


CLV
zera bit de Dois
status
Flag de meio carry
CLH

Salto
Imediato

Clk

Registrador, seta

Flag de carry de Complemento de


SEV
Seta bit de Dois
Status
Flag de meio carry
SEH

Compara

Flags

Flag de Sinal

CLS

Flag de Transferncia

CLT

Flag de Desabilitao de Interrupo

CLI

Registrador, Registrador

CP r1,r2

ZCNVH 1

Registrador, Registrador + carry

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

Bit de status setado

BRBS b7,c127

1/2

Bit de status zera

BRBC b7,c127

1/2

Salta se igual

BREQ c127

1/2

Salta se diferente

BRNE c127

1/2

Salta se carry setado

BRCS c127

1/2

Salta se carry zero

BRCC c127

1/2

Salta se igual ou maior

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

Salta se meio carry setado

BRHS c127

1/2

Salta se meio carry zero

BRHC c127

1/2

Salta se Flag T setada

BRTS c127

1/2

Salta se Flag T zera

BRTC c127

1/2

Salta se flag de complemento de 2


BRVS c127
setado

1/2

Salta se flag de complemento de 2


BRVC c127
zero

1/2

Salta se interrupo habilitada

BRIE c127

1/2

Salta se interrupo desabilitada

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

Compara, salta se for igual

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

Lista de Diretivas e Instrues em ordem alfabtica


Diretivas de Assembler em ordem alfabtica
Diretiva

... significa ...

.CSEG

Compilar para o segmento de cdigo

.DB

Inserir bytes de dados

.DEF

Definir o nome de um registrador

.DW

Insirir palavras de dados

.ENDMACRO

A macro est completa, parar a gravao

.ESEG

Compilar para o segmento da EEPROM

.EQU

Definir uma constante por nome e setar o seu valor

.INCLUDE

Inserir o contedo de um arquivo neste local como se fosse parte deste arquivo

.MACRO

Iniciar a gravao das seguintes instrues como definies de macro

.ORG

Setar o endereo de sada do assembler para o seguinte nmero

Instrues em ordem alfabtica


Instruo

... faz ...

ADC r1,r2

Soma r2 com carry com r1, e armazena o resultado em r1

ADD r1,r2

Soma r2 com r1 e armazena o resultado em r1

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

Faz operao and de r1 com o valor em r2 e armazena o resultado em r1

ANDI rh,c255

Faz operao and com o registrador superior rh com a constante c255 e armazena o resultado em rh

ASR r1

Desvio direita aritmtico do registrador r1

BLD r1,b7

Copia a flag T do registrador de status para o bit b7 do registrador r1

BRCC c127

Desvia ou volta para instrues c127 se a flag de carry for 0

BRCS c127

Desvia ou volta para instrues c127 se a flag de carry for 1

BREQ c127

Desvia ou volta para instrues c127 se a flag de zero for 1

BRGE c127

Desvia ou volta para instrues c127 se a flag de carry for 0

BRHC c127

Desvia ou volta para instrues c127 se a flag de meio-carry for 0

BRHS c127

Desvia ou volta para instrues c127 se a flag de meio-carry for 1

BRID c127

Desvia ou volta para instrues c127 se a flag de interrupo for 0

BRIE c127

Desvia ou volta para instrues c127 se a flag de interrupo for 1

BRLO c127

Desvia ou volta para instrues c127 se a flag de carry for 1

BRLT c127

Desvia ou volta para instrues c127 se as flags de negativo e estouro forem 1

BRMI c127

Desvia ou volta para instrues c127 se a flag de negativo for 1

BRNE c127

Desvia ou volta para instrues c127 se a flag de zero for 1

BRPL c127

Desvia ou volta para instrues c127 se a flag de negativo for 0

BRSH c127

Desvia ou volta para instrues c127 se a flag de carry for 0

BRTC c127

Desvia ou volta para instrues c127 se a flag de transferncia for 0

BRTS c127

Desvia ou volta para instrues c127 se a flag de transferncia for 1

BRVC c127

Desvia ou volta para instrues c127 se a flag de estouro for 0

BRVS c127

Desvia ou volta para instrues c127 se a flag de estouro for 1

BST r1,b7

Copia o bit 7 no registrador r1 para a flag de transferncia no registrador de status

CBI pl,b7

Zera bit b7 na porta mais baixa pl

CBR rh,k255

Zera todos os bits no registrador superior rh, que esto setados na constante k255 (mscara)

CLC

Zera o bit de carry

CLH

Zera o bit de meio-carry

CLI

Zera o bit de interrupo, desabilita a execuo de interrupes

CLN

Zera o bit de negativo no registrador de status

CLR r1

Zera o registrador r1

CLS

Zera a flag de sinal no registrador de status

CLT

Zera a flag de transferncia no registrador de status

CLV

Zera a flag de overflow do registrador de status

CLZ

Zera a flag de zero do registrador de status

COM r1

Complementa registrador r1 (complemento de um)

CP r1,r2

Compara registrador r1 com registrador r2

CPC r1,r2

Compara registrador r1 com registrador r2 e flag de carry

CPI rh,c255

Compara o registrador superior rh com a constante imediata c255

CPSE r1,r2

Compara r1 com r2 e pula sobre a prxima instruo se for igual

DEC r1

Decrementa o registrador r1 por 1

EOR r1,r2

Ou-exclusive dos bits do registrador r1 com registrador r2 e armazena resultado em r1

ICALL

Chama a subrotina no endereo no par de registradores Z (ZH:ZL, R31:R30)

IJMP IN r1,p1

Salta para o endereo no par de registradores Z (ZH:ZL, R31:R30)

INC r1

Incrementa o registrador r1 por 1

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

Carrega o registrador superior rh com a constante c255

LDS r1,c65535

Carrega o registrador r1 com o contedo do endereo 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

Desvio esquerda lgico do registrador r1

LSR r1

Desvio direita lgico do registrador r1

Avr-Asm-Tutorial

49

http://www.avr-asm-tutorial.net

MOV r1,r2

Move registrador r2 para o registrador r1

NEG r1

Subtrai registrador r1 de Zero

NOP

Sem operao

OR r1,r2

Faz operao OR do registrador r1 com r2 e armazena o resultado em r1

ORI rh,c255

Faz operao OR do registrador superior r1 com a constante c255

OUT p1,r1

Copia registrador r1 para porta de E/S p1

POP r1

Incrementa o ponteiro de pilha e retira o ltimo byte da pilha e o coloca no registrador r1

PUSH r1

Coloca o contedo do registrador r1 na pilha e decrementa o ponteiro de pilha

RCALL c4096

Coloca o contador de programa na pilha e adiciona a constante com sinal c4096 ao contador de
programa (chamada relativa)

RET

Recupera o contador de programa da pilha (retorna ao endereo de chamada)

RETI

Habilita interrupes e recupera o contador de programa da pilha (retorna de interrupo)

RJMP c4096

Salto relativo, soma constante com sinal c4096 ao endereo do programa

ROL r1

Rotaciona registrador r1 esquerda, copia a flag de carry para o bit 0

ROR r1

Rotaciona o registrador r1 direita, copia a flag de carry para o bit 7

SBC r1,r2

Subtrai r2 e a flag de carry do registrador r1 e armazena o resultado em r1

SBCI rh,c255

Subtrai constante c255 e carry do registrador superior rh e armazena o resultado em rh

SBI pl,b7

Seta o bit b7 na porta baixa pl

SBIC pl,b7

Se o bit b7 na porta baixa pl for zero, pula a prxima instruo

SBIS pl,b7

Se o bit b7 na porta baixa pl for um, pula a prxima instruo

SBIW rd,k63

Subtrai a constante k63 do par de registradores rd (rd+1:rd, rd = R24, R26, R28, R30)

SBR rh,c255

Seta os bits no registrador superior rh, que so 1 da constante c255

SBRC r1,b7

Se o bit b7 do registrador r1 for zero, pula a prxima instruo

SBRS r1,b7

Se o bit b7 no registrador r1 for um, pula a prxima instruo

SEC

Seta flag de carry no registrador de status

SEH

Seta flag de meio carry no registrador de status

SEI

Seta flag de interrupo no registrador de status, habilita a execuo de interrupo

SEN

Seta flag de negativo no registrador de status

SER rh

Seta todos os bits no registrador superior rh

SES

Seta flag de sinal no registrador de status

SET

Seta flag de transferncia no registrador de status

SEV

Seta flag de estouro (overflow) no registrador de status

SEZ

Seta flag de zero no registrador de status

SLEEP

Coloca o controlador no modo de repouso selecionado

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

Armazena o contedo do registrador r1 na localizao apontada pelo par de registradores ry (Y ou z),


deslocado pela constante k63.

STS c65535,r1

Armazena o contedo do registrador r1 na localizao c65535

SUB r1,r2

Subtrai o registrador r2 do registrador r1 e escreve o resultado em r1

SUBI rh,c255

Subtrai a constante c255 do registrador superior rh

SWAP r1

Troca os nibbles superior com o inferior no registrador r1

TST r1

Compara o registrador r1 com Zero

WDR

Watchdog reset

Detalhes das Portas


Esta tabela contm as portas importantes nos AVR tipo AT90S2313, 2323 e 8515. Portas ou pares de
registradores acessveis no so mostradas em detalhes. No h garantias da exatido destes dados,
confira os data sheets originais!

Avr-Asm-Tutorial

50

http://www.avr-asm-tutorial.net

Registrador de Status, Flags do Acumulador


Porta
SREG

Endereo da
porta

Funo

Acumulador do registrador
0x3F
de status

Endereo da
RAM
0x5F

Bit Nome

Significado

Indica

Comando

Interrupo 0: Interrupes desabilitadas


1: Interrupes habilitadas

CLI

Flag
de
Global

Armazm de bits

Flag de Meio-Carry

Flag de Sinal

Flag de complemento de 0: No ocorreu transporte (carry)


dois
1: Ocorreu transporte (carry)

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

0: O resultado no era negativo/menor

CLN

1: O resultado era negativo/menor

SEN

0: Resultado no era zero/diferente

CLZ

1: Resultado era zero/igual

SEZ

0: No ocorreu transporte (carry)

CLC

1: Ocorreu transporte (carry)

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

Do AT90S2313 para frente, no em 1200

SPH

Byte alto do
ponteiro de pilha

Do AT90S8515 para frente, apenas para dispositivos com mais de 256


bytes de SRAM interna.

SRAM e controle externo de interrupes


Porta
MCUCR

Registrador de Controle Geral


0x35
MCU

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

Estados de espera (wait 0=Sem wait state extra na SRAM externa


states) da SRAM Ext.
1=Wait state adicional na SRAM externa

SE

Habilita repouso (sleep)

SM

Modo de respouso

ISC11

0=Ignora comando SLEEP


1=Aceita comando SLEEP
0=Inatividade (Meio-repouso)
1=Desligamento (Repouso total)

00: Nvel baixo inicia interrupo


Pino de controle de 01: Indefinido
interrupo
INT1
ISC10 (conectado a GIMSK)
10: Borda de descida dispara interrupo
11: Borda de subida dispara interrupo

2
1

ISC01

00: Nvel baixo inicia interrupo


Pino de controle de 01: Indefinido
interrupo
INT0
ISC00 (conectado a GIMSK)
10: Borda de descida dispara interrupo
11: Borda de subida dispara interrupo

Controle de Interrupo Externa


Porta
GIMSK

Endereo da
Porta

Funo
Registrador mascarado
Interrupo Geral

de

0x3B

Endereo da
RAM
0x5B

INT1

INT0

Bit Nome

Significado

Indica

INT1

Interrupo por pino externo 0: INT1 Externa desabilitada


INT1 (conectado a MCUCR)
1: INT1 Externa habilitada

INT0

Interrupo por pino externo 0: INT0 Externa desabilitada


INT0 (conectado a MCUCR)
1: INT0 Externa habilitada

0...5

(No usados)

Porta

Endereo
da Porta

Funo

GIFR Registrador geral de Interrupes

0x3A

Endereo da
RAM
0x5A

INTF1

INTF0

Bit

Name

INTF1 Ocorreu interrupo externa pelo pino INT1

INTF0 Ocorreu interrupo externa pelo pino INT0

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

Controle do Timer de Interrupo


Port
TIMSK

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

Estouro de Timer/Contador 1-Interrupo

int

no

1: Int no estouro
6

OCIE1A Interrup. do Timer/Contador 1 Comparador A

OCIE1B Interrup. do Timer/Contador 1 Comparador B

0: Sem int igual a A


1: Int igual a A
0: Sem int em B
1: Int em B

(No usado)

TICIE1

0: Sem
captura

Captura do Timer/Contador 1 Interrupo

int

na

1: Int na captura
2

(No usado)

TOIE0

0: Sem
estouro

Estouro de Timer/Contador 0-Interrupo

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

OCF1A Timer/Contador 1 chegou a Compara A

Modo-Interrupo:

OCF1B Timer/Contador 1 chegou a Compara B

(No usado)

Zero pela execuo


da
rotina
da
interrupo

ICF1

2
1
0

Timer/Contador 1 estourou

Evento de captura de Timer/Contador 1


(No usado)

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

Registrador de controle de Timer/


0x33
Contador 0

TCCR0

0x53

CS02

CS01

CS00

Bit

Nome

Significado

Indica
000: Pra timer
001: Clock = clock do chip
010: Clock = clock do chip / 8

2..0 CS02..CS00 Timer Clock

011: Clock = clock do chip / 64


100: Clock = clock do chip / 256
101: Clock = clock do chip / 1024
110: Clock = borda de descida do pino T0
111: Clock = borda de subida do pino T0

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

Registrador de Controle A de Timer/


0x2F
Contador 1

COM1A1 COM1A0 COM1B1 COM1B0


Bit

Nome

COM1A1

COM1A0

5
4
3
2

Significado

Endereo da
RAM
0x4F

PWM11

PWM10

Indica

Sada Comparadora A 00: OC1A/B no conectado


01: OC1A/B troca polaridade
10: OC1A/B para zero
COM1B1
Sada Comparadora B 11: OC1A/B para um
COM1B0
(No usado)

PWM11
1..0
PWM10

00: PWM desligado


Modulador por largura 01: 8-Bit PWM
de pulso (PWM)
10: 9-Bit PWM
11: 10-Bit PWM

Avr-Asm-Tutorial

55

Port

http://www.avr-asm-tutorial.net

Endereo da
Porta

Funo

Registrador de Controle B de Timer/


0x2E
Contador 1

TCCR1B

Endereo da
RAM
0x4E

ICNC1

ICES1

CTC1

CS12

CS11

CS10

Bit

Nome

Significado

Indica

ICNC1

0: desabilitado, primeira borda inicia a


Cancelador
de amostragem
rudo no pino ICP
1: habilitado, pelo menos quatro ciclos

ICES1

Seleo de bordo 0: borda de descida dispara captura


na captura
1: borda de subida dispara captura

5..4 (No usado)


3

CTC1

Limpa quando a
comparao
for 1: Contador zera se for igual
igual a A

2..0 CS12..CS10 Seleo do clock

Port

000: Contador parado


001: Clock
010: Clock / 8
011: Clock / 64
100: Clock / 256
101: Clock / 1024
110: borda de descida em pino T1
111: borda de subida em pino T1

Funo

TCNT1L/H Registrador Timer/Contador 1

Port

Funo

Endereo da
Porta
0x2C/0x2D

Endereo da
RAM
0x4C/0x4D

Endereo da
Porta

OCR1AL/H Timer/Contador 1 Output Compare register A 0x2A/0x2B

Port

Funo

OCR1BL/H

Port
ICR1L/H

Endereo da
Porta

Registrador de Sada do Comparador B


0x28/0x29
Timer/Contador 1

Funo

Endereo da
Porta

Registrador de Entrada de Captura do


0x24/0x25
Timer/Contador 1

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

Ciclo-WDT a 5,0 Volts

(No usado)

WDTOE

Habilita ciclo de Watchdog

Requerido setar antes de


desabilitar o WDE

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

2..0 WDP2..WDP0 Tempo do Watchdog

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

Habilita Escrita EEPROM

Setar para iniciar gravao

EERE

Habilita Leitura EEPROM

Setar para iniciar leitura

Habilita ciclo de leitura

Avr-Asm-Tutorial

57

http://www.avr-asm-tutorial.net

Interface de Perifricos Seriais (SPI)


Port
SPCR

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

DORD Ordem de Dados

MSTR Seleo Master/Slave

CPOL Polaridade do Clock

CPHA Fase do Clock

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

Freqncia do clock 01: Clock / 16


SCK
10: Clock / 64
11: Clock / 128

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

Flag de Coliso de Ocorreu


Escrita
escrita

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

Recepo UART Completa

1: Caractere recebido

TXC

Transmisso
Completa

1: Shift register vazio

UDRE

Registrador de Dados da 1:
Registrador
UART Vazio
transmisso disponvel

FE

Erro de
(framing)

OR

Perda (Overrun)

UART

enquadramento

2..0

de

1: Bit de Parada Ilegal


1: Caractere perdido

(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

TX 1: Interrupo quando transmisso


completada

UDRIE

Habilita
Interrupo
Registrador de Dados vazio

RXEN

Recepo Habilitada

1: Receptor habilitado

TXEN

Transmisso Habilitada

1: Transmissor habilitado

CHR9

Caracteres de 9 bits

1: Tamanho do caractere 9 bits

RXB8

Recebe Bit de Dado 8

(segura nono bit na recepo)

TXB8

Transmite Bit de Dado 8

(escreve nono bit para transmisso)

Port
UBRR

Funo

recebe

quando 1: Interrupo quando buffer de


dados vazio

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

Sada do Comparador Sada dos Comparadores

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

00: Interrupo na mudana de


nvel

01: (No usado)


Habilita Captura de
10: Interrupo
ACIS0 Entrada
descida
11: Interrupo
subida

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

Endereo dos Pinos de


Entrada

0x19

0x39

PORTB

Registrador de Dados

0x18

0x38

DDRB

Registrador da Direo
dos Dados

0x17

0x37

PINB

Endereo dos Pinos de


Entrada

0x16

0x36

PORTC

Registrador de Dados

0x15

0x35

DDRC

Registrador da Direo
dos Dados

0x14

0x34

PINC

Endereo dos Pinos de


Entrada

0x13

0x33

PORTD

Registrador de Dados

0x12

0x32

DDRD

Registrador da Direo
dos Dados

0x11

0x31

PIND

Endereo dos Pinos de


Entrada

0x10

0x30

Avr-Asm-Tutorial

60

http://www.avr-asm-tutorial.net

Portas, ordem alfabtica


ACSR, Registrador de Status e Controle do Comparador Analgico
DDRx, Registrador da Direo dos Dados da Porta x
EEAR, Registrador de endereo da EEPROM
EECR, Registrador de controle da EEPROM
EEDR, Registrador de Dados da EEPROM
GIFR, Registrador da Flag de Interrupo Geral
GIMSK, Registrador de Interrupo Mascarada Geral
ICR1L/H, Registrador de Captura de Entrada 1
MCUCR, Registrador de Controle Geral da MCU
OCR1A, Registrador de Sada do Comparador 1 A
OCR1B, Registrador de Sada do Comparador 1 B
PINx, Acesso Porta de Entrada
PORTx, Port x Output Register
SPL/SPH, Ponteiro de Pilha
SPCR, Registrador de Controle de Perifricos Seriais
SPDR, Registrador de Dados de Perifricos Seriais
SPSR, Registrador de Status de Perifricos Seriais
SREG, Registrador de Status
TCCR0, Registrador de Controle do Timer/Contador Timer0
TCCR1A, Registrador de Controle do Timer/Contador 1 A
TCCR1B, Registrador de Controle do Timer/Contador 1 B
TCNT0, Registrador do Timer/Contador, Contador 0
TCNT1, Registrador do Timer/Contador, Contador 1
TIFR, Flag de Interrupo do Timer
TIMSK, Registrador Mascarado de Interrupo do Timer
UBRR, Registrador de velocidade da UART (Baud Rate)
UCR, Registrador de Controle da UART
UDR, Registrador de Dados da UART
WDTCR, Registrador de Controle do Timer Watchdog

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

Registrador fonte comum

rh

Registrador de pgina superior

R16..R31

rd

Registrador gmeo

R24(R25), R26(R27), R28(R29), R30(R31)

rp

Registrador de ponteiro

X=R26(R27), Y=R28(R29), Z=R30(R31)

ry

Registrador
de
deslocamento

k63

Constante ponteiro

0..63

c127

Distncia de salto condicional

-64..+63

c255

Constante de 8 bits

0..255

c4096

Distncia de salto relativo

-2048..+2047

c65535

Endereo de 16 bits

0..65535

b7

Posio do bit

0..7

p1

Porta comum

0..63

pl

Porta de pgina inferior

0..31

R0..R31

ponteiro

com

Y=R28(R29), Z=R30(R31)

Você também pode gostar