Useful objasm macros

 

EQUx

I don't like the DCx version of allocating storage, I'm used to the EQUx method provided by the BASIC assembler...

EQUB

          ; EQUB <value>
          ; set a byte
          MACRO
          EQUB    $var
          DCB     $var
          MEND

EQUW

          ; EQUW <value>
          ; Set a 16 bit value
          MACRO
          EQUW    $var
          DCW     $var
          MEND

EQUD

          ; EQUD <value>
          ; Set a 32 bit value
          MACRO
          EQUD    $var
          DCD     $var
          MEND

EQUS

          ; EQUS "<value>"
          ; Set a string.
          ; For 'EQUS "something", 13, 0'
          ; you will need use DCB directly.
          MACRO
          EQUS    $var
          DCB     "$var"
          MEND

EQUSZ

          ; EQUSZ "<value>"
          ; Set a string and zero-terminate it.
          MACRO
          EQUSZ   $var
          DCB     "$var", 0
          MEND

EQUSB

          ; EQUSB "<value>"
          ; Set a string and BASIC-style terminate it.
          MACRO
          EQUSZ   $var
          DCB     "$var", 13
          MEND

EQUSZA

          ; EQUSZA "<value>"
          ; Set a string and zero-terminate it, then align.
          MACRO
          EQUSZA  $var
          DCB     "$var", 0
          ALIGN
          MEND

 

 

RLIST

You can use RLIST to define ranges of registers:
stm_temp  RLIST {R0-R3,R14}
ldm_temp  RLIST {R0-R3,PC}
str_temp  RLIST {R0-R3}
Then, in your code, instead of:
  STMFD R13!, {R0-R3, R14}
  ...
  LDMFD R13!, {R0-R3, PC}

you could write:
  STMFD R13!, stm_temp
  ...
  LDMFD R13!, ldm_temp

The 'str_temp' version is for when you want to store/load without messing with R14/PC. The same is used for both loading and storing.

 

 

Push and Pull

It can be useful to write macros for common register pushing and pulling. Here are the ones that I use...

BSR

        ; BSR "<function>"
        ; Branch to subroutine saving R14 around it
        ; This is a lot like JSR on the 6502.

        MACRO
$label  BSR     $dest
$label  PushLR
        BL      $dest
        PullLR
        MEND

Pull

        ; Pull "<reglist>" [,<"condition"> [,"^"]]
        ; Pull registers given in reglist. Can be conditional.
        ; Use '^' with care.
        ; Example:
        ;   Pull   "R2-R4", "EQ"
        MACRO
$label  Pull    $reglist, $cond, $hat
$label  LDM$cond.FD R13!, {$reglist}$hat
        MEND

Push

        ; Push "<reglist>" [,<"condition">]
        ; Push registers given in reglist. Can be conditional.
        ; Example:
        ;   Push   "R2-R4", "EQ"
        MACRO
$label  Push   $reglist, $cond
$label  STM$cond.FD R13!, {$reglist}
        MEND

PushLR

        ; Push LR (and only LR) to the stack.
        ; Optimised for fast saving of one register,
        ; instead of using STMFD R13!, {LR}
        ; Can be conditional.
        MACRO
$label  PushLR    $cond
$label  STR$cond. R14, [R13, #-4]!
        MEND

PullLR

        ; Pull LR (and only LR) from the stack.
        ; Optimised form of LDMFD R13!, {LR}
        ; Can be conditional.
        MACRO
$label  PullLR    $cond
$label  LDR$cond. R14, [R13], #4
        MEND

Ret and Return

        ; Return from function.
        ; Can be conditional. DOES NOT RESTORE FLAGS.
        MACRO
$label  Ret     $cond
$label  MOV$cond PC, R14
        MEND


        ; This is functionally the same as 'Ret'. Use
        ; whichever you prefer.
        MACRO
$label  Return $cond
$label  MOV$cond PC, R14
        MEND

PullRet

        ; Pull LR and Return
        ; This is equivalent to:
        ;    PullLR
        ;    Return
        ; but it saves an instruction as we load to PC
        MACRO
$label  PullRet    $cond
$label  LDR$cond. PC, [R13], #4
        MEND

 

Miscellaneous

SetV

        ; SetV sets the oVerflow flag
        ; regardless of processor type
        MACRO
$label  SetV     ; DOES NOT TAKE A CONDITION
$label  CMP      R0, #1<<31
        CMNVC    R0, #1<<31
        MEND

ProcMode

        ; ProcMode returns:
        ;    EQ if 32 bit (PC and CPSR) mode
        ;    NE if 26 bit (PC + PSR) mode
        MACRO
$label  ProcMode ; DOES NOT TAKE A CONDITION
$label  TEQ      PC, #0
        TEQ      PC, PC
        MEND

Sometimes it can be useful to stick in an on-screen debugging message so you can quickly trace the flow of the program without restorting to the tedium of single-stepping in the debugger...

DebugMsg

        ; DebugMsg - embeds a debugging message
        MACRO
        DebugMsg $msg
        SWI      XOS_WriteS
        DCB      "$msg", 13, 10, 0
        ALIGN        
        MEND
You could expand upon this by, for instance, wrapping it in a conditional test for a DEBUG 'define'. In this way, you can simply alter the DEBUG 'define' to make the macro either output the in-line debugging string or simply do nothing.


Return to assembler index
Copyright © 2004 Richard Murray