home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of A1200
/
World_Of_A1200.iso
/
programs
/
develop
/
ezasm
/
ezasm.doc
< prev
next >
Wrap
Text File
|
1995-02-27
|
33KB
|
1,445 lines
EZAsm Version 1.8 November '93 by Joe Siebenmann
DISCLAIMER:
You have the right to freely use, copy, and distribute
the files in this collection ( A68k and Blink have their own
distribution policies ) provided the following
conditions are met:
1. They are distributed together, and are not modified
in any way. Foreign language translations can be added.
2. They are not included in any package for profit
unless written consent from the author is obtained.
Inclusion in a PD series is OK as long as the
cost is REASONABLE.
------- NO LIABILITY FOR CONSEQUENTIAL DAMAGES -------
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DAMAGES
WHATSOEVER ARISING OUT OF THE USE OF OR INABILITY TO USE
THESE PROGRAMS.
--- New for Version 1.8 ---
o Bug fixes:
- Size arguments for "++" and "--" stopped working.
Thanks to Andreas Ackermann for the suggestions
and reporting the bug.
foo = Function() foo = Function()
foo != 0 Quit foo <op> <operand>
- In trying to optimize by eliminating the following "tst"
it could remove the 2nd statement by mistake.
Thanks to Martin Combs for the suggestions, testing,
ez.lib improvements, and bug reports.
- Problem with using "MACRO", "ENDM" above your code.
o Support for all the new 3.0 function calls, including
tag lists.
o Function argument syntax is now much more relaxed.
You can now use: "Permit()", "OpenWindow(NewWin)", etc..
o New optimizations using PC relative addressing.
A size decrease of over 11% was achieved on "scrwin".
o Better handling for allowing assembly statements to
come before EZAsm statements, and better detection of where
your code starts.
o Improved handling of paths for source and output files.
EZAsm was written to make programming in 680X0 assembly
language MUCH easier! EZAsm combines 680X0 assembly language
with parts of C. The result is highly optimized code,
with almost HALF the development time!
A68k ( by Charlie Gibbs ) and Blink ( from The Software Distillery )
are included, so you'll have everything you need to start
producing executables. ( except Commodore's include files )
Here are some of its advantages:
o Your code is converted into the fastest possible
assembly statement(s), so you automatically write
"good" code.
o More structured. Compare and bit test statements can have
braces and "else" like C. Being able to use braces lets
you use assembly language in a whole new way!
o C-like Amiga function calls! Every 3.0 function in every
library is supported.
o Import functions from libraries using ".fd" files.
o All needed libraries, including ".fd"s and resources,
are opened and closed automatically.
o Your code is much more readable, and easier to debug.
You can code nearly twice as fast, with fewer syntax errors.
o No more having to constantly look up which condition code to
use for compares, bit tests, or maximum numbers for
"moveq" or "addq" etc.
o You can freely mix assembly statements with "EZAsm statements".
You need to know a little about assembly language and
C operators before you dive right in. If you're new to
68000 assembly language, I suggest looking at one of the
many available books on the subject. The source code
for "Mk", "scrwin" and "scrwintags" are included as examples.
****************************************
Using EZAsm:
Create a directory, and copy these files into it:
EZAsm, A68k, Blink, Mk, ez.lib, nm1, dat1
You can either CD into your directory or take
advantage of the new path handling:
1. Add "assign EZASM: [path][YourEZAsmDir]".
2. Add EZASM: to your path: "path EZASM: add"
( Use "path" to check that it worked )
( Mk and EZAsm will first check to see if you're
CD'd into the directory, then will try looking for
the ASSIGN )
Paths:
If a path to the source file is given, the output file
will go to same directory. If no path, EZAsm uses the
current directory for source and output files.
( Another good method is to create an ALIAS to load these
files into VD0:, or RAD:, CD into it, and work from there )
Mk
Mk is a make-like program, written in EZAsm, that will
Execute() the necessary programs for you, creating an
executable file with a minimum of effort. It also
supports an optional include path for A68k, and support
for a ".mak" file. The source code is included.
( !! WShell users might need to rename Mk !! )
Usage:
Mk [-iPathToIncludes] [path]file
( where "file" is your source file, NO extension )
Execute()s these commands:
ezasm file.s
a68k [-iPathToIncludes] file.asm
blink FROM file.o LIB ez.lib TO file
.mak
For times when you need to supply more options for A68k or
Blink, or invoke other assemblers or linkers, Mk supports
a .mak file. Just create a file with the same name as your
source file, but with a ".mak" extension. The file should
contain the EZAsm, A68k, Blink or other commands, with any options
or switches you need, as if you were entering them from the CLI.
Any comments should begin with a non-alpha character.
If Mk finds the .mak file, it will Execute() those commands,
otherwise it will Execute() the standard commands.
Getting Started:
The best way to begin using EZAsm is to take your existing
assembly source and gradually make these changes:
- Eliminate all your opening and closing of libraries,
and any "SECTION" statements, EZAsm takes care of all
that for you.
- Declare your variables.
- Start replacing the statements that make up your Amiga
function calls with the simple C-style calls.
At your own pace you can: (1) Continue to "convert" chunks of
your code, or leave them alone. (2) Code new routines using
EZAsm/assembly statements.
***************************************
* Addressing Modes *
***************************************
Operand Type
Mode [A] [B] [C] [D] [E] [F]
Dn * * * - * -
An * - * - - -
(An) * * * * * *
(An)+ * * * * * *
-(An) * * * * * *
d16(An) * * * * * *
d8(An,Xn) * * * * * *
16 bit addr * * * * * *
32 bit addr * * * * * *
d16(PC) * - - - * *
d8(PC,Xn) * - - - * *
immediate * - - - * -
bd(An,Xn) * * * * * * 68020/68030
([bd,An],Xn,od) * * * * * * 68020/68030
([bd,An,Xn],od) * * * * * * 68020/68030
bd(PC,Xn) * - - - * * 68020/68030
([bd,PC],Xn,od) * - - - * * 68020/68030
([bd,PC,Xn],od) * - - - * * 68020/68030
declared variables:
"foo" becomes "foo(a5)" ( d16(An) )
**************************************
<1-8> 1 - 8
<q> -128 - 127
<n> any byte, word, or long size number
Dn d0 - d7
An a0 - a7
bd 32 bit displacement
od 32 bit outer displacement
Xn a0 - a7 d0 - d7
Options: Examples:
size: .w .l a2.w a0.l
scale: *1 *2 *4 *8 a1*2 a0.w*4 ( 68020/68030 )
{B} byte data size not allowed for An operands
**********************************
* legal * legal *
* operands * sizes *
**********************************
Addition Subtraction
++
--
[C] <op> L,W,{B} *
+=
-=
Dn <op> [A] L,W,B
An <op> [A] L,W *
[D] <op> Dn L,W,B
[B] <op> <n> L,W,B
[C] <op> <1-8> L,W,{B} *
Examples:
Total ++
d1 += 10
Optional Args:
l, w, b
* These are optimized by making the size word (.w)
instead of long (.l) for "An" operands. It's 4 cycles
shorter, and the upper two bytes are correctly handled!
********************************************
Multiplication Division
*=
Dn *= [E] W
Dn *= ## W *
/=
Dn /= [E] W
Examples:
d0 *= d1
d2 /= 2
Optional Args:
w,
s ( signed divs/muls )
* ( Improved! ) This optimization results in code that's larger then
"mulu" or "muls", but will execute much faster. Not all numbers
can be optimized. If the number doesn't work, "mulu"
or "muls" will be used.
( where ## is a word or byte length number )
*********************************************
And Or Exclusive-OR
&=
|=
Dn <op> [E] L,W,B
[B] <op> <n> L,W,B
[D] <op> Dn L,W,B
^=
[B] <op> Dn L,W,B
[B] <op> <n> L,W,B
Examples:
Mask &= %11010000
Flags |= $f0
Optional Args:
l, w, b
*********************************************
Shift Left/Right
<<
>>
Dn <op> Dn L,W,B
Dn <op> 1-31 L,W,B *
[D] <op> 1 W
Examples:
d2 << d0
d1 >> 4
Optional Args:
l, w, b,
a = Preserves the sign bit by using "asr" and "ext.l".
Use only with right shifts ( ">>" ).
* Normally you're limited to shifting 1-8, or using a
data register to hold higher shift values. This
optimized version is faster, and saves using a data register!
*********************************************
Assign
=
[B] = [A] L,W,{B}
An = [A] L,W
Examples:
temp = Total
(a1)+ = 0 w
Optional Args:
l, w, b
********************************************
The following Compare and Bit test statements
use this syntax:
operand <op> operand label
operand <op> operand {
.
.
}
operand <op> operand {
.
.
} else {
.
.
}
********************************************
Compare
>=
<=
!=
>
<
=
Dn <op> [A] L,W,{B}
An <op> [A] L,W
[B] <op> <n> L,W,B
(An)+ <op> (An)+ L,W,B
Examples:
Total >= 100 Over
Buf != 0 {
FreeMem( Buf 100 )
}
(a0)+ = $20 {
SPCnt ++
} else {
ChrCnt ++
}
Optional Args: ( placed AFTER label or brace )
l, w, b,
s ( signed )
*********************************************
Bit test
=
!=
Dn:0-31 <op> 0-1 L
Dn:Dn <op> 0-1 L
[F]:0-7 <op> 0-1 B
[F]:Dn <op> 0-1 B
Examples:
d1:0 != 1 EvenRtn
($bfe001):6 = 0 LMBDown
d2:d0 = 1 {
rts
}
Optional Args:
( ignored )
Rules:
o No spaces inside first operand.
o Right operand can only be 0 or 1.
*********************************************
Additional Arguments:
b forces operation to be byte
w " " " word
l " " " long
a preserves sign bit ( >> )
s signed ( *=, /=, compares )
( it's OK to use multiple arguments ( "w s" etc. ))
( these are RESERVED and can't be used as variables or labels
( unless you use upper case ) )
*********************************************
Functions:
o All 3.0 functions are now supported.
"OBSOLETE" functions are included to maintain compatibility
with earlier versions of the operating system.
See "nm1" for supported functions.
o All needed libraries including ".fd"s and resources
are opened and closed AUTOMATICALLY, and their bases
are added to your variables. ( resources don't need to
be closed ) ( See also "XFAIL", "LVER" )
All functions within these 3.0 libraries and resources
are supported:
amigaguide.library _AmigaGuideBase
asl.library _AslBase
battclock.resource _BattClockBase
battmem.resource _BattMemBase
bullet.library _BulletBase
card.resource _CardResource
ciaa.resource _CiaABase
ciab.resource _CiaBBase
commodities.library _CxBase
datatypes.library _DataTypesBase
diskfont.library _DiskfontBase
disk.resource _DiskBase
dos.library _DOSBase
exec.library
expansion.library _ExpansionBase
gadtools.library _GadToolsBase
graphics.library _GfxBase
icon.library _IconBase
iffparse.library _IFFParseBase
intuition.library _IntuitionBase
keymap.library _KeymapBase
layers.library _LayersBase
locale.library _LocaleBase
mathffp.library _MathBase
mathieeedoubbas.library _MathIeeeDoubBasBase
mathieeedoubtrans.library _MathIeeeDoubTransBase
mathieeesingbas.library _MathIeeeSingBasBase
mathieeesingtrans.library _MathIeeeSingTransBase
mathtrans.library _MathTransBase
misc.resource _MiscBase
potgo.resource _PotgoBase
rexxsyslib.library _RexxSysBase
translator.library _TranslatorBase
utility.library _UtilityBase
workbench.library _WorkbenchBase
All functions for these .devices are supported:
console.device _ConsoleDevice
input.device _InputBase
ramdrive.device _RamDriveDevice
timer.device _TimerBase
You're responsible for calling OpenDevice() and
loading the base to use these .device functions:
LONG _TimerBase TimeRequest
TimeRequest = AllocMem( 40 #CLEAR_PUBLIC )
beq Exit
OpenDevice( "timer.device" 0 TimeRequest 0 )
bne Exit
a0 = TimeRequest
_TimerBase = 20(a0) ;TimeRequest->tr_node.io_Device
.
.
o The cia.resource functions AbleICR(), AddICRVector(),
RemICRVector(), and SetICR() have been changed to
simplify the OpenResource(). The functions are now
AbleICRA() and AbleICRB() etc. and open the corresponding
ciaa.resource or ciab.resource.
o The leading underscores of the bases are necessary so you can
use includes without your assembler complaining. Some library
bases are already defined in some ".i"s resulting in
"multiply defined symbol" errors.
AllocMem(100 #CLEAR_PUBLIC)
^
| space required
o Function argument syntax is now much more relaxed!
Arguments must be separated by a space or tab.
a2 = ViewAddress()
d1 = Read( "DF0:myfile" Buf BufLen )
o Address or data registers can be used for returns if
they're more convenient. Return variables can be ANY size.
Variables used in function arguments must be LONG.
Arguments:
o You can pass registers to function arguments directly.
If the proper register is already loaded, just pass "*".
o You can also use these, and other addressing modes for function
arguments and returns: "(An)", "(An)+", "-(An)", "d16(An)" etc.
o EZAsm supports argument strings surrounded by double quotes.
Strings are automatically NULL terminated.
The following C character constants are supported:
\b backspace
\f form feed
\n newline
\r carriage return
\t horizontal tab
\v vertical tab
\\ backslash
\" double quote
\' single quote
\nnn octal character value
\xnn hex character value
Examples:
"Hello, World!\n"
"\x1b[32mEZAsm 1.8\x1b[39m\n"
END
NewWin ds.w 0 ;align
dc.w 0,0,640,200
dc.b -1,-1
.
.
o PC relative addressing is now used, when appropriate,
to reference data labels.
The following are used with FUNCTION ARGUMENTS and STATEMENTS
when referencing declared variables and data labels:
Address of:
#NewWin
&NewWin
( These can go to an address or data register:
"move.l #NewWin,Dn", "lea NewWin[(pc)],An" )
Contents of:
NewWin
o Sometimes you have to "play around" with using "#", "&",
variables, constants etc.. Also taking into account if it's
being pushed onto the stack. You might be giving it the
CONTENTS of a variable, when it needs its ADDRESS. ( etc. )
o It keeps track of the current library base. As long as no user
labels, or close braces are hit, it will skip reloading
the base register for functions which use the same library base.
OpenScreenTagA( 0
SA_Width 640
SA_Height Hgt
SA_Depth 2
SA_DetailPen -1
SA_BlockPen -1
SA_Type $f
SA_Quiet 1
SA_DisplayID $8000
TAG_END )
Tag list Functions:
Tag list functions are now supported. When using the
"varargs" version of a function ( above ), the tag list
arguments are built as data, and the function argument is
converted to a pointer to the data structure.
The following functions HAVE BEEN CHANGED for consistancy:
( was ) ( now )
_DOSBase:
SystemTagList SystemA
[System] System
[AllocDosObjectTagList] AllocDosObjectA
AllocDosObject AllocDosObject
[CreateNewProcTagList] CreateNewProcA
CreateNewProc CreateNewProc
_AslBase:
AllocAslRequest AllocAslRequestA
[AllocAslRequestTags] AllocAslRequest
AslRequest AslRequestA
[AslRequestTags] AslRequest
_GfxBase:
ExtendFont ExtendFontA
[ExtendFontTags] ExtendFont
_IntuitionBase:
OpenWindowTagList OpenWindowTagA
[OpenWindowTags] OpenWindowTag
OpenScreenTagList OpenScreenTagA
[OpenScreenTags] OpenScreenTag
o It knows about every 3.0 tag ( "SA_Height", "WA_Width" etc. )
and they'll automatically be converted to their
equivalents ( $80000024, $80000066 ), no includes are needed.
All the supported tags are listed in the file "nm1"
below the function names.
o It's important to use these tags! That's how it differentiates
between 'regular' and tag list function arguments.
o Tag lists MUST be terminated with "TAG_DONE", "TAG_END"
( with NO '0' tag data ) or "TAG_MORE" ( with a tag list address ).
o Be sure to add an include when using tag data arguments like:
"TRUE", "FALSE", "CUSTOMSCREEN" etc.
o The closing parenthesis ( ")" ) shouldn't be on a separate line.
You should have at least one argument before it. 8^(
o Variables used for tag data arguments can be ANY size, and are
correctly loaded automatically.
o When importing tag list functions from libraries and using
"unknown" tags, I'd recommend setting up a tag list data structure
like EZAsm does, use includes, and pass its address.
*********************************************
Importing functions from library ".fd"s
Usage:
PROTO [path]LibraryName [path]FDName
Example:
PROTO req.library req.fd
Where PROTO is in upper case, begins at column 1, and
is placed ABOVE your variable declarations. The ".fd"
file is read, and all its functions, both "##public"
and "##private", become available for use. The
library base is added to your variables, and the
opening and closing of the library is handled
automatically.
To avoid any conflicts with other function names, these
are used first. Up to 10 ".fd" files can be used.
"PROTO" is most useful for "importing" functions from
libraries like req.library and reqtools.library, and
updating the standard Amiga libraries when new versions
of the operating system come out. You can also define YOUR
OWN functions, or fix a "buit-in" function's offset or
argument register(s). Here's an example:
##base _DOSBase
##bias 102
Examine()(D1,D2) ;( arguments within the first "()" are ignored )
##end
( the default bias is 30 )
*********************************************
Option switches:
Using command line arguments:
Because the automatic opening of libraries will
corrupt A0 and D0, the following "switches" are provided:
ARGS A0 is loaded into the variable "Args" ( automatically
created ) and "clr.b -1(a0,d0.w)" is used to NULL terminate
the argument string. The length in D0 is lost.
( see Mk.s for an example of using "ARGS" )
SAVEARGS
A0 and D0 are pushed onto the stack with "movem.l d0/a0,-(sp)".
You're responsible for restoring and using them.
Other useful switches:
SAVEREGS
Pushes registers YOU REQUEST onto the stack at the start of
your code, and restores them before exiting.
Usage: SAVEREGS register list
Example: SAVEREGS d2-d4/a0-a3/a6
Where register list contains no spaces, and will generate
these statements: "movem.l d2-d4/a0-a3/a6,-(sp)"
"movem.l (sp)+,d2-d4/a0-a3/a6"
NOPC Turns off PC relative addressing optimizations.
NODOT Changes labels ".cn", ".ln" and ".tn"
to "_cn", "_ln" and "_tn" for Devpak users.
OPT4 Uses "$4.w" instead of "$4" to load ExecBase, and
"lea n.w,An", "pea n.w" when appropriate.
( If you don't use A68k, I'd recommend using this.
A68k makes these optimizations, but doesn't like the
"$4.w" syntax )
EXT Allows you to specify the extension of the output assembly
file. The default is ".asm". Example: EXT .a
NOEXTRAS
Removes the loop clearing the stack frame and insertion of
"moveq #0,d0", "rts" at the end of the code.
XFAIL Prevents your program from exiting if OpenLibrary(), for
the specified library, fails.
Example: XFAIL reqtools.library
LVER Allows you to specify a version number for an OpenLibrary().
Example: LVER intuition.library 36
*********************************************
Optimizations:
In addition to the many "standard" optimizations performed
on statements, the following are also performed:
STATEMENT BECOMES NOTE
An = 0 sub.l An,An
[B] = 0 clr [B] 1
( compares )
[B] < 0
[B] >= 0 5
[B] = 0
[B] != 0 tst [B] 6
bxx label
----------------------------------
[B] += <q>
[B] -= <q>
[B] &= <q>
[B] |= <q>
[B] ^= <q>
[B] = <q> moveq <q>,d7 2
[opr].l d7,[B]
( compares )
Dn <op> <q> moveq <q>,d7 2
cmp.l d7,dn
bxx label
An <op> <q> moveq <q>,d7 2
cmpa.l d7,an
bxx label
----------------------------------
An += <i> lea i(An),An
An -= <i> lea -i(An),An 3, 2
An = <n> lea n,An 4, 2
<i> maximum: -= 32768 += 32767
Notes:
1 For byte and word sizes the code size is smaller, for long
its smaller and faster. ( then "move #0,[B]" )
2 Only apply to long sized operations.
3 ( 1-8 handled by "addq", "subq" ( see note in Addition Subtraction ))
4 ( 0 handled by "sub.l An,An" )
5 Taken as signed.
6 In some cases "tst" is eliminated, or D7 is loaded, see below.
More optimizations:
Buf != 0 {
FreeMem( Buf 100 )
}
( standard ) ( now )
tst.l Buf(a5) move.l Buf(a5),d7
beq .l2 beq .l2
movea.l $4,a6 movea.l $4,a6
movea.l Buf(a5),a1 movea.l d7,a1
. .
. .
o Instead of doing a "tst", the variable is loaded into D7
( flags set, and same size and number of cycles ) where it can
be utilized by a following function call. In this case it
loads D7 into A1, saving 2 bytes, and taking only 4 cycles
instead of 13.
Fhandle = Open( "df0:myfile" 1005 )
Fhandle = 0 {
.
.
}
. .
. .
move.l d0,Fhandle(a5) move.l d0,Fhandle(a5)
tst.l Fhandle(a5) bne .l5
bne .l5
o The flags are set by the "move", so the "tst" instruction
can be eliminated, saving 4 bytes and 9 cycles.
( a label before the "Fhandle = 0 {" statement disables this )
foo > 10 {
.
.
[jmp statement]
} else {
.
.
}
o In cases where a [jmp statement] ( "jmp", "bra", "bra.s",
"rts", "rte", "rtd" or "rtr" ) is immediately above
the "else" ( above ), normal label generation ( etc. ) for
jumping past "else" is eliminated.
*********************************************
General Info:
o Statements can be indented as you like. Operands, operator,
and arguments must be separated by at least one space or tab.
o Braces can be nested up to 30 deep.
o Only one statement per line.
o Comments must begin with "*" or ";" and begin at column 1, or after
statements ( separated from last argument or operand ) using ";".
( both types are transferred to the output file ( some may not ))
o Operands supported: @141 (octal), $61 (hex), %1100001 (binary),
'a' (ASCII), 97 (decimal). ASCII strings in operands can
contain a maximum of 4 characters.
( no quotes within quotes permitted )
o To make labels and symbols as compatible as possible, they aren't
checked for illegal characters. Typically the 1st character
must be a letter, underscore "_", or a period ".".
The rest of the characters can be any of these plus 0-9.
o Labels and symbols are limited to a length of 127.
( Check your assembler to find what length they're
significant to ( usually around 30 ))
o Labels that don't begin at column 1 must be followed immediately
with ":", otherwise, use of ":" is optional.
o Temporary labels of the form n$, where n consists of decimal
digit(s), are supported. These labels are only in effect till
the next non-temporary label is encountered. ( be careful
of "hidden" labels generated by braces )
o "moveq #0,d0", "rts" is automatically inserted for you in the
closing block of code. ( See also "NOEXTRAS" )
o D7 is used as a scratch register for many optimizations, so be
careful if you use it.
o Labels and constants that are generated are in the range:
".l0" to ".ln" Program labels
".c0" to ".cn" String constants
".t0" to ".tn" Tag list labels
Try to avoid accidentally using them.
( See also "NODOT" )
o "SP", "PC", "CCR", "SR" & "USP" ( upper or lower case )
are supported, but you must ensure it's used correctly.
o For best viewing of the output file, set your tabs to 8 spaces.
( printing should be fine )
IMPORTANT! :
Don't use register A5! It holds the base address of the
stack frame used for variable storage.
*********************************************
Variable Declaration:
LONG foo bar
WORD DMASave
BYTE Sw ViewPort[40]
o "xxx[n]" reserves n consecutive blocks of given size,
with "xxx" pointing to the left-most byte.
( this is for advanced users who need a convenient
way to allocate SMALL chunks of stack memory for structures,
saving registers, etc. )
o You're limited to 14 variables per line.
o No other statement types may occur between these lines.
o Variables must be separated by at least one space, or tab.
o To keep things word aligned, if an odd number of variables are
declared in BYTE, an extra byte will be added.
( this will offset the next "equ" by one )
o Declarations must occur JUST BEFORE your program code,
and begin at column 1, with LONG, WORD, or BYTE in upper case.
o EZAsm uses "link" to allocate space for variables on the stack.
The maximum size of this space is 32K. Since this stack space
contains "garbage", code is added to clear it out before use.
( The frame size is now rounded up to the nearest LONG )
What the stack frame looks like:
LONG foo
WORD bar Total
LONG Count
becomes...
foo equ -4
bar equ -6
Total equ -8
Count equ -12
h l A5 base register
i o |
OOOO OO OO OOOOO memory bytes
(-) <- 1119 87 65 4321
210
( Sometimes variables are "adjusted" for proper loading, and
"-2(a5)" or other displacement may appear in the output file
instead of "foo(a5)" or other variable name you might be expecting. )
*********************************************
General Info:
o It's now much more forgiving about your placement of
assembler directives, and smarter about detecting where
your code starts. If you experience any problems
( it hit an assembly directive it didn't recognize )
try placing your data statements below "END",
and "equ", "xref" and "xdef" type directives above your
variable declarations, or below "END".
( In the final .asm file "END" will be adjusted )
o Instruction size: IN MOST CASES YOU WON'T NEED
A SIZE ARGUMENT. It knows the size of your variables,
address and data registers, and is smart enough to know
what size to use. You'll need to specify a size if
the data is smaller than the instruction size you want,
( d1 = $20 w ) or it can't know the size of the operands
( (a2)+ = 3(a0) l ).
Caution: Be aware that if you load small variables into
larger ones, the upper bytes aren't cleared and
may garbage your result. Always initialize those
variables, or restrict the size of further
operations to "b" or "w".
o Try not to overuse the size arguments. Once you get confident
it's sizing your instructions correctly ( by checking the
.asm file ) you'll find you can eliminate their use almost
entirely. By needlessly restricting a long operation to
a word, or byte, you can miss the "quick" optimization.
o Since "(a1)" refers to the CONTENTS of the byte, word, or long
that A1 points to, "($dff180)" is used in a similar way.
( decimal addr's are also valid: "(14675968)" )
o Numbers are "converted" for you. ( $f2 -> #$f2 37 -> #37 )
Operands it doesn't recognize, like "wd_UserPort(a2)",
are output "as is".
o Large programs: If your executable size is near 32K, it's
possible that PC relative optimizations may turn off too soon,
or stay on, incorrectly, when the displacement is exceeded.
o If at any time you're unsure of what a statement is being
output as, or want to check something out, just look
at the output .asm file. Well placed blank lines in your
source code can enhance its readability.
o I think it's a good idea to get away from using include files.
Most assembly source files I see do this.
It speeds up the assembler tremendously, and saves
endless wear and tear on your drives.
****************************************************
Converting C to EZAsm:
Its fairly easy to convert any C code into
EZAsm if you follow these guidelines:
Allocating structures:
Whenever you see "struct VSprite SpriteA" etc.,
you need to either allocate some memory for the
structure, or set up your own:
CLEAR_PUBLIC equ $10001
LONG SpriteA
SpriteA = AllocMem( [structure size] #CLEAR_PUBLIC )
beq Exit
---------- or ----------------
SpriteA ds.w 0 ;align
dc.l 0 ;NextVSprite
dc.l 0 ;PrevVSprite
.
.
( you could use "#vs_SIZEOF" etc. for [structure size]
and let the assembler get its size from the includes )
Some functions will create the structures for you
and return a pointer to it ( OpenWindow(), OpenScreen()
etc. ) just declare a LONG, and load the returned pointer:
LONG Window
Window = OpenWindow( #NewWindow )
beq Exit
Accessing structure elements:
Often you'll need to get at data inside structures.
First load the "structure pointer" into an address
register, then use the offset of the structure element.
Here's a typical example:
Move( Window->RPort, 20, 20 ); /* C */
a0 = Window
Move( wd_RPort(a0) 20 20 )
---- or ----
a0 = Window
Move( 50(a0) 20 20 )
( add an include to your source, and the assembler
will look-up "wd_RPort" and substitute its offset or,
even better, use "50(a0)" )
!!! See the included file StructOffsets !!!
Be sure to convert BPTRs ( left shift 'um 2 bits )
before using them:
a3 = _DOSBase
Forbid()
a3 = 34(a3) ;dl_Root
a3 = 24(a3) ;rn_Info
add.l a3,a3 ;convert BPTR
add.l a3,a3
.
.
*********************************************
Errors:
"Illegal argument"
The argument found was not valid for the operator. See
the list of "Optional Args" for the operator. It must
be lower case, and be separated from the operands
by at least a space or a tab.
"Illegal operand"
One, or both, of the operands are: not valid for the operator,
have an invalid number, or byte size was specified for an
"An" operand ( {B} ). In most cases it's looking for "Dn" or "An"
as one of the operands. ( look under the "legal operands"
of the operator for a valid combination )
"Illegal size"
The argument size you specified is not valid for the operator.
Check the "legal sizes" for the operator.
"Needs size argument"
It doesn't have enough size information about the operands to
calculate an instruction size.
You need to add an l, w, or b argument.
"Label not found"
No label matching your label argument was found.
"Brace mismatch"
Checks are made when a closing brace ( "}" ) is hit, and when "END"
is hit. If the brace stack is "messed up" at that time, an error
is given. If "}" is shown, look from there up. Both "}" and "END"
may appear. If just "END", look for a "{" or "} else {" without a
matching "}".
"Function not found"
No function matching your function name was found. Check case and
spelling of function name, and be sure there isn't a space before
the "(". Check the list of supported function names in the
file "nm1".
"Function argument count incorrect"
Check the number of arguments you used for the function. Too many
or not enough were used. With string arguments, check for
a missing '"'. Also look for a missing end ")".
( EZAsm doesn't do much checking of normal assembly statements.
A68k and Blink will catch any problems missed by EZAsm and bring
them to your attention )
*******************************************************************
*******************************************************************
Try using EZAsm, I don't think you'll want to go back to
"ordinary" assembly language programming. 8^)
Why isn't EZAsm shareware? I don't think you can make much
money with shareware. I'd like to get it into the hands
of as many interested people as possible because I believe
it'll really make a difference. If you have any suggestions
for improvements, found bugs, or just want to say "hello",
please write, I'd like to hear from you!
Enjoy!
You can reach me at:
Joe Siebenmann
2204 Pimmit Run Lane Apt 1
Falls Church, VA 22043
( USA )
(703) 893-2579