chiark / gitweb /
Initial revision
[ssr] / StraySrc / Libraries / BAS / src / README
1 BAS -- the Basic Assembler Supplement
2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3
4         Once upon a time, this was meant to be a commercial Straylight
5         product.  I never got around to writing the documentation.
6
7         BAS is Yet Another tool for people who use the BASIC assembler.  The
8         odd thing is that Straylight use Acorn's `objasm' assembler for all
9         our `real' work.  The idea was to produce a procedure library for
10         generating linkable AOF code from BASIC, and the functionality grew
11         from there.  Features are:
12
13           * Generates AOF version 2 object code.
14           * Handles literal pools.  (I'll come to them.)
15           * Translates (a simple subset of) objasm header files.
16           * A small collection of other tools.
17
18         BAS is almost entirely written in assembler, with a BASIC procedure
19         library thrown in.  You don't need to worry about that -- the code
20         is tacked on the end of the BASIC file, so it all comes as one
21         package.
22
23 _____________________________________________________________________________
24
25 LICENCE
26
27         BAS is Free Software; you can redistribute it and/or modify
28         it under the terms of the GNU General Public License as published by
29         the Free Software Foundation; either version 2, or (at your option)
30         any later version.
31
32         BAS is distributed in the hope that it will be useful, but WITHOUT
33         ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
34         or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
35         License for more details.
36
37         You should have received a copy of the GNU General Public License
38         along with BAS; if not, write to the Free Software Foundation, Inc.,
39         675 Mass Ave, Cambridge, MA 02139, USA.
40
41         Of course, you can do what you like with the output of BAS.
42
43 _____________________________________________________________________________
44
45 AOF CODE GENERATION
46
47         I'll assume you understand how linkable objects work.  We'll be
48         here all day if you don't.
49
50         All code must be in an `area'.  You start an area by saying
51
52                 FNarea("NAME", "ATTRIBUTES")
53
54         The name can be anything you like; common names are `C$$Code' for
55         C code, and similar.  Dollars are popular for some reason.
56
57         The attributes define properties of areas, which in turn affect
58         positioning and access permissions.  We've tried to use the same
59         names as Objasm here:
60
61                 CODE            -- area contains code (implies `READONLY')
62                 COMDEF          -- definitons for a common area
63                 COMMON          -- overlay areas with this name
64                                         (implies `NOINIT')
65                 NOINIT          -- initialise this area with zeros
66                 READONLY        -- I don't need to write to this area
67                 DEBUG           -- contains debugging information
68
69         By default, areas with the same name are concatenated.  You get
70         given symbols `NAME$$Base' and `NAME$$Limit' to tell you the
71         boundaries of the complete area called `NAME', which is useful for
72         building tables.
73
74         Attribute names can be separated by anything you like -- they're
75         parsed by the BASIC library using INSTR.  Objasm uses commas, so
76         I tend to too.
77
78         A program generating AOF code will usually look something like this:
79
80                 LIBRARY "libs:BAS"
81                 PROCbas_init
82
83                 PROCbas_aofInit(SIZE)
84                 FOR o%=4 TO 6 STEP 2
85                 [       opt o%
86                         FNpass
87
88                         FNarea("Foo$$Code", "CODE, READONLY")
89                         ...
90
91                 ]
92                 NEXT
93                 PROCbas_aofSave / PROCbas_aofSaveAs(FILENAME)
94
95         Here, `SIZE' is the amount of space to reserve for the code, and
96         `FILENAME' is the name to save it as.  The PROCbas_aofSave function
97         uses the value of <BAS$Output> as a default filename: this allows
98         you to declare an alias
99
100                 Set Alias$BasAsm Set BAS$Output %1|mBASIC -quit %0
101
102         which you can use in Makefiles.
103
104         You're not limited to one assembly per source file -- you can create
105         any number of object files, although each one must start with a
106         call to PROCbas_aofInit and end with PROCbas_aofSave[As].
107
108         Note that you must begin each assembly by calling FNpass -- this
109         will set the P% and O% variables appropriately for the assembly, and
110         make sure that the BAS code understands where you are in the
111         assembly.
112
113         You can export a synbol (so that other object files can see it) by
114         calling FNexport; for example:
115
116                 FNexport("hello")
117         .hello  stmfd r13!,{r0,r14}
118                 ldr r0,FNlitsz("Hello, world")
119                 swi "OS_Write0"
120                 ldmfd r13!,{r0,pc}^
121                 FNltorg
122
123         Because AOF allows a wider range of identifiers than BASIC, you can
124         `alias' names as you export them; for example:
125
126                 FNexport("foo", "My$$FooishThing")
127
128         takes the value represented in the BASIC variable `foo' and exports
129         it as `My$$FooishThing' in an object file.
130
131         You import values in the same way:
132
133                 FNimport("malloc")
134                 FNexport("xmalloc")
135
136         .xmalloc
137                 stmfd r13!,{r1-r3,r12,r14}
138                 bl malloc
139                 cmp r0,#0
140                 ldmnefd r13!,{r1-r3,r12,r14}
141                 ldr r0,FNliterr(1,"Not enough memory")
142                 swi "OS_GenerateError"
143
144                 FNltorg
145
146         (I'll explain the FNlit... and FNltorg macros later.  Bear with me.)
147
148         You can also FNimportAs a symbol with a funny name:
149
150                 FNimportAs("Image$$RW$$Limit","program_end")
151
152         fetches the limit of the read-write area of the image, telling you
153         where the program ends.  This is quite handy.
154
155
156         How this all works is possibly interesting.  It (ab)uses offset
157         assembly, directing output (O%) to a buffer BAS allocates for you,
158         and starting P% at &FC000000, which is an illegal instruction, and
159         hopefully unlikely to appear in `real' code.  Once the assembly's
160         finished, BAS runs through and picks out references to things in
161         with addresses &FCxxxxxx and creates relocation directives for them
162         in the AOF file.  Imported things get given addresses &FDxxxxxx.
163         Assuming these values don't appear in genuine code, we're OK.  Just
164         in case you want to make arbitrary data appear in the object, BAS
165         has directives for disabling and reenabling relocation:
166
167                 FNnoreloc
168                 ...
169                 FNreloc
170
171         won't munge anything between them.
172
173         Finally, the call
174
175                 FNentry
176
177         marks the entry point in an AIF program -- execution will start
178         here.  That's all there is to it.
179
180 _____________________________________________________________________________
181
182 LITERALS AND LITERAL POOLS
183
184         Data like strings and absolute addresses are a pain in the BASIC
185         assembler -- you have to make up labels for them, and then reference
186         them.  BAS tries to handle this sort of thing for you, which is
187         rather more pleasant of it.
188
189         At any point in an assembly, BAS is building a `literal pool'.  You
190         create a literal using one of the supplied directives, and BAS is
191         responsible for putting it in a literal pool; it gives you the
192         address at which the literal will be placed in the finished output.
193         The current literal pool will be written to the assembly when you
194         call FNltorg.  A literal pool is also written at the very end of
195         the assembly.
196
197         Essentially, then
198
199                 adr r0,FNlitsz("Hello, world")
200                 ...
201                 FNltorg
202
203         is equivalent to
204
205                 adr r0,hello_string
206                 ...
207         .hello_string
208                 equs "Hello, world" + CHR$(0)
209
210         The literal creation macros provided are:
211
212           * FNlitw(WORD) stores a 32-bit value WORD at a word-aligned
213             address, e.g.,
214
215                 FNimportAs("Image$$RW$$Limit", "prog_end")
216                 ldr r0,FNlitw(prog_end)
217
218             puts the address of the end of the program in R0.
219
220           * FNlits(STRING) stores a string, unterminated, and non-word-
221             aligned.  This isn't very useful.
222
223           * FNlitmagic(STRING) stores an unterminated string at a word-
224             aligned address.  This is for things like
225
226                 ldr r1,FNlitmagic("TASK")
227
228             so you don't have to remember that this is &4B534154.  I
229             remember it anyway.
230
231           * FNlitsz(STRING) stores a null-terminated string at a non-word-
232             aligned address.  This is useful for all kinds of messages.
233
234           * FNliterr(NUM, STRING) stores a RISC OS error block at a word-
235             aligned address.
236
237         If you need some kind of structure which isn't provided, you can
238         build it yourself.  PROClitStart informs BAS that it's meant to
239         assemble a literal; FNliteral completes the literal, returning
240         the address where BAS will eventually put it.  FNlitAlign does
241         the same job, only it word-aligns the literal.
242
243 _____________________________________________________________________________
244
245 READING OBJASM HEADERS
246
247         FNget(FILENAME) reads an Objasm-format header file.  It's not perfect
248         but it tries hard.
249
250         Objasm directives supported are: `^', `#'. `EQU', and `IMPORT'.
251         This is hopefully enough for most purposes.  The `*' synonym for
252         `EQU' is also supported.
253
254         BAS can't understand Objasm macros.  Instead, it understands `active
255         comments'.  The only one implemented is `LIB':
256
257                 ;+      LIB     FILENAME
258
259         which loads the BASIC procedure library FILENAME.  A BAS macro
260         library `foo' must contain a function FNfoo_test, which is used by
261         BAS to see whether the library is loaded.
262
263 _____________________________________________________________________________
264
265 OTHER USEFUL TOYS
266
267         BAS defines a whole slew of constants:
268
269           * r0-r15, R0-R15, a1-a4, v1-v6, sb, sl, fp, sp, SP, lr, LR,
270             lk, LK, pc and PC are all set to the appropriate register
271             numbers.
272
273           * EQ, NE etc. are set to the appropriate condition code values.
274
275         FNalign aligns the output position to a word boundary, padding with
276         zero bytes. FNreserve(SIZE) writes SIZE zero bytes to the output.
277
278         FNbin(FILENAME) inserts the contents of the file FILENAME into the
279         output, protecting it from relocation.  FNfSize(FILENAME) returns
280         the size of the file FILENAME.  This can be handy for setting up
281         sprite areas.
282
283         FNws_start clears a storage-area counter to zero.  FNws_base(VALUE)
284         sets the counter to VALUE.  FNws_align word-aligns the counter.
285         FNws(SIZE) returns the counter, and increases it by SIZE.  FNws_word,
286         and FNws_byte are equivalent to FNws(4) and FNws(1) respectively.
287         These are useful for laying out workspace areas and data structures.
288
289         FNadrl(REG, ADDR) assembles a long ADR; FNadrccl(COND, REG, ADDR)
290         assembles a conditional long ADR.  FNaddl(REG, BASE, OFFSET)
291         assembles a long ADD; FNaddccl(COND, REG, BASE, OFFSET) does the
292         same conditionally.
293
294         FNldrl(REG, ADDR) assembles a long LDR; FNldrccl(COND, REG, ADDR)
295         assembles a conditional long LDR.  FNldrrl(REG, BASE, OFFSET)
296         assembles a long non-PC-relative LDR;
297         FNldrrccl(COND, REG, BASE, OFFSET) does that conditionally.
298
299 _____________________________________________________________________________
300
301 BUILDING BAS FROM SOURCES
302
303         This is quite involved.  You need to have:
304
305           * Acorn Desktop Assembler or later
306
307           * An implementation of `sed' -- I recommend the port of GNU sed.
308
309           * Straylight's basic library set (`header', `swis' and `stream')
310             available from the same place you got this from.
311
312           * A copy of Cy Booker's `ccrunch' BASIC compressor.  If you don't
313             have this, edit `remnames' and remove the `ccrunch' line -- the
314             BAS output file will be a little larger, but that's OK.
315
316         Build the ARM code part by running the Makefile.  Now run `Setup'
317         to mangle the nice BASIC library part, and to tack the code on
318         the end.  That should be it.
319
320 _____________________________________________________________________________
321
322 WHAT USE IS BAS?
323
324         Dunno.  Straylight were hoping to sell it for maybe fifteen quid a
325         go.  We use it in-house for building simple AOF-outputting tools;
326         our message-file and template-file compilers are BAS-based, for
327         example.  (These are available as part of the SDLS and Sapphire
328         packages, if they're out yet.)
329
330 _____________________________________________________________________________