home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
623a.lha
/
TurboDEX
/
Dex.doc.pp
/
Dex.doc
Wrap
Text File
|
1992-04-04
|
48KB
|
1,206 lines
TurboDEX Compiler v1.1 by $#%!
M A N U A L
Contents:
1. Introduction, The Features
2. Installation And Running
3. The Language In General
4. Step by step Tutorials
5. Alfabetical Overview Of Instructions
6. Advanced Programming And Language Info's
7. Additional Info's
-------------------------------------------------------------------------
CHAPTER 1, INTRODUCTION; THE FEATURES.
-------------------------------------------------------------------------
What is DEX ?
DEX is a Compiler-Language, like C, Modula2, GfaBasic, Pascal etc. it
features a similar programming structure and programming possibilities as
above languages. Yet you'll have to consider that DEX as to offer a lot
more, and, on the other hand, it's not a totally 'complete' language.
Dex Features:
- Possibility of clear program structure (like f.e. Pascal and Gfa, no
C-spaghetti).
- Short Executables; small to medium size DEX-sources will compile nearly
always compile to less than 1K, where above languages will need nearly
always more than 5K. (examples: the program given as an example with
the WRITE statement in the reference section would compile into an
executable of ± 300 bytes, the code of a complete vectordemo was done in
± 1300 bytes, and a shell in ± 500 bytes. All inclusive hunks,
reloc-tables, opening of librarys etc.)
- Clear assembly source output: DEX generates fully commented assembly
source, in which you will be able to find all the variables you used,
and compare the code-generation directly to the DEX-source.
- Direct access of all routines of EXEC, DOS, INTUITION, GRAPHICS and MATH,
without ANY includefiles and without opening ANY library. All
customchip registers can adressed by their name, without ANY include.
- Advanced features like Global/Local variables, easy calling of
procedures and libraryroutines with return values, inline assembly
code (like aztec C), use of registervariables.
- Faaast executables, extensive use of registers, fast parameter passing,
smart solutions for local variables and structs, quick optimization,
pc relative branching and adressing, special HYPER optimize mode for
loops and other instuctions where every clockcycle counts.
- Easy to manage development system: just one compiler will do the job,
no 5 meg of includes, linkfiles, objects, optimizers, profilers etc.
All instructions needed for writing a substancial program integrated
in the compiler.
What is wrong with TurboDEX? (in this version, that is.)
- some things haven't been implemented.
- some errors which you might make while programming are not recognised,
and will be compiled, (if you're lucky, a68k discovers them)
since no things like stack-overflow checking are implemented.
- Its mosly faster than above languages, but still not optimized enough.
- it doesn't do any type-checking, so things like dividing a CHAR
variable by a LONG, or messing up pointers to wrong memory-area's
are not flagged by the compiler.
- The compiler can be *very* slow sometimes
- The development system is not adequate for big app's.
- kick 2.0 compatible but not 2.0 specific (generates 1.2-and-up code).
- It's not idiot-proof.
Generally, DEX gets you ASSEMBLY quality performance an size executables,
with BASIC effort. But the prize to pay for this that the programmer
needs to know what he's doing. That's why this language is not ideal
for beginners, but more appropriate for advanced coders who want to
write a high performance util with minimum effort.
If you're eager to see what a DEX-source looks like, browse through
the drawer with examples, kick-ass with 'HelloWorld.dex', then check
out the other small sources. For your convenience here's some example:
' oh look, it's my first DEX program!
PROC main()
WRITE 'Hello, World!\n'
ENDPROC
' well, that was exiting, wasn't it? hmmm?
-------------------------------------------------------------------------
2. INSTALLATION AND RUNNING
-------------------------------------------------------------------------
How to work with TurboDEX.
First of all: all you really need is the compiler 'DEX'. just type
something like:
DEX [-opts] <sourcefile>
example:
DEX:> dex -a helloworld
the compiler will take a pure ascii file with the name 'HELLOWORLD.DEX'
as input in the current directory (this file contains some dex program
you wrote), and will produce a file 'HELLOWORLD.S' as output (this file
contains the assembly language translation from your DEX-source).
The -a flag will cause DEX to invoke A68k and Blink straight away, to
assemble and link the .S file..
Now type:
DEX:> HELLOWORLD
Hello, World!
DEX:>
If you don't use the -a flag, you'll have to assemble by hand. Almost
any assembler will do, supported are A68k and DEVPAC (tm).
Compile with an assembler like A68K and link it with for example Blink:
Dh0:> A68K HELLOWORLD.S
Dh0:> BLINK HELLOWORLD.O
Another example:
Dh0:> dex -flgr
This will enable you to pick your source by means of a file-requester,
dex will generate a list-file, invoke Devpac's GENAM instead of the
A68k/Blink duo, and execute your program afterwards.
Above is all you need.
Additional suggestions:
Best you shove DEX into your C: dir next to A68K and BLINK.
You may want to make Genam or Blink resident to speed up the process,
and if don't own a HD, copy DEX to ram: so you can
Compile-Assemble-Link-Run without disk Access.
NOTE: DEX outputs code suitable for A68K, so if you'd like to use
some other Assembler, you could be forced to make some minor changes.
(see -o option).
CommandLine Options:
Executing DEX with nothing following it will result in DEX opening
a window, where you can enter the commandline at the 'IN>' prompt.
options:
? Display a 'usage:' and some info
-a If compiling succeeded, invoke A68K and BLINK from the compiler.
NOTES: both need to be in the search-path (i.e: mostly C: or the
active directory). this will need c:run (<2.0) and some free-memory.
-c Don't add comments to assembly source (because you're not interested
in the generated code anyway), makes file smaller.
-f Pops up a filerequester to let you choose a source to compile
instead of having to enter it at the commandline.
-g Have GENAM (part of the Devpac (tm) assembler) assemble and
link your program. Includes -o, excludes -a.
-l Produce a list file named <source>.LIST, containing statistical
info's about the program, the compiler-status, and lists of
identifiers, procedures etc.
-o Generate assembly source for any other assembler than A68k.
-r Run the executable after being generated. needs -a or -g
-s Try to generate code that is more reliable, but slower. The compiler
will insert extra intructions to do extending of wrong-size variables,
and make some extra checks. This option must only be used for
test-purposes. Not guaranteed to help.
-t Don't compile file at the command line, but internal test-source
instead (for test-purposes only).
NOTE: options are case-INsensitive, may be put anywhere on the commandline,
and can be but together. so 'DEX -c test -A' has the same effect as
'DEX -ac test'.
Ok. Now over to the real stuff:
-------------------------------------------------------------------------
3. THE LANUAGE IN GENERAL
-------------------------------------------------------------------------
Procedures.
All programming instructions are gathered in modules, called PROCs.
The most important of these is the procedure PROC main() which always
has to be part of a program (it doen't have to be the first procedure).
this is the actuall program, where all variables are global. Other
procedures can be added, that can have own (local) variables. These
procedures can be called with or without parameters, like:
'VOID getpicture(rastport,x+4,y/8)'
Procedures cannot be called recursively.
Loops.
Lots of loops are supported, like FOR ... ENDFOR, WHILE ... ENDWHILE and
some others. These can be nested infinetely (well, nearly).
Variables.
At the moment 10 types of variables are supported:
- LONG, a 32 bit wide integer variable, can hold any value from
somewhat less than -2.14 to a little more than 2.14 milliard. this
is the most used variable since all addresses are kept in these,
most system routines expect longints, and nearly all calculations
are done in 32 bit.
- INT, a 16 bit variable, keeps values from -32k to +32k. Used with
multiplies/divides.
- CHAR, an 8 bit variable, most used with texts, and other small data.
range 0 to 255.
- REGLONG, REGINT and REGCHAR. These are the same ase those three described
above, with some small differences: - max. 6 of them can be used per
module, - 680x0 registers are used for their storage.
The advantage of these is mainly their speed, as wel as the smaller and
better code they produce. They are best used with DOWN loops, and
everywhere you need to have a certain part of your program to be as
faaast as possible.
NOTE WELL: these may only be declared with LOCAL
- ARRAY and ARRAYCHIP. These are simple implementations of arrays, and
function as CharArray only. They are defined as variable, and the
variable (compatible with LONG) contains a pointer to the array.
ARRAYCHIP is the version of ARRAY where the array is forced to
chipmem. (for the 'insiders': BSS_c ).
- CUSTOMREGS. all customregs can be used as variable. Just type the
official name in capitals, like DMACON. this enables lines like:
AUD0LEN := samplelen/2 or even COLOR00 := VPOSR*VHPOSR
its up to you to see which registers you can read or write.
- ABSOLUTE, if you would write or read absolute addresses, you can
use a value (specifying the adress) between [], following the variable-
name in the definition, like: sysbase[4]:LONG, would enable you to
use sysbase as an absolute variable. Like this you can specify a
variable as part of a STRUCT, which provides extremely flexibel
programming, like: depth[newscreen.8]:INT
all these variables (except for the CustomRegs) have to be defined before
use. See DEF in the reference section for more info's.
Other parameters.
these can be used as value only.
supported in this version are:
- Values: dependent on the instruction you use, values like 4, 100,
4543836, $ff, $c00000, %101110 etc. can be used.
- Adresses of labels and STRUCTS. you may need to now the address of a
label or stuct in your program. e.g. if somewhere in your program is
something like 'PROC text()', 'STRUCT text' or 'text:' the address could
be obtained with adr := {text} (use {} with the labelname).
- A text string. in the current version, strings that can be altered
are not supported. Though, you may give a string between '' as a
parameter. if the string is one character long, the ascii code will
be passed: c := 'A' equals c := 65 . If the string is longer, however,
the address of the string is passed, thus enabling flexible programming
were routines need the address of a textstring, for example:
VOID Text(rast,'Hello There !',LEN). LEN is a systemvariable, always
containing the lenght of the last string used. In the string you
may use the following codes:
\n a return + linefeed (ascii 10 and 13)
\a an apostophe, the one you need for enclosing the string
\t insert a TAB (9)
\e insert an escape-code (27), '\e[' will work as CSI.
\0 a null byte (not often needed, as all strings in DEX
are terminated with a '0').
\\ a backslash.
example: 'this: \a\\\a is a backslash \n\0'
Additionally, following codes may be used only when using a
string as part of a WRITE-statement:
\d print out a LONG as decimal.
\h print out a LONG as hexadecimal
\c print out a LONG as character
\s print out a 0-terminated string at address.
\w<x> sets minimum width for print, rest will be padded with spaces.
\z pad with zeroes instead of spaces.
\m<x> sets maximum width for strings.
\l put data to the right of the field (default).
\r put data to the left in the field instead of to the right.
example:
WRITE 'some results: \z\w8 $\h \c.',65535,65
will print:
some results: $0000FFFF A.
note: changes to print-formatting made with \w\z\m\l\r are only
valid within one WRITE-statement, they are reset to default
values at the start of the next statement.
- A string as integer value. you may use strings of lenght 1-4 between
double quotes ("") to, for example, quickly compare short strings:
IF {buffer}="FORM" and a := "A"
are equal to
IF {buffer}=$464F524D and a := 65
The first character is stored in the MSB of the LONG. If only
one character is supplied, it is stored in the LSB.
Parameters needed;
mostly a parameter could be one of 2 different types, in the description
of the commands that follows specified as var or exp.
var = parameter that must be a variable. examples;
a, count, COLOR01, etc.
exp = parameter that can be a variable, a value, or an expression (a
combination of more aspects). examples;
1, 200, $ff, a, DMACON, count+3/a-2000
these can be all mentioned above, including combinations.
For example, the parameter of FOR that is the counter would be a var,
and the two parameters specifying the range could be any exp(ression).
Expressions.
as stated above, everywhere an instructions needs a parameter that is
is an exp, you can use any of these operators with variables/values mentioned:
-,+ minus and plus, no restrictions.
examples: 3+a, 60-{text}+$ff
/,* divide and product, these are always done 16bit wide, watch
carefully when using them. examples: a/20, counter*256.
for 32bit operations, see MUL() and DIV().
&,^ AND and OR, used only as mathematical, not logical operators.
=,<,>,? comparisons. in the current version they are only usefull with
IF and WHILE. They need to be the last operator used.
In order: equal, smaller than, bigger than or equal, unequal.
examples: a=3, {data}-1024>$c00000, flag?0, 3*b+a
IMPORTANT: in the current version of the compiler, expressions are compiled
in the same order as written in the sourcecode, and () are not supported.
thus, a+(3*b) shouldn't be written as a+3*b, but 3*b+a, otherwise a+3 would
be calculated first, instead of 3*b. same goes for comparison (!) operators.
Labels and remarks.
in the current version, labels and remarks stand on their own line.
a label is any string followed by a ':' and can be used only to point at
instructions, not structs etc. (see above) example:
startofprogram:
when you program very structured, you won't need labels.
remarks start with a ' and are totally ignored by the compiler. f.e.:
' Here the screen is setup
Syntax.
first of all, the only place where spaces are obigatory, is after an
instruction keyword: WHILE<space>a=3
furthermore, the whole language is case sensitive.
uppercase: keywords, customregisternames
lowercase: variablenames, labelnames, procnames, structnames
both : systemcallnames. every part of the name starts of with
an uppercaseletter, like: VOID WindowToFront()
Startup options.
optional keywords about what sort of startup-code TurboDEX should
generate, may be given between the brackets of PROC main() :
ARG The variables 'argadr' and 'argl' contain the command-line
passed to your program (both LONG).
WB Code will be added to start your program from workbench too.
DETACH makes a program auto-detaching, can be started from shell
without 'C:RUN'
INIT compiles no initcode at all, no opening of librarys etc,
for programs that need to be _VERY_ small (<200 bytes),
rarely usefull.
example: PROC main(ARG)
NOTE: it is not advisable to use more than one option at a time.
Build-In Variables:
Presently, seven of them may be used: stdout, dosbase, graphicsbase,
intuitionbase and mathffpbase (execbase is DEF sysbase[4]:LONG).
When using these variables, code is genereated to provide a correct
contents, and, when using a function from a library, the base is also
defined. stdout contains the output filehandle (mostly the shell window),
when using the WRITE statement: when it's 0, you can open a CON:, and
put it's filehandle into the variable stdout. Furthermore, the variables
argadr and argl (both LONG) may be used if the flag ARG is used
in the header of main().
------------------------------------------------------------------------
4. STEP BY STEP TUTORIALS
------------------------------------------------------------------------
Assuming you copied DEX, A68K and BLINK to your C: directory, made
a directory for storing your sources and the examplesources, and
started up some editor to get things going, i will now give some small
tutorials on DEX-programming.
Best you try to get the HelloWorld.dex program running first. This
will give you a good impression on how the system works. load it in your
editor to see what it looks like:
' The HelloWorld program in DEX !
PROC main()
WRITE 'Hello, World!\n'
ENDPROC
Now, change it to your needs, save it, and compile it with:
DEX HelloWorld -a
After all compiling has been done, check the directory the source is
in. It should now contain two new files: HelloWorld.s and HelloWorld.
I'll get back later on the contents of the .s file, now just execute
the program by typing it's name. Please take note of the small size
of the executable (i guess about 300 bytes).
You now used the basis of any dex program: the PROC main().
this is the minimum of any program: you may add other procedures,
which may have arguments and local variables. The WRITE instruction
can be used for many more purposes than just writing string-contants:
it can print variables in decimal, hexadecimal and ascii format,
and nil-terminated strings. as an example we will now make a program
that prints the starting address of the exec.library to the screen:
PROC main()
DEF sysbase[4]:LONG
WRITE 'execbase = $\h',sysbase
ENDPROC
Here we do something new, we declare a global variable, like 'a'
DEF a:LONG
but now we state we would like to have it at a fixed address, $00000004.
We can print out the contents of the variable sysbase by putting
the formatcode '\h' (hexadecimal) in the outputstring, and the value
following it.
I will now discuss some of the programs to be found in the directory
with example sources to show how small programs could be developped.
First here's the SHELL.DEX program:
' TurboShell in TurboDEX
PROC main(DETACH)
DEF window:LONG, buffer=60:ARRAY, a:REGLONG, text:REGLONG
window := Open('con:10/10/400/100/TurboShell v0.0\0',1006)
VOID Write(window,'Shell by $#%! in 1991. \aquit\a to stop.\n',LEN)
WHILE text?"quit"
VOID Execute(buffer,0,window)
VOID Write(window,'Turbo> ',LEN)
a := Read(window,buffer,59)
MCHAR buffer+a,0
text := MLONG(buffer)
ENDWHILE
VOID Close(window)
ENDPROC
It's a very small program that show's clearly enough how to use some of
the language's features. Here's a step-by-step explanation of how
it works:
Because it's a small program, all code is gathered in one procedure,
and we tell the compiler that we want to give the Shell-prompt back
after our program is loaded with the DETACH option. Now we define
a couple of variables for use in the program: in 'window' we will
store the filehandle to our CON:-window, 'a' and 'text' are for use
lateron and buffer is an array of 60 bytes, which we will use to store
the commandline Note that 'buffer' is actually a variabele of the type
LONG which contains a pointer to that array. Now we use Open() from
the dos.library to open our console window, and we do not check if
an error occurred, for the simplicity of the example. Note that you
do not need include-files modules to be linked or whatever to be
able to use functions like Open, they're build in to the language.
Now we use the dos.library Write() (not the DEX WRITE!) to output
a message to it: We could have done this using WRITE, but the example
is about system-functions. Now we come in a loop which we will only
exit if 'text' is unequal to the (LONG-encoded) string "quit".
In this loop, we will Read() something from the console, and then
Exexute() it as a cli-command. Note that we use MCHAR (put a CHAR-sized
value into memory) to terminate the string.
Here's a somewhat longer example to get the feeling of how things
are done in DEX, COLORSCREEN.DEX
' Open a screen and do something
PROC main()
DEF rast:LONG,screen:LONG
DEF sx:REGINT, sy:REGINT
screen := screen(320,256,5,0,' TurboDEX Screen \0')
rast := screen+84
MOUSE
FOR sx,0,319
FOR sy,0,255
VOID SetAPen(rast,sx*sy)
VOID WritePixel(rast,sx,sy)
JUMPMOUSE leave
ENDFOR
ENDFOR
ENDMOUSE
leave:
VOID CloseScreen(screen)
ENDPROC
PROC screen( width, height, depth, mode, title)
LOCAL width[ns.4]:INT, height[ns.6]:INT, depth[ns.8]:INT, mode[ns.12]:INT
LOCAL title[ns.20]:LONG, return:REGLONG
return := OpenScreen({ns})
STRUCT ns
INT 0,0,320,256,2,$203,0,1
LONG 0,0,0,0
ENDSTRUCT
ENDPROC return
Because there's no command like OPENSCREEN in in DEX (yet), we make
a usefull procedure to easily open screen (see NEWWINDOW.DEX) for a
window example), which we can add to our sources anytime we want a screen.
We pass the characteristics of the screen via screen(), and get
back the pointer to the screen, which we should, in a non-example
program, check against zero. Note well: all local variables used are
declared as being part of a struct, which allows very flexible
addressing, and effecient code.
In the main program we enter the big MOUSE - ENDMOUSE loop which
is very handy for demo-like programs like this one. it is accompanied
by an extra JUMPMOUSE for faster exit. The inner loop draws the screen
full of colourfull pixels. Note the VOID intruction: we're not interested
in the returnvalues ( 'VOID' is like 'dummy:=' ), when calling the
procedure screen(), we are: ENDPROC gives us the screenptr.
Now we will look at a complete utility in DEX, with errorchecks
To make it usefull for everyday use: a three-column dir-command!
DIRQUICK.DEX displays filelenght too and makes use of extended WRITE
string-formatting.
' nice directory command in dex !
PROC main(ARG)
DEF lock:LONG, info=260:ARRAY, ok:REGLONG, d:REGLONG, c:REGLONG
DEF dir:LONG
MCHAR argadr+argl-1,0
lock := Lock(argadr,-2)
IF lock?0
ok := Examine(lock,info)
IF ok?0
dir := MLONG(info+4)
IF dir>0
WRITE 'Directory of: \s\n',info+8
c := 0
WHILE ok?0
ok := ExNext(lock,info)
INC 1,c
IF ok?0
d := MLONG(info+124)
dir := MLONG(info+4)
IF dir>0
WRITE '\e[1;32m\w25\m25\l\s\e[0;31m',info+8
ELSE
WRITE '\w17\m17\l\s \r\w7\d',info+8,d
ENDIF
IF c=3
WRITE '\n'
c := 0
ELSE
WRITE ' '
ENDIF
ENDIF
ENDWHILE
IF c?1
WRITE '\n'
ENDIF
ELSE
WRITE 'No Dir!\n'
ENDIF
ENDIF
VOID UnLock(lock)
ELSE
WRITE 'What ?!?\n'
ENDIF
ENDPROC
At every step in the program we check if an error may have occurred,
and we put all the nested IF's into one procedure: after making the
neccesary locks and examines, we read each entry, and put it directly
on the screen, directory's and files each their own color for distinction.
Those WRITE statements are good examples of somewhat more complex
string/integer formatting. Note we keep track of the column we're in
with variable 'c'.
Here's short description of all other examples:
DIRSORT.DEX An extented version of DIRQUICK.DEX, does a very
slow bubble sort on the entries before displaying, and
separates the directories from the files. can only read
dir's with less than 400 entries (changeable).
ASLREQ.DEX a demo of how non-DEX-standard-kick-2-libraries may be
used: it puts up the ASL-filerequester, and checks
nicely if you have KICK2, if it could open the library etc.
PLAYSAMPLE.DEX Show's how the buil-in hardware-register variables
can be used to play a beep.
COPPER.DEX Show's the ease of copper-programming from DEX
NEWWINDOW.DEX Opens a intuition-window and output's a text it.
ARG.DEX Show's how to handle commandline arguments from DEX.
SPEED.DEX Proggie to show off DEX's optimed loops.
RESIDENT.DEX Display's all exec resident modules. Shows how for example
system lists can be dumped.
VECTOR.DEX A vectorDemo in DEX that rotates the word 'TurboDEX' on
the screen in three colours, using the graphics.library,
double-buffering and a precalculated-coordinate list
in the file VECTOR.BIN. If you want to compile
this program, make sure the INCLUDE statement in the
source points to where you have the .BIN file.
-------------------------------------------------------------------------
5. ALPHABETICAL DESCRIPTION OF INSTRUCTIONS
-------------------------------------------------------------------------
-----------
AND, OR, NOT
-----------
syntax: AND value,variable
OR value,variable
NOT variable
description: Performs logical and, or and not on a variable.
NOTE: AND and OR are also available as operators in an
expression (&,^).
example: AND $ff,c
NOT x
-----------
ASM, ENDASM
-----------
syntax: ASM
ENDASM
description: all following this statement until ENDASM will not be compiled
by the compiler, and is put unchanged into the output file,
thus enabling inline assembly. if registers D2-D7 are used,
these should be put on the stack first. Make sure you use
distinct labels: best way is to prefix them.
example ASM
moveq #0,d0
ENDASM
-----------
CALL
-----------
syntax: CALL address, paraddress, returnvar
CALL base[offset], paraddress, returnvar
par: address = any memory location that is the start of a routine
base = base address of a library
offset = offset from a librarybase, like -552
paraddress = pointer to memory chunk of 14 longwords,
containing the parameters to a routine, in d0-d7/a0-a5 order.
returnvar = variable to put the returnvalue in
NOTE: both paraddress and returnvar are optional.
description: this instruction enables you to call any assembly language
subroutine, and in particular librarycalls that are not
part of the DEX set.
see the ASLREQ.DEX source for a good example.
example: ' assuming you have an initialized variable called 'aslbase':
CALL aslbase[-30],,reqadr
' this will call AllocFileRequest() from the asl.library
' reqadr may contain 0
-----------
CMOVE, CWAIT, CSKIP, CPART, CSTOP
-----------
syntax: CMOVE value,customreg
CWAIT rastline,rastpos
CSKIP rastline,rastpos
CPART
CSTOP
par: customreg = valid name for a customchip register, like: BLTSIZE
rastline = beam y position (0-255)
rastpos = beam x position (0-$E0)
description: Instructionset to code the copper coprocessor. these
instructions need to be gathered in a CHIPSTRUCT
See your Hardware Reference Manual for more information on
functioning of these instructions. CSTOP designates the
end of a copper-list, CPART needs to precede any intructions
that are to be executed after rasterline 255.
example: ' Split screen in two colors and be very rude to multitasking;
PROC main()
COP2LCH := {coplist}
INTENA := $4000
MOUSE
ENDMOUSE
ENDPROC
CHIPSTRUCT coplist
CMOVE $fff,COLOR00
CWAIT 80,$01
CMOVE $f00,COLOR00
CSTOP
ENDCHIPSTRUCT
-----------
DEC, INC
-----------
syntax: DEC value,variable
INC value,variable
description: Substracts or adds the value (-8 to 8 excluding 0)
to the indicated variable.
example: INC count
-----------
DEF, LOCAL
-----------
syntax: DEF varname:TYPE [, ... ]
LOCAL varname:TYPE [, ... ]
par: type = any of the types of variables discussed in the above
section of variabletypes (like LONG, ARRAY etc.)
varname = any string, signifying the name of the variable. may
be followed by = with a value (LONG, INT, CHAR only) to
initialize it before use (default = 0). Using = with ARRAY
signifies the size of the array (like string=100:ARRAY).
description: declares a variable before use, where DEF defines the
variables that can be used in any module (global), and LOCAL those
which can only be used in one module (local).
example: DEF adr:LONG, sign=25:CHAR, count:REGINT, string=256:ARRAY
LOCAL item[data.6]:INT, picture=10240:ARRAYCHIP
-----------
DIV, MUL
-----------
syntax: var := MUL(exp,exp)
var := DIV(exp,exp)
description: MUL and DIV are 32 bit substitutes for the * and / operators.
The 68000 processor doesn't support 32 bit multiplication and
division, only 16 bit. dex compiles * and / using 16 bit,
for speed reasons, and tries to use 32 bit shifts when
possible. Mostly this isn't a problem, but when it is,
the slower DIV and MUL routines can be called to use
the full 32 bit.
-----------
DOWN, ENDDOWN
-----------
syntax: DOWN counter,loops
ENDDOWN
par: counter = (var) variable decreased by the loop
loops = (exp) number of times loops should be executed
description: this is a simple FOR loop. the counter will be decreased
to zero, f.e. if you specify 100 for loops, the counter will
go from 99 to 0. the must end with an ENDDOWN.
NOTE: Because the only reason to use DOWN over FOR is
speed, it can only be used with REG variables (i.e. REGLONG).
example: DOWN count,1000000
' fast loop here
ENDDOWN
-----------
ENDPROC
-----------
syntax: ENDPROC returnvalue
par: returnvalue = (exp) result of the PROC
description: marks the end of a procedure and returnes a value to the
whatever called it. Default is zero
example see PROC example 2
-----------
EXIT
-----------
syntax: EXIT returnvalue
par: returnvalue (exp) = returncode for dos
description: exits program at any point in the program.
example: EXIT 5
-----------
FOR, ENDFOR
-----------
syntax: FOR counter,start,end [,step]
ENDFOR
par: counter = (var) the variable that counts the loops
start = (exp) begin value of counter
end = (var or value) value for the loop to end with.
step = a value between 8 and -8 (excluding 0), default 1
description: The loop will be executed as many times as specified by
start and end. meanwhile, the counter is being increased
with every loop. as standard, the counter will be increased
by 1, specifying a step changes this.
example: FOR counter,0,319,2
VOID Move(rast,counter,0)
VOID Draw(rast,counter,255)
ENDFOR
-----------
GOTO
-----------
syntax: GOTO labelname
description: continues the execution of the program within one module
at the place of the label.
example: IF a/20=3
GOTO someplace
ENDIF
' rest of the program
someplace:
-----------
IF, ELSEIF ELSE, ENDIF
-----------
syntax: IF equation
...
[ ELSEIF equation ]
...
[ ELSEIF equation ]
...
[ ELSE ]
...
ENDIF
par: equation (exp) = expression to be equated.
description: the programblock between IF and ENDIF will only be executed
if the expression is TRUE. if it is FALSE, however, it will
be skipped, and an ELSEIF block may be executed if that
equation is TRUE. If an ELSE block is present, it will only be
executed if all the other IF's were FALSE.
example: IF a>1000
WRITE 'hey dude, \d is a little too much!!!\n',a
ELSEIF a<0
WRITE 'what about that?\n'
ELSE
WRITE 'that's more like it!\n'
ENDIF
-----------
INCLUDE
-----------
syntax: INCLUDE filename
description: Includes any binary file into the program. Statement
needs to be part of a STRUCT to be accessed properly.
filename doesn't need quotes.
-----------
JUMPMOUSE
-----------
syntax: JUMPMOUSE label
description: If the leftmousebutton is pressed at the moment this
instruction is executed, execution of the program will be
continued at <label> (only within one module).
-----------
LONG, INT, CHAR
-----------
syntax: LONG value1, value2, ...
INT value1, value1, ...
CHAR value1, value2, ...
par: value = any number like 4, 100, $c00000 etc. additionally,
with CHAR you may use strings, like: CHAR 'hello\0', and with
LONG you may use the adresses of programlabels, like:
LONG vectordata .
description: with these statements you can put data of the appropriate
format into your program. they are only usefull within a
struct.
example: anylabel:
structadr := {anystruct}
STRUCT anystruct
INT 0,10240,512
LONG $c00000,anylabel,4
CHAR 0,25,'anystring\n\0',34,227
ENDSTRUCT
-----------
LOOP, ENDLOOP
-----------
syntax: LOOP
ENDLOOP
description: builds an infinite loop. Must end with ENDLOOP. be sure there
is an exit out of the loop.
example: LOOP
WRITE 'An everlasting loop\n'
ENDLOOP
-----------
MLONG,MINT,MCHAR
-----------
syntax: MLONG address,value
or
value := MLONG(address)
par: address (exp) = any valid memory address, with MLONG and
MINT this needs to be at an equal address.
value (exp) = the value to be 'poked' into, or read from
that memorylocation.
description: Commands similar to PEEK and POKE in basic, poke a longword,
word and byte respectively.
example: MCHAR $40000+a,b-1
-----------
MOUSE, ENDMOUSE
-----------
syntax: MOUSE
ENDMOUSE
description: these make a loop that will be repeated as long as the
left mousebutton is not pushed.
example: MOUSE
VOID movesprites(x,y,3)
VOID playtune()
ENDMOUSE
-----------
WRITE
-----------
syntax: WRITE 'string'
par: 'string' = any string of ascii signs, that may contain
codes with an '\' (see above for a discussion on strings
and codes).
description: prints any string and/or integers etc. to standard output
(normally the cli/shell window); can be used to write to
files by saying: stdout:=Open(...) etc.
example: PROC main()
WRITE 'Hello, World!\n'
ENDPROC
-----------
PROC
-----------
syntax: PROC name(par1, par2, ...)
par: name,par = any normal string like 'dosomething', 'rastport'
these must be defined in this PROC as local variables.
description: designates the beginning of a procedure. procedures should
not be nested, and the end of a procedure should always end
with an ENDPROC statement. Zero upto eight parameters can be
passed to localvars. Arguments for a PROC need to declared
as the first local variables in that module. for more info on
return values (as in example 2) see ENDPROC
Info on the main PROC can be found elsewhere
example 1 : PROC screenflash()
VOID DisplayBeep(0)
ENDPROC
example 2 : result=addition(x,y)
...
PROC addition(value1, value2)
LOCAL value1:LONG, value2:LONG
ENDPROC value1+value2
-----------
REPEAT, UNTIL
-----------
syntax: REPEAT
UNTIL equation
description: The block within REPEAT/UNTIL is repeated as long as the
truth for the equation holds. Thus, this loop will always
be executed atleast once: the UNTIL will jump to the
beginning of the loop if the equation is TRUE.
example: REPEAT
Read(fh,buf,10)
UNTIL {buf}="quit"
-----------
SIZEOF
-----------
syntax: size := SIZEOF(label)
description: SIZEOF returns the size of the STRUCT indicated by the label.
example: see STRUCT
-----------
STRUCT, ENDSTRUCT
-----------
syntax: STRUCT structname
ENDSTRUCT
description: this statemenent adds a struct to your program. it can be
anywhere in the program, since it will be compiled to a
place separate from the code. see description of LONG etc.
for more info's. The statements CHIPSTRUCT and ENDCHIPSTRUCT
function exactly the same way, but will be allocated in
chipmem (handy for copperlists, see CMOVE etc.).
example: a := SIZEOF(newscreen)
STRUCT newscreen
INT 0,0,640,256
LONG 0,0, ... etc.
CHAR 'WindowTitle\0'
ENDSTRUCT
-----------
WHILE, ENDWHILE
-----------
syntax: WHILE equation
par: equation = (exp) comparison to be equated.
description: the loop between WHILE and ENDWHILE is repeated as long as
the equation is TRUE. the program will continue after
ENDWHILE as soon as the equation is false. this loop must
end with ENDWHILE.
example: WHILE a/3+1 > 100
a := a-1
ENDWHILE
------------------------------------------------------------------------
6. ADVANCED PROGRAMMING AND LANGUAGE INFO'S
------------------------------------------------------------------------
This chapter is about:
- DEX <-> Assembly conventions.
- Code generated by DEX / Optimizing.
- Debugging.
- EBNF overview of DEX syntax.
- DEX as a language concept / The future of DEX.
To use the inline assembly feature without trouble, it's best to
know a few things about TurboDEX code-generation:
Register use: normally you may trash ALL (except A7, ofcourse!)
registers, since none are used to point at vital data during the
course of the program. However, REG variables are stored in D2-D7,
(starting with D7) so if you use these in your DEX code, you may not
trash these. Using REG-variables can also be a fine way to allocate
a register for permanent use in a PROC, for example:
PROC bla()
LOCAL a:REGINT, b:REGLONG
...
ASM
... (use D6/D7 here)
ENDASM
... (use a/b here)
ENDPROC
In this module you could store something permanent in D6/D7, without
the danger of getting them trashed: DEX will preserve these registers
if they need to be used for a (system-)functioncall.
This is the sort of PROC-setup you'd be using to obtain very optimized
code.
D0-D1/A0-A1 may ofcourse be trashed by assembly as well as DEX code.
Functions like WRITE are likely to trash more address-registers than
just these.
Sharing local and global variables:
Each variable has a label that can be used to access DEX-variables
from within the inline assembler, they are build as folows:
ModuleName + 'var' + VariableName
PROC bla()
Example: DEF screen:LONG gives EA: mainvarscreen
LOCAL a:INT blavara
ENDPROC
note that global variables always have ModuleName = 'main'
if you want to have an overview of the each effective address
then compile your program with option -l, also have a look at the
source (the .s file) TurboDEX generates to get the idea.
Accessing of labels and arrays is just as easy:
PROC main() will yield: proglabmain
DEF string=80:ARRAY arraylabstring
start: proglabstart
STRUCT newscreen proglabnewscreen
If your program uses functions from a certain library, the base of
that library can be accessed by LibraryName + 'base' (f.e. dosbase).
Debugging hints:
Apart from debuggingmethods that may be used on any language/compiler,
following are specifically handy with DEX:
- expressions: as these are different from other other languages,
it's very likely mistakes are made: check out the order of
operators/comparison's, problems that may occur when using/comparing
variables of different sizes (LONG/CHAR) etc.
- compile with -l to see if you possibly made errors in declaration
of variables etc.
- check variables that contain pointers, as DEX does no type-checking
- throwing the assembly source through a source-level debugger will
mostly indicate the problem :-) .
BNF overview of the language:
The compiler-builders under the readers may find it clarifying
to see some structural elements formalized (not complete):
<program> ::= { <procedure> }
<procedure> ::= PROC <label> ( <definitionlist> )
{ <defstatement> | <localstatement> }
{ <statementblock }
ENDPROC <exp>
<label> ::= <ident>
<variable> ::= <ident>
<ident> ::= <letter> { <character> }
<character> ::= <letter> | <digit>
<definitionlist> ::= <definition> { , <definition> }
<definition> ::= <variable> : <type> |
<variable> = <integer> : <type> |
<variable> [ <absolute> ] : <type>
<type> ::= CHAR | INT | LONG | REGLONG | REGCHAR | REGINT |
ARRAY | ARRAYCHIP
<integer> ::= <digit> { <digit> } |
$ <hexcharacter> { <hexcharacter> }
% 0 | 1 { 0 | 1 }
<absolute> ::= <integer> | <label> . <integer>
<defstatement> ::= DEF <definitionlist>
<localstatement> ::= LOCAL <definitionlist>
<statementblock> ::= { <statement> | <assignment> }
<exp> ::= <empty> | <expitem> { <operator> <expitem> }
<empty> ::=
<expitem> ::= <integer> | <variable> | '{' <label> '}' | " <ascii's> " |
' <ascii and format characters> '
<operator> ::= + | - | * | / | & | ^ | = | > | < | ?
<assignment> ::= <variable> := { <exp> | <procedurecall> |
<function> | <systemcall> }
<procedurecall> ::= <label> <argumentlist>
<function ::= <keyword> <argumentlist>
<systemcall> ::= <amigasystemcall> <argumentlist>
<argumentlist> ::= () | ( <exp> { , <exp> } )
<statement> ::= { <structuralstatement> | <otherstatement> }
<structuralstatement> ::= <conditionalstatement> | <loopstatement>
<loopstatement> ::= <repeatstatement> | <forstatement> | ...
<repeatstatement> ::= REPEAT <statementblock> UNTIL <exp>
<forstatement> ::= FOR <variable> , <exp> , <integer>
<statementblock> ENDFOR
<conditionalstatement> ::= <ifstatement> | ...
<ifstatement> ::= IF <exp> <statementblock> ENDIF |
IF <exp> <statementblock> <elseblock> ENDIF
<elseblock> ::= { ELSEIF <exp> <statementblock> } |
{ ELSEIF <exp> <statementblock> } ELSE <statementblock>
Some definitions are missing, some things are simplified, and
of all instructions only a few are taken as an example. Just
to give the reader a view on the matter.
DEX as a language concept.
As you might have noticed, DEX is not a complicated language when
it comes to structural and typological elements. It belongs to
a family of three languages sofar, and is derived from the language E,
which inturn has mostly been influenced by Modula2 and some C.
In DEX only the fundamentals of E are left, nearly all advanced features
of the language are not contained in DEX, and DEX has few enhancements,
some as replacement of the proffessional features in E, others just
Amiga-specific add-ons.
E
/ \
/ \
/ EEX
/
DEX
Another language in the family, also derived from E, is EEX. It
stands much closer to the original E language definition, and is
richer in structure, it only misses some of the complex OOP features
of E.
Import characteristics of E (and to some extend, also DEX and EEX)
as opposed to typical influences such as Modula2 (and some C) are:
1. The Principle of True Inline Assembly:
As no higher programming language can be an 'ideal' programming
language, because only Assembly is, E has the feature of true
inline assembly: assembly instructions are part of the language,
and are equal to E instructions when it comes to using identifiers
etc. Note that DEX has this feature only partly
2. The Principle of System-Integration:
the E language has OS-specific features in the core of the language.
Because of 1 and 2 principle 3 automatically holds:
3. The Principle of Non-Portability:
Languages like DEX and EEX derived from E are designed to be non-
portable: Programs should use machine-specific features (in this
case AmigaOs 1.2 and up) for highest quality app's.
4. The Principle of the Typeless Variables:
E is Typeless. Types, as do exist in DEX (not to mention Oberon),
are gathered to one, as for example in EEX, where all types are
LONG. Only where it comes to OBJECT's and reading CHAR's out of
memory, EEX has some type-definitions.
------------------------------------------------------------------------
7. ADDITIONAL INFO'S
------------------------------------------------------------------------
TurboDEX Compiler v1.1 released as DonationWare in 1992, first
public release.
Together with this distribution you will find A68k, Blink and their docs,
see those for distribution contraints. Thanx go to Charlie Gibbs (A68k)
and The Software Distillery (Blink), as well as Raymond Hoving and Chris
Straman (for their beta-testing and moral support :*-)
NOTE to future DEX coders: people that use DEX more than occasionally
and get stuck may count on full support by me, the compiler author. Send
your unsolvable problems or requests for hints/tips/tricks/enhancements
to me (i prefer electronic above paper mail). Also sources of for example
completed utilities in DEX may be send for inclusion in a library of
DEX-sources to be distributed with future releases for the benefit of
beginning DEX programmers.
Needless to say, but: TurboDEX may be copied, crunched and used freely as
long as the full distribution is with it, and no modifications are made
to either the executable, the doc or the supportfiles.. For spreading on (pd)
disk series other than that of Fred Fish you need my written permission.
I will personally RemHead() and AbortIO() those 'Pd-Distributors' that sell
this program for more than a copy-fee.
For those of you who don't know DonationWare, it's the same as Shareware,
with three principle differences: You may yourself decide on the size of the
gift, payment can be done in anything, and you don't have to feel guilty if
you don't send anything at all. Future versions, and other productions
(yes: lotsa nice stuf coming up) depend on YOU. (you guessed that .. right?)
Also bug-reports, nice letters, software, turboboards are all accepted as
donation ...
Wouter van Oortmerssen ($#%!)
Levendaal 87
2311 JG Leiden
HOLLAND
Or even better Email:
Wouter@alf.let.uva.nl