Prof. Célio Guimarães - IC Unicamp
Atualizado em: 27/08/12
Macros são uma sequencia de instruções cujos operandos podem ser parâmetros, o que permite inserir no código fonte do programa a mesma sequencia de instruções porém com diferentes operandos. Macros são definidas e invocadas de forma semelhante a subrotinas. A diferença básica é que o código da macro é inserido no programa a cada invocação (também chamada de expansão) da macro. A expansãp da macro é feita em tempo de montagem pelo montador (assembler), ou seja, tudo se passa como se no momento da invocação da macro são inseridas no código fonte as instruções que compõem a macro, colocando os parâmetros fornecidos na invocação. A definição da macro é delimitada pelas diretivas .macro nome-da-macro e .endmacro. Entre elas são colocadas as instruções que compõem o corpo da macro, com parâmetros denominados @0, @1, @2, etc. A invocação da macro consiste no nome da macro (onde seria colocado o mnemônico de uma instrução) seguido de uma lista de parâmetros separados por vírgula. Nesse momento o montador substitui o comando de invocação pelas instruções no corpo da macro, com os parâmetros @0, @1, @2, etc substituídos pelos parâmetros fornecidos na ordem dada no comando de invocação. Um exemplo tornará esses conceitos claros:
Queremos codificar uma macro mult8 para multiplicar o conteúdo de dois registradores passados como parâmetros (@0 e @1), colocando o produto na memória apontada por um dos pares de registradores X, Y ou Z, passado como terceiro parâmetro (@2):
Definição da macro: ;*************************************************************************************************************************** .listmac ; para incluir no arquivo .lst as instruções da expansão de macro ; .macro mult8; macro para multiplica dois números de 8 bits sem sinal ; Parâmetros de entrada: ; @0 e @1: dois registradores quaisquer (números para multiplcar) ; @2 um dos pares X,Y ou Z: endereço na RAM para colocar o produto no formato little endian ; destroi: r0, r1, @2 mul @0,@1 st @2+,r0 st @2, r1 .endmacro ;******************************************************************************* Preparação dos parâmetros: ldi yh, high(SRAM_START) ; area da RAM onde será colocado o resultado: parametro @2 ldi yl, low(SRAM_START) ldi r16,2 ; parametro @0 ldi r17,5 ; parameto @1 Invocação da macro: mult8 r16,r17, y ;r16 = @0, r17 = @1, y = @2
Recursos adicionais
de macros no AVR:
É possível invocar recursivamente uma macro. Veja o exemplo fib8.asm onde o nível de recursão é controlado por diretivas de montagem condicional.
Não é permitido definir uma macro no corpo de outra macro
.macro conta_algo or @0,@0 breq done ; o salto sera para a 1a instrucao após o corpo da macro! . . . ;faz alguma coisa aqui . . . done: .endmacro
Par de registradores passado como parâmetro:
Obs: 1.
como toda invocação de uma macro implica em inserção das
instruções no seu corpo, este tipicamente deve conter poucas
instruções (caso a macro seja invocada muitas vezes num programa) 2. Use
a diretiva .listmac para
que as instruções geradas pela invocação da macro sejam incluídas
no arquivo .lst
É possível acessar cada elemento do par via sufixo "l" ou "h" e usar os operadores de pós-incrementação ou pré-decrementação.
Exemplo: suponha que o par X tenha sido passado como parâmetro @0 na invocação da macro.
Então as seguintes instruções no corpo da macro são válidas:
mov r16, @0l ; será substituido por: mov r16, xl
mov r17, @0h ; será substituido por: mov r17, xh
st @0+, r0 ; será substituido por: st x+, r0
st -@0, r1 ; será substituido por: st -x, r1