Pseudo
|
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<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 ALIGNIndeed, 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<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
ALIGNThe 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 <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 stringFor example:
.start_counter DCB 1 .pointer DCD 0 .error_block DCD 17 DCS "Uh-oh! It all went wrong!" + CHR$0 ALIGN
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 stringThis is exactly the same as DCx (above), simply understood by a different name.
=
' as a short-hand version of EQUB.
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.