I have also decided to make publicly available the most recent version of ASM11 (v2.10) and whatever updates may follow. This version has many features not available on the last public release (v1.84). Read the included PDF for more. Get it here: http://www.aspisys.com/freeasm11.zip
In both cases, three executables are included (DOS, Win32, and Linux i386).
Another update for ASM8 & ASM11 (v9.67) is available for download that adds two new features:
Download by clicking on the respective page's title in these pages:
Another update (v9.66) is available for download that fixes a very old, minor and obscure bug discovered just a few days ago. In short, some macro processing still went on even inside false conditionals resulting in the :mexit internal variable having the wrong number when tested right after a false #IF block in which that same macro was called.
Also, updated library code for the ASM8 case, including the addition of right-aligned numbers, and dot point insertion (floating point simulation) in the print macro (lib/print.sub). This allows a single @print macro call to send a string, number, variable, or constant to the output device.
Download by clicking on the respective page's title in these pages:
ASM8 and ASM11 v9.50. Improvements in the versions since my previous post here:
* A whole bunch of internal optimizations and improvements.
* Several minor bug fixes.
* IFNUM now detects hex and binary also.
* NEXT may now have no label on the left to simply advance the counter.
* Added :HOUR :MIN and :SEC internal variables to complement :YEAR :MONTH :DATE for assembly time clock.
* Added Zn and Fn { ... } formats to left fill with zeros or spaces.
* Two new built-in macro instructions INCH and DECH (ASM8 only)
* Added multiple paths capability to -I (Include) option. Separate paths with semi-colons. Use * to replicate current path if adding more paths to either side (before or after).
* Updated INCLUDE / USES / IFEXISTS search order to be relative to (a) main file's folder, (b) parent file's folder, (c) each include option folder, from left to right.
* #!IF #!IFZ #!IFNZ variants combine #IFDEF and the respective #IF
Added the following internal symbol to ASM8 and ASM11:
:CYCLES which returns the current value of the cycle counter.
The cycles counter is reset to zero as soon as it is accessed. To count cycles for a section of code, you must access :cycles twice, once before the code section to reset the counter to zero, and once right after the code section to get the accumulated cycles.
Because of the auto-reset on access, if you need to use the same value in more than one place at a time (for example, both in code and in a #Message directive), you must assign it to a label first, then use the label. If you simply want to display it with #Message you can use it directly.
Example use for the HC08 that automatically calculates delay constant (see ASM11 manual for HC11 equivalent):
Delay1ms | proc | |
#Cycles | ||
ldhx | #DELAY@@ | |
#Cycles | ||
Loop@@ | aix | #-1 |
cphx | #0 | |
bne | Loop@@ | |
#temp :cycles | ||
rts |
DELAY@@ | equ | BUS_KHZ-:cycles-:ocycles/:temp |
The obvious advantage is that if you alter the above loop code (as needed) it will still be timed correctly without requiring a manual adjustment of the delay constant.
Some of the latest changes (some are available only in the Win32/Linux versions) for ASM8 and ASM11:
1. Added #UNDEF (to be used with extreme caution)
2. Minor bug fixes (e.g., division by zero in {...} now shows ???)
3. Added new curly formats (6)..(9) for 32-bit labels.
4. Added #WARN and #NOWARN from within code (same as command line option -WRN)
5. #PUSH and #PULL now save/restore the active segment as well. Useful for general-purpose include files that may relocate.
6. Added :AB internal symbol which returns the number of address bytes used (3 for MMU, 2 for normal).
7. JMP-based instructions (including extras like JEQ) will be automatically corrected for the current page (in MMU mode) if both the source and the destination addresses fall on the same page and within the page limits. Makes it possible to use JMPs with paged code but without warnings if used within the page limits. Warnings will still show if jumping from/to outside the page.
#6 and #7 are not found in ASM11. #6 makes it possible to auto-adjust stack offsets for auto CALL/JSR and RTC/RTS selection based on current MMU mode.
(See updated stkmth32.sub example for how to write code to be loaded in either normal or paged memory without any source code changes.)
The latest version of ASM8 (Win32/Linux versions only) adds the following directives:
#SP and#SP1
#SP1 automatically adds one to all SP indexed offsets.
#SP cancels #SP1 (reverts to default/normal operation).
When enabled, all SP indexed instructions use the same offsets as their corresponding X indexed instructions right after a TSX instruction. This allows to use the exact same offsets for both addressing modes to access the same memory location(s)!
#PUSH and #PULL will save/restore the current setting of this option.
The assembler always starts in #SP mode (no auto correction).
For example, both LDA instructions in the code sample below will access the exact same memory when in #SP1 mode:
?A equ 0 #sp1 psha tsx lda ?A,x lda ?A,sp
On second look, I thought something was missing from the last update. With this one, I hope this feature has become a bit more useful.
I added an optional expression parameter to either #SP or #SP1. This allows automatic addition of an arbitrary number to the SP offset. This means, you can keep your offset labels clean from messy add-on constants at any time, such as when stack size is altered within a routine or when calling subroutines that access the parent routine's stack.
Although #SP1 is effectively the same as #SP with parameter 1, the two have different purposes. #SP with offset should be used to adjust for stack changes or subroutine nesting whereas #SP1 is meant to take care of zero-based vs. one-based symbolic (or numeric) offsets. So, for zero-based offsets you should be using #SP1 with whatever offset is required for taking care of stack size changes.
For this to work even easier, an extra internal symbol was necessary (P) which returns the currently effective offset (same for either #SP or #SP1 mode). You can use it to adjust the SP processing relative to a previous condition, so you don't have to keep a mental count of where things should be.
#PUSH and #PULL will save/restore this offset, also.
(Should you find any errors, I expect to hear from you.)
Example code follows:
;******************************************************************************* ; Example usage for #SP and #SP1 with optional offset ;******************************************************************************* ; Use #SP for one-based offsets (normal) ; Use #SP1 for zero-based offsets (same as if with X indexed mode) ; Optional offset is separate from #SP1 offset (added on top of it) org * ?A equ 0 ;zero-based offsets #sp1 ;(SP1 does not change :SP offset) psha tsx ;HX -> stacked data lda ?A,sp lda ?A,x call Sub ;near or far (MMU) subroutine pula bra * ;******************************************************************************* #sp1 :ab ;Adjust SP offset for RTS/RTC Sub lda ?A,sp ;lda ?A+2,sp OR lda ?A+3,sp (MMU) bsr SubSub ;yet another (local) subroutine rtc ;******************************************************************************* #sp1 :sp+2 ;Adjust SP offset for RTS (+2) SubSub lda ?A,sp ;lda ?A+4,sp #sp1 :sp+1 ;account for stacked A (+1) psha inc ?A,sp ;inc ?A+5,sp lda ?A,sp ;lda ?A+5,sp cmpa #3 blo ?SubSub.AOK lda #3 sta ?A,sp ;sta ?A+5,sp ?SubSub.AOK pula #sp1 :sp-1 lsl ?A,sp ;lsl ?A+4,sp rts ;******************************************************************************* #sp ;restore normal SP processing ;(no offset, no auto-increment)
A natural next step was to add a method for auto-adjusting the offset based on the encountered instructions that mess with the SP.
The #SPAUTO does that. It works together with #SP and #SP1. More details in the manual.
Example use:
1 F600 org * 2 3 0001 ? equ 1 4 0001 ?H next ? 5 0002 ?X next ? 6 0003 ?A next ? 7 8 F600:8789 8B [ 6] Sub push 9 10 #spauto 11 12 F603:A7F6 [ 2] ais #-10 ;allocate some temp variables 13 14 F605:89 [ 2] pshx 15 F606:9EE6 0E [ 4] lda ?A,sp 16 F609:9EE1 01 [ 4] cmpa 1,asp 17 F60C:88 [ 2] pulx 18 19 F60D:A705 [ 2] ais #5 ;de-allocate some variables 20 21 F60F:9EE6 08 [ 4] lda ?A,sp 22 F612:9EE1 07 [ 4] cmpa ?X,sp 23 24 F615:A705 [ 2] ais #5 25 26 F617:9EE6 03 [ 4] lda ?A,sp 27 F61A:9EE1 02 [ 4] cmpa ?X,sp 28 29 #ifnz :sp 31 #endif 32 33 F61D:8A88 86 [ 6] pull 34 F620:81 [ 4] rtc 35 36 #sp
You can even use it to check for balanced stack instructions. (The #ifnz :sp above would issue an error if there is a mismatch.) Example:
#ifnz :sp #Error Stack is unbalanced by {:sp} bytes #endif
You still need to manually fiddle with the offset (#SP like before), if the stack depth is changed in other ways.
ABOUT MACROS (THIS IS A BETA FEATURE, so expect to find errors.)
------------
Macro-enabled versions of the assemblers are named ASMx (where x is 8 or 11).
If you wish to use the previous stable non-macro enabled version, rename the
files ASMx_350.EXE to ASMx.EXE [Win32] and ASMx_350 to ASMx [Linux] (where x is
8 or 11, depending on the assembler used).
(The older versions are included until the new ones are stable enough.)
The normal documentation may not be updated to include macros until they are
found to work correctly in all respects.
Macro usage description.
To define:
MacroLabel MACRO optional parm description (parms here are ignored, actually)
macro body [any text (normally code) - unlimited number of lines]
macro body
macro body
macro body
macro body
...
ENDM
To use:
@MacroLabel Optional Parm1 !Optional Parm2 etc.
(@MacroLabel is located in the opcode column, and it may have a label field, if
needed.)
During invocation, 2nd and following parms always begin with the ! (exclamation
point). An exclamation point is normally used for decimal number definition
which is the default number base, so there will never be a need to use it within
a parm. Why not use comma or other symbols, you may ask. Simple answer: For
flexibility. Commas can be part of the parm to be used in instructions.
For example:
@mymacro 1,sp!2,x
are valid parms to be used with a macro body like this:
lda ~1~
sta ~2~
Parms are simple text replacements within the macro body. Any part of the
assembly instruction can be affected by the parms, even the label and opcode
itself, or even string contents.
When inside the macro definition:
~0~ thru ~9~ are placeholders which correspond to the current macro invocation's
actual parameters.
~0~ is reserved for the macro name itself. ~1~ thru ~9~ are macro parameters.
$$$ is a placeholder for macro-local labels. For example:
Loop$$$ ...
bra Loop$$$
will be correct no matter how many times the macro is invoked. The $$$ is
replaced with the unique number of the current macro invocation, and a special
control character to prevent unwanted collisions with user-defined symbols.
Parms can be used in labels, also.
caseKey macro
lda Key
cbeqa #~1~,Case~1~
cbeqa #~2~,Case~2~
rts
Case~1~ ...
rts
Case~2~ ...
rts
endm
invoked as:
@caseKey ESC !DEL
(note the ! which separates the second parm from the first.
Spaces in parms are copied also, but if they are trailing it usually poses no
problem, unless inside strings.
You could also do: @caseKey ESC!DEL
(no spaces between parms). But @caseKey ESC ! DEL
will make the second parm " DEL" (with a leading space) which will cause
problems.
Restrictions (possibly incomplete list):
* Macro names are always case-insensitive (just like regular language mnemonics).
* Macros cannot #Include files.
* Macros cannot define other macros.
* Macros cannot invoke other macros.
* Macro names are always visible (they cannot be made local with ?labels).
* While the macro is being defined (between MACRO .. ENDM), no code is parsed.
(Syntax or other errors will only appear when the macro is invoked.)
* When using parms inside labels or as opcodes, expect to see formatting issues
in the corresponding listing lines. This is expected behavior.
---
* Macro names do not conflict with normal labels. They have their own namespace.
* The @ symbol is used to invoke a macro. No conflict with opcode names.
* Unlimited number of macro definitions (memory permitting).
* Unlimited size of each macro (memory permitting).
Hope you like these changes, but please let me know of any issues you encounter.
I can't possibly attempt to solve any problems if I don't at least know about
them.
Added the following:
* #PARMS to allow changing or restoring the macro parameter separator. Default separator now is comma (for compatibility with most other assemblers.)
* #DROP to delete one or more macros (separated by commas).
* File-local macros (?labels)
* Additional macro-relative line number display in errors when expanding macros (easier to locate errors, if macro fails.)
* #IFPARM and #IFNOPARM conditionals (only from within macros) to check for parameter presence. Can be used to display expected macro usage, or for having macros with optional parameters.
* Several bug fixes related to macros.
For more details, read the macro.txt file in the related archive.
Some last minute improvements.
* Added #MLISTON or #MLIST and #MLISTOFF or #NOMLIST directives for turning on/off the macro expansion in listings.
I also prepared some example macros to see some of the possibilities.
Latest versions ASM8 and ASM11
One more (hopefully useful) update.
* A macro can now jump to another macro (this is not the same as nesting.) Once the new macro is started it will never return to the original one. This can be used to combine certain macros, or for creating loops (by jumping to same macro), like the example provided below.
FillMem macro From,To,Value ;Fill a memory range with value #ifnoparm ~3~ #Error Usage: @~0~ From,To,Value mexit #endif #if ~1~ > ~2~ mexit ;termination when "To" reached #endif org ~1~ ;at specified location fcb ~3~ ;place value @~0~ {~1~+1(h)},~2~,~3~ ;repeat with next location endm ;------------------------------------------------------------------------------- @FillMem $8000,$81FF,$AA ;test expansion of macro ;-------------------------------------------------------------------------------
* Labels and macro invocation parameters now understand expressions in curly brackets (like it is with strings). This allows creating labels dynamically. (Using simply placeholders when looping will eventually make the "counter" parameter string too long and cause various syntax errors, while using expressions will always keep the size the same.) For example:
#CaseOn ;to use actual macro name case Bit macro number ~0~{~1~}. equ ~1~ ~0~{~1~}_ equ 1<~1~ #ifz ~1~ mexit #endif @~0~ {~1~-1} endm ;------------------------------------------------------------------------------- @bit 31 ;test macro expansion ;-------------------------------------------------------------------------------
Should you find any issues, let me know.
Links for v4.51: ASM8 and ASM11
Just a couple of minor enhancements.
* Macros are invoked using the @MacroName[,parm] syntax. The macro name may be followed by a comma and any single character. If this option is found, then the character right after the comma will act as a one-time parameter delimiter (just for this macro call. The #PARMS defined delimiter will not be affected.) For example:
@macro 1,2
uses the default parameter separator (either a comma, or whatever you have defined with the #PARMS directive)
@macro, 1,sp 2,x
uses space as parameter separator for just this call, allowing comma to be part of the parameter.
@macro,, a,b
uses comma as parameter separator (in case your default isn't comma).
* The number of macro invocations appears right after the number of Included files near the end of the listing.
Also, I have updated the example macros for both CPUs, HC08/9S08 and 68HC11.
Could not get it to run in win7 x64, any plans to support that later?
Does is support RS08?
Is this assembler simple to use and get you started right away?
From the Amiga 68000 days i remmember Seka assembler.
And if it was not for QuickSharp (PC) for C# I probably would not even looked in to it.
Codewarrior is overkill and complex if I just want to learn how to flash some leds with a 8bit mcu.