Atualizado em 28/04/2015

.macro

The commands .macro and .endm allow you to define macros that generate assembly output. The following macro shifts left register in parameter a by b bits (parameter b) if b is positive and shifts right if b is negative:
.macro SHIFTLEFT a, b
 .if \b < 0
 MOV \a, \a, ASR #-\b
 .exitm
 .endif
 MOV \a, \a, LSL #\b
.endm 
it could be "invoked" as follows:
SHIFTLEFT r0, 5
or
SHIFTLEFT r0, -8 
Another example: this definition specifies a macro sum that puts a sequence of numbers into memory:

        .macro  sum from=0, to=5
        .long   \from
        .if     \to-\from
        sum     "(\from+1)",\to
        .endif
        .endm

With that definition, `SUM 0,5' is equivalent to this assembly input:

        .long   0
        .long   1
        .long   2
        .long   3
        .long   4
        .long   5
.macro macname
.macro macname macargs ...
Begin the definition of a macro called macname. If your macro definition requires arguments, specify their names after the macro name, separated by commas or spaces. You can supply a default value for any macro argument by following the name with `=deflt'. For example, these are all valid .macro statements:
.macro comm
Begin the definition of a macro called comm, which takes no arguments.
.macro plus1 p, p1
.macro plus1 p p1
Either statement begins the definition of a macro called plus1, which takes two arguments; within the macro definition, write `\p' or `\p1' to evaluate the arguments.
.macro reserve_str p1=0 p2
Begin the definition of a macro called reserve_str, with two arguments. The first argument has a default value, but not the second. After the definition is complete, you can call the macro either as `reserve_str a,b' (with `\p1' evaluating to a and `\p2' evaluating to b), or as `reserve_str ,b' (with `\p1' evaluating as the default, in this case `0', and `\p2' evaluating to b).
When you call a macro, you can specify the argument values either by position, or by keyword. For example, `sum 9,17' is equivalent to `sum to=17, from=9'.
.endm
Mark the end of a macro definition.
.exitm
Exit early from the current macro definition.
\@
as maintains a counter of how many macros it has executed in this pseudo-variable; you can copy that number to your output with `\@', but only within a macro definition.
Nota: util para gerar rotulos locais para saltos condicionais no corpo da macro. Veja o exemplo: macroabs.s

Exercícios

  1. (i) Escreva uma macro mem_or addr, reg que toma como parametros um registrador contendo o endereço de uma palavra na RAM e outro registrador reg (ambos < r8) com o objetivo de fazer o "ou" do registrador reg com a palavra apontada por addr
    (ii) Acrescente um parâmetro (constante) nbits à macro acima com valor default 32, com o objetivo de especificar o número de bits menos significativos do registrador a serem usados na operação "ou".

    (iii) Escreva uma macro ubfx rd, rn, sbit, nbits onde rd e rn são registradores (< r8) e sbit e nbits são constantes, com o objetivo de emular a instrução ubfx - unsigned bit field extract, ou seja extrair nbits do registrador rn a partir do bit sbit, e inseri-los nos nbits menos significativos de rd, colocando em 0 os bits restantes de rd.
    Sugestão: a partir da máscara padrão (todos os bits = 1), construa uma máscara com os nbits menos significativos = 1 e os restantes = 0; complemente-a. O objetivo da máscara resultante deve ser então óbvio.

    (iv) Escreva uma nova macro sbfx rd, rn, sbit, nbits - signed bit field extract, (cujos parâmetros são os mesmos da macro ubfx), com o objetivo de emular a instrução sbfx onde agora a inserção considera o bit + significativo do campo a ser inserido como um bit de sinal que deve ser propagado para os bits mais significativos de rd.
    Sugestão: você não precisa de nenhuma máscara para resolver esta questão! Como consequencia, se o bit menos significativo do campo for 0, a macro dará o mesmo resultado do que a macro do problema anterior, ou seja, com uma modificação trivial a mesma técnica pode ser usada para implementar de forma muito mais simples a macro do problema anterior!

    (v) Escreva uma macro bfc rd, sbit, nbits com o objetivo de emular a instrução bfc - bit field clear, que zera um campo de nbits a partir do bit sbit do registrador rd (rd < 8, sbit e nbits são constantes no intervalo 0..31).
    Sugestão: construa duas máscaras m1 e m2 onde os sbit's menos significativos de m1 são 0 e os outros 1 e, no caso de m2, os bits à esquerda de nbits + sbit são 0 e os outros 1 (exemplos: m1= |111111111|sbits 0|) e m2= |0000000|nbits + sbits 1|). O objetivo dessas máscaras deve, então, ficar claro (esta macro pode ser codificada com 7 instruções!).
    Teste sua macro com o valor de rd= 0xaabbccdd, nbits= 8 e sbit=0, 8, 16, 24, exibindo rd após cada invocação da macro.
    Obs: este exercício corresponde a pelo menos 50 % da atividade 5.

  2. Escreva uma macro bfin addr, field, sbit, nbits - que toma como parâmetros:
    addr - constante cujo valor é o endereço de uma palavra na RAM,
    field - registrador (< r8) contendo um valor qualquer
    sbit - um número de bit (0-31),
    nbits -uma constante (0-31)
    O objetivo da macro é inserir na palavra cujo endereço é addr os nbits menos significativos do registrador field, a partir do bit sbit, sem alterar os outros bits da palavra na RAM (use a instrução bfi).