Pseudo
instructions

 

The BASIC assembler provides you with a selection of pseudo-instructions. These are instructions which are not actually understood by the processor, but are converted into something that may be understood. They exist to make your programming simpler.

 

ADR : load ADRess

   ADR<suffix> <register>, <label>
This loads the address referred into the given register:
   00008FE4                    OPT     l%
   00008FE4 E28F0004           ADR     R0, text
   00008FE8 EF000002           SWI     "OS_Write0"
   00008FEC E1A0F00E           MOV     PC, R14
   00008FF0                    .text
   00008FF0                    EQUS    "Hello!" + CHR$13 + CHR$10 + CHR$0
   00008FFC                    ALIGN

The following code has the exact same effect:

   00008FE4                    OPT     l%
   00008FE4 E28F0004           ADD     R0, R15, #4
   00008FE8 EF000002           SWI     "OS_Write0"
   00008FEC E1A0F00E           MOV     PC, R14
   00008FF0                    .text
   00008FF0                    EQUS    "Hello!" + CHR$13 + CHR$10 + CHR$0
   00008FFC                    ALIGN
Indeed, a disassembly of either of the above would show:
   *MemoryI 8FE4 +18
   00008FE4 :  E28F0004 : .. : ADR     R0,&00008FF0
   00008FE8 :  EF000002 : ... : SWI     "OS_Write0"
   00008FEC :  E1A0F00E : . : MOV     PC,R14
   00008FF0 :  6C6C6548 : Hell : STCVSTL CP5,C6,[R12],#-&120 ; =288
   00008FF4 :  0A0D216F : o!.. : BEQ     &003515B8
   00008FF8 :  00000000 : .... : DCD     &00000000

 

ADR is a useful instruction, though, as you do not need to worry about R15's offset (ie, why do we only add four?) nor do you need to calculate the offset over a block of code. Simply use ADR Rx, label and the assembler will sort it out for you using ADD, SUB, MOV or MVN as is best appropriate.
The limiting factor, however, is you can only reference within a 4096 byte range (not strictly true, it typically uses ADD or SUB with eight bits rotated by a multiple of two, but for argument's sake we'll assume the range is 4K).

Therefore...

 

 

ADRL : load ADRess Long

   ADRL<suffix> <register>, <label>
This is not supported by BASIC's assembler, though some extensions add it.

The ADRL instruction uses a combination of ADR and ADD, or ADR and SUB, to generate a wider range of addresses which may be reached. However this always uses two instructions, so a more workable arrangement may be to try to restructure your code so that a normal ADR will work.

There is also, in some assemblers, an ADRX which uses three instructions to address even more locations.

Here is a macro for ADRL that you may use to address within a 64K range:

   DEFFNadrl(register%, location%, pass%)
   REM Uses two instructions to load an address within a 64K range
   LOCAL progcnt%
   progcnt% = P%
   IF (location% > progcnt%) THEN
     [ OPT     pass% ; positive offset
       ADR     register%, (location% - ((location% - progcnt%) AND &FFFFFF00))
       ADD     register%, register%, #((location% - progcnt%) AND &FFFFFF00)
     ]
   ELSE
     [ OPT     pass%
       ADR     register%, (location% + ((progcnt% - location%) AND &FFFFFF00))
       SUB     register%, register%, #((progcnt% - location%) AND &FFFFFF00)
     ]
   ENDIF
   = 0

 

 

ALIGN : ALIGN pointers

   ALIGN
The ALIGN instruction sets P% (and, if required, O%) to be aligned on a word boundary. This is usually required following a string or one or more bytes of data, and should be used before further code is assembled.

The BASIC assembler is quite smart, and experience shows that it will deal with alignment issues for you, if you neglect to do it...

   00008FF4                    OPT     l%
   00008FF4 E28F0004           ADR     R0, text
   00008FF8 EF000002           SWI     "OS_Write0"
   00008FFC EA000004           B       carryon
   00009000                    .text
   00009000                    EQUS    "unaligned text!!!" + CHR$0
   00009012                    .carryon
   00009014 E1A0F00E           MOV     PC, R14

 

 

DCx : initialise data storage

   DCx <value>
There is no DCx instruction. The small 'x' denotes a range of possibilities. These are:
   DCB    Reserve a byte (8 bit value)
   DCW    Reserve a half-word (16 bit value)
   DCD    Reserve a word (32 bit value)
   DCS    Reserve up to 255 bytes as required by given string
For example:
   .start_counter
     DCB     1

   .pointer
     DCD     0

   .error_block
     DCD     17
     DCS     "Uh-oh! It all went wrong!" + CHR$0
     ALIGN

 

 

EQUx : initialise data storage

   EQUx <value>
There is no EQUx instruction. The small 'x' denotes a range of possibilities. These are:
   EQUB   Reserve a byte (8 bit value)
   EQUW   Reserve a half-word (16 bit value)
   EQUD   Reserve a word (32 bit value)
   EQUS   Reserve up to 255 bytes as required by given string
This is exactly the same as DCx (above), simply understood by a different name.
You can use '=' as a short-hand version of EQUB.

 

 

OPT : set assembler OPTions

   OPT <value>
This sets various assembler options; produce listing? offset assembly? ignore errors? and the like. You will find more detail in the document devoted to OPT.

 


Return to assembler index
Copyright © 2001 Richard Murray