Mimas User’s Manual

Version 0.2
October 2010


Mimas is an integrated development environment for writing Z80 assembly programs on the Texas Instruments TI-83 Plus, TI-84 Plus, and TI-Nspire graphing calculators. Using Mimas, you can write, compile, and run programs in assembly language, entirely on the calculator; no PC or other tools are required.

The latest version of Mimas can be found at ticalc.org. Mimas is free software; you are permitted (and encouraged) to distribute it to others, and/or modify it to suit your needs, under the terms of the GNU General Public License.

Contents

Getting Started

(Screenshot)

When you first start Mimas, the main menu is displayed. Select “1: New Program” to create a new program file, or “2: Open Program” to open an existing file.

(Screenshot)

The New Program dialog is used to create a new assembly program. The name of the program must be a legal variable name (i.e., it must begin with a letter), and must be unique. (If a file with that name already exists, the existing file is opened instead.) You can also select a program type (“Asm(”, “Ion”, “MirageOS”, “DoorsCS7”, or “Library / Other”.) Based on the program type you select, Mimas will insert an appropriate program header. (You can, of course, change this header later if you wish.) Press [ENTER] or [GRAPH] (“OK”) to create the program.

(Screenshot)

The Open Program dialog shows a list of existing assembly programs. As in normal OS menus, a star is displayed to indicate that a program is archived. Press [ENTER] or [GRAPH] to open the selected program.

Editing Program Sections

(Screenshot)

After you create or open a program, the program section editor is displayed. Sections serve two purposes: they can be used to divide a large program into more manageable pieces, and they allow you to define the order that parts of the program will be assembled. (“Header” sections will be placed first, followed by “code” sections, then “data” sections, and finally “footer” sections. Separating code from data is important for large programs due to the calculator’s execution restrictions.) By default, a single code section will be created for you, called MAIN.

To create a new section, select “New Section” and press [ENTER]. You can also add a new section in the middle of the program, by moving the cursor to the place where you want to insert a section, and pressing [WINDOW] (“Ins”).

To delete a section, press [ZOOM] (“Del”). You cannot delete a section that has code in it; delete the code first.

Press [Y=] (“Edit”) to edit the selected section (see Editing Assembly Code.)

Press [GRAPH] (“Menu”) for more options:

1: Libraries Edit the list of libraries used by this program (see Using Libraries.)
2: Compile Program Compile the program (see Compiling Programs.)
3: Archive Program Archive the program (see Archiving Programs.)
4: Close Program Close the program and return to the main menu.
5: Quit Quit Mimas and return to the calculator OS.

Editing Assembly Code

(Screenshot)

The program code editor is similar to an ordinary text editor, with an important difference: the text must be valid assembly code (see Assembly Language Syntax.)

Within the code editor, lowercase alpha mode is enabled (press [ALPHA] twice to type lowercase letters.) In addition, a number of keys have special functions within the code editor:

[ALPHA] [.] (normally :) Types either a colon (:) or a semicolon (;) depending on context.
[ALPHA] [(–)] (normally ?) Types an underscore (_).
[ENTER] Inserts a new line after this line.
[2nd] [DEL] Inserts a new line before this line.
[CLEAR] Deletes all text on this line after the cursor. If the cursor is already at the end of the line, deletes all text before the cursor. If the line is already empty, deletes it and moves to the next line. The deleted text is saved to the clipboard.
[2nd] [STO ▸] Inserts text from the clipboard (i.e., whatever was most recently deleted using [CLEAR].)
[2nd] [ENTER] Undoes changes to the current line, restoring its previous contents.
[MATH] Displays a menu containing the mathematical operators that can be used in expressions.
[PRGM] Displays a menu containing all of the supported Z80 instructions.
[X,T,θ,n] Displays a menu containing useful special characters.
[Y=] (“Lbl”) Displays the Lbl menu.
[WINDOW] (“Sys”) Displays the Sys menu.
[ZOOM] (“Char”) Displays a menu containing all of the characters in the calculator’s font (including all of the characters found in the [MATH] and [X,T,θ,n] menus, and then some.)
[GRAPH] (“Done”) Exits the code editor and returns to the program section editor.
[2nd] [MATH] Shortcut for the Test/Logic menu.
[APPS] Shortcut for the System Routines menu.
[VARS] Shortcut for the System Addresses menu.

Instruction shortcut keys

In addition, there are shortcut keys for the most commonly used Z80 instruction mnemonics. The following can be used only when the cursor is on an empty line (otherwise, the keys perform their usual functions):

[+] ADD
[×] AND
[APPS] BCALL
[TAN] BIT
[(] CALL
[(–)] CP
[x-1] DEC
[x2] INC
[,] JQ
[STO ▸] LD
[/] OR
[LOG] POP
[LN] PUSH
[COS] RES
[)] RET
[SIN] SET
[] SUB
[^] XOR

Lbl menu

(Screenshot)

The Lbl menu displays all of the labels that have been used or defined within the current program. As in the system CATALOG menu, pressing a letter key will jump to the appopriate location in the list.

To open the Lbl menu, press [Y=]. If you have already typed the first few characters of a label, the menu will show labels beginning with those characters.

Sys menu

(Screenshot)

Mimas includes a large collection of built-in constants that are useful in writing TI-83 Plus programs. The Sys menu displays these constants, and is divided into four sub-menus:

System Routines
System routines are useful functions provided by the calculator OS for assembly programs to use. These are used with the BCALL and BJUMP instructions and cannot be used in ordinary expressions (e.g., PutS is just a normal symbol in all other contexts.) (If you really want to refer to the B_CALL table address, write _PutS instead.)
System Addresses
System addresses include areas of RAM that are set aside by the OS for various purposes (such as OP1, curRow, and saveSScreen.) Many of these RAM areas are used for inputs and outputs to various system routines; a few are more or less free for assembly programs to store variables in.
This menu also includes the handful of system routines that can be called using the CALL and RST instructions: rMOV9TOOP1, rOP1TOOP2, rPUSHREALO1, rFINDSYM, rFPADD, LCD_BUSY_QUICK, APP_PUSH_ERRORH, and APP_POP_ERRORH.
Constants
This menu includes key codes (used by the GetCSC and GetKey routines), variable data types (used in the calculator Symbol Table and by the FindSym and ChkFindSym routines), and system flag offsets.
Flags
This menu contains the names of system flags (single-bit variables used to store a wide variety of system settings, accessed using the IY register.) Note that when using the SET, RES, and BIT instructions, you can omit the IY offset: SET textInverse will be automatically expanded to SET textInverse, (IY + textFlags).

(For more information about TI-83 Plus system routines, RAM areas, constants, and flags, see the official documentation from the TI-83 Plus SDK, as well as the third-party documentation provided by WikiTI.)

To open the Sys menu, press [WINDOW]. As with the Lbl menu, if you have already typed the first few characters of a built-in symbol, the menu will show possible completions (within the category you select.)

Using Libraries

(Screenshot)

When creating a large program, you may find it helpful to break it up into several smaller source files. (If you are creating a very large program, breaking it up may be necessary, since the entire source code won’t fit in RAM all at once.) You may also find it useful to place commonly-used subroutines in separate files, so that they can be used by multiple programs.

Each program source file contains a list of other source files that it uses as libraries. When you compile your program, all of its libraries, and all of its libraries’ libraries, and so forth, will also be compiled into the output file. (If a particular file is listed more than once, only one copy of it will be included in the final program.)

To edit the list of libraries, go to the program section editor, press [GRAPH] (“Menu”), and select “1: Libraries”. Initially the list will be empty. Press [Y=] (“Add”) to add a file to the list; press [WINDOW] (“Del”) to remove the selected file from the list.

Archiving Programs

Mimas program files may be stored either in RAM or archive (Flash) memory, but they must be stored in RAM while you are editing them. (If you try to modify a program that is archived, Mimas will try to unarchive it; if you don’t have enough free RAM, an error message will be displayed and you will not be able to change the program.) It is generally a good idea to keep your programs archived whenever possible, to protect them from being lost or corrupted when the calculator crashes.

Also keep in mind that compiling a program requires a fair amount of free RAM; if you are editing a large program, you may need to archive it before compiling.

To archive a program, go to the program section editor, press [GRAPH] (“Menu”), and select “3: Archive Program”.

Compiling Programs

(Screenshot)

To compile your program into executable Z80 machine code, go to the program section editor, press [GRAPH] (“Menu”), and select “2: Compile Program”.

By default, the name of the output file is the same as the main source file; you can change this if you want.

By default, Mimas will report an error if code is stored above address BFFFh. (Although shells such as Ion and MirageOS allow you to run programs larger than that, the calculator will crash if you try to execute any code stored in the upper 16k of RAM.) You can set “Allow PC > BFFF” to “Yes” to disable this behavior, if you really know what you’re doing.

Errors

(Screenshot)

Any of the following errors may occur while compiling. When an error occurs, Mimas will, whenever possible, jump directly to the location of the error.

Argument 1234h out of range
An argument value is not in the range permitted for the instruction. Values used in 8-bit LD and arithmetic instructions must be in the range –128 to 255. Values used as offsets to IX and IY must be in the range –128 to 127. Addresses used as the destination of a JR instruction must be between –126 and 129 bytes away from the current PC (you can, if you prefer, use JQ instead, which will switch to using a JP instruction if the destination is too far away.)
Assertion failed
An ASSERT condition is not true.
Code too large
Executable Z80 instructions are placed at an address greater than BFFFh. To avoid this, try to store non-executable data in “data” rather than “code” sections. If this is not sufficient (i.e., your program contains more than 8811 bytes of code), you’ll need to find some other way of getting around the hardware limitations, such as by copying chunks of code into ramCode before executing them. (In this case, use RORG to adjust code labels appropriately, and to notify the assembler that the code is meant to be copied elsewhere rather than being executed in place.)
Divide by 0
An expression attempts to divide by zero.
File NAME does not exist
File NAME is not valid
The program you are trying to compile, or one of its libraries, lists as a library a file that doesn’t exist or is not a valid Mimas program file.
Maximum number of passes exceeded
The program could not be compiled within the maximum allowed number of passes (currently 16.) This usually means that there are too many “forward” references in EQU and/or IF directives. To avoid this, use backward references whenever possible (e.g., if label2 is defined in terms of label1, place the definition of label1 first.)
Missing ENDIF
A preceding IF (or IFDEF or IFNDEF) directive does not have a corresponding ENDIF.
Out of memory
You do not have enough free RAM to compile the program. There are, of course, many reasons why this might occur. Try archiving the program and libraries (as well as any other large files that you have in RAM) before compiling.
Program empty
The program contains no code.
Symbol redefined
A label or EQU directive is attempting to assign a value to a symbol that is already defined. (Global symbols may only be defined once in the entire program, including libraries; local symbols may only be defined once in each file.)
Symbol undefined
A symbol is used in an expression, but has never been assigned a value. (Symbols are allowed to be undefined only during the first assembly pass.)
Too many conditionals
A series of IF (or IFDEF or IFNDEF) directives is nested too deeply (the limit is currently 255.)
Unmatched ELSE
Unmatched ENDIF
An ELSE or ENDIF directive does not have a corresponding IF.

Assembly Language Syntax

Due to the small screen size, the syntax of Mimas is somewhat restricted compared to that of other assemblers: each line may contain either a label, a comment, an instruction, or a directive, but not more than one at once.

All instructions, directives, register names, and operators are case-insensitive (e.g., ld a,42 is the same as LD A,42.) Case is significant only in comments and user-defined symbols.

Expressions

All argument expressions are evaluated as 16-bit integer values. (This may, unfortunately, cause some confusion if you are trying to port code that has been written on a PC; for instance, 8000h is considered a negative number, equivalent to –32768.)

Expressions may contain any of the following:

Numeric constants
A number without any special prefix or suffix (123) is a decimal constant. Adding a % before the number, or a b after it, marks the number as binary (base 2): %01111011 or 01111011b is the same as 123 decimal. Likewise, an @ prefix, or an o suffix, marks the number as octal (base 8), and a $ prefix, or an h suffix, marks the number as hexadecimal (base 16). (Note that if you use the h notation, the number must begin with a digit 0–9; A0h would be interpreted as a symbol, so you must write 0A0h instead.)
Character constants
A single character enclosed in single or double quotes ('A', "A") represents the (TI-variant) ASCII value of the character.
Symbols
A symbol is a string consisting of letters (A–Z, a–z, and θ), digits (0–9), and/or underscores (_), beginning with either a letter, an underscore, or a period (.). A symbol can be defined either by using it as a label (in which case the value of the symbol is the address of that label) or using the EQU directive. Note that normal (user-defined) symbols are case-sensitive: my_loop is not the same as MY_LOOP.
Built-in constants
Mimas also includes a large collection of built-in constants (as seen in the Sys menu.) Note that unlike user-defined symbols, built-in constants are case-insensitive (appbackupscreen is the same as APPBACKUPSCREEN.)
Anonymous labels
The special symbol θB (theta-B) refers to the address of the previous anonymous label. The symbol θF (theta-F) refers to the next anonymous label.
Program counter
The special symbol PC or $ refers to the current value of the program counter (as defined by the ORG or RORG directive.)
Program load address
The special symbol LPC or $$ refers to the current address within the program (as defined by the ORG directive, and ignoring the effect of RORG, if any.)
Unary operators
The following unary operators can be used:
lsb(x) Least significant byte of x; i.e., (x & $FF)
msb(x) Most significant byte of x; i.e., (x >> 8)
x (minus) Negative x
~x Bitwise complement of x; i.e., (x ^ $FFFF)
!x Logical negation of x; i.e., 1 if x = 0, or 0 otherwise, as with the TI-BASIC not( function
Binary operators
The following binary operators can be used. Standard precedence rules as used, as in C and most assemblers (but not TASM or SPASM, which treat all operators as having equal precedence.) Mimas will automatically add parentheses in cases that are potentially confusing.
x × y Multiplication (highest precedence)
x / y Signed division (rounds down)
x % y Signed remainder
x + y Addition
x – y Subtraction
x << y Logical left shift
x >> y Logical right shift
x < y x is less than y (signed)
x > y x is greater than y
x ≤ y x is less than or equal to y
x ≥ y x is greater than or equal to y
x = y x equals y
x ≠ y x does not equal y
x & y Bitwise AND of x and y
x ^ y Bitwise XOR of x and y
x | y Bitwise OR of x and y (lowest precedence)
Parentheses or brackets
Either parentheses ((, )) or square brackets ([, ]) can be used to group sub-expressions; the two are equivalent. Note that parentheses or brackets around an entire expression indicate indirection (LD A,123 stores the value 123 in register A, while LD A,(123) reads a value from memory address 123.)

Labels

A label defines a name for a particular location in the program. A label consists of a valid symbol followed by a colon (:). (Unlike many other assemblers, the colon is not optional.) The symbol must begin with a letter (A–Z, a–z, and θ), an underscore (_), or a period (.), followed by a string of letters, digits, and/or underscores.

A label that begins with a period (.) is considered “local” to the source file where it is defined (i.e., other source files cannot refer to that label, but may contain their own labels with the same name.) Local labels can be useful in large programs and libraries, since they let you use short, descriptive names without worrying about conflicts between files. Local labels can also make compilation slightly faster.

A label consisting of the single letter θ (theta) is an “anonymous” label. (These are similar to $$ labels in ZMASM, or {@} labels in Brass.) Any number of anonymous labels can be defined within the program. The symbol θB can then be used in any expression to refer to the last anonymous label before that expression; the symbol θF refers to the next anonymous label after that expression.

Labels are stored in a slightly compressed form; using lowercase letters in your labels will result in a smaller source file.

All labels are limited to a maximum length of 32 characters.

Comments

A line beginning with a semicolon (;) is considered a comment. Comments are ignored by the assembler; they’re just there for the programmer’s benefit.

Comments, like labels, are compressed, and as a result, not all characters can be used in a comment. Letters, numbers, and most ASCII punctuation characters are allowed; other characters will be replaced with ‘#’.

Z80 instructions

Mimas supports all of the Z80 instructions, both documented and undocumented. For details of the documented instructions, see the official Z80 documentation.

For convenience, when setting, resetting, or testing a system flag, you can simply type the name of the flag (or select it from the System Flags menu), omitting the IY offset. For instance, SET textInverse will be automatically replaced with SET textInverse, (IY + textFlags).

The undocumented instructions are described below. Note, however, that undocumented instructions will not work on the TI-Nspire, so you should avoid using them in programs that are intended to be portable.

IX/IY Half Registers
The upper and lower halves of the IX and IY registers can be manipulated independently, just as H and L can; these “half registers” are referred to as IXH, IXL, IYH, and IYL. Half registers can be used in all of the basic 8-bit operations (ADD, SUB, ADC, SBC, AND, OR, XOR, CP, INC, DEC), can have constant values loaded into them, and can be loaded to and from the A, B, C, D, and E registers.
Shift Left Inverted
SLIA is similar to the documented SLA, except that the low bit of the result is set to 1 instead of 0. (SLIA arg has the same effect as SCF followed by RL arg.) SLIA can be used with any of the same arguments that can be used with SLA.
Shift/Rotate/Set/Reset Bit with Copy
The instructions SLA, SRA, SLIA, SRL, RL, RLC, RR, and RRC can be used with two arguments, where the first is one of the registers B, C, D, E, H, L, and A, and the second is an indexed address (either (IX+n) or (IY+n).) The instructions SET and RES can be used with three arguments, where the first is a bit number, the second is a register, and the third is an indexed address. This means that a value is read from that indexed address, the appropriate operation is performed on that value, and the result is both written back to memory and also copied into the given register. For instance, SLA H,(IX+2) has the same effect as LD H,(IX+2) / SLA H / LD (IX+2),H. SET 3,H,(IX+2) has the same effect as LD H,(IX+2) / SET 3,H / LD (IX+2),H.
Test-Only Input
IN (C) reads a byte from I/O port C, without storing it anywhere, but sets or clears the sign, zero, and parity flags according to the input value, just as the documented IN r,(C) instructions do. (IN (C) has essentially the same effect as PUSH BC / IN B,(C) / POP BC.)
Zero Output
OUT (C),0 writes a zero byte to I/O port C. (OUT (C),0 has essentially the same effect as PUSH BC / LD B,0 / OUT (C),B / POP BC.)

Special instructions

Mimas also supports the following special instructions. These, of course, are really just Z80 instructions with a more convenient syntax.

BCALL addr
Calls a system routine. The argument may be either a system routine name (BCALL GrBufCpy) or an expression giving an exact address (BCALL 486Ah).
BJUMP addr
Jumps to a system routine.
JQ addr
JQ C, addr
JQ NC, addr
JQ Z, addr
JQ NZ, addr
Jumps to the given address; in the two-argument forms, jumps only if the condition is true. The assembler will use either a JP or a JR instruction, depending on how far away the given address is.

Directives

Assembly directives are commands to the assembler, which will be performed at the time the program is compiled (as opposed to instructions, which become part of the compiled program.) Mimas supports the following assembly directives:

ALIGN expr
Skips forward (leaving empty space in the output file) until the program counter is an exact multiple of the argument value. For instance, ALIGN 8 would move the program counter forward to the next address equal to zero mod 8.
ASSERT expr
Halts compilation and displays an error message if the argument value is zero (false). For instance, ASSERT (abc ≤ def) would display an error message if abc were greater than def.
DB expr,expr,...
Evaluates the given expressions and stores them as literal bytes in the output file.
DB "string"
DB "string",0
Stores the given string as a series of literal bytes in the output file. Note that strings cannot be mixed with literal byte expressions within a single DB statement. A single zero, however, may be added to the end of the string, as a terminator.
DS expr
Skips forward by the given number of bytes (leaving empty space in the output file.)
DW expr,expr,...
Evaluates the given expressions and stores them as literal 16-bit, little-endian words in the output file.
name EQU expr
name = expr
Evaluates the given expression and assigns its value to the given symbol. Note that once a symbol has been defined (either as a label or using EQU) it is fixed; it cannot be redefined later in the program.
IF expr
...
ELSE
...
ENDIF
IFDEF name
...
ELSE
...
ENDIF
IFNDEF name
...
ELSE
...
ENDIF
Conditional statements allow parts of the program to be assembled only if some condition is satisfied. IF evaluates the given expression; lines following the IF, up to the next ELSE or ENDIF, are assembled only if that expression’s value is not zero.
The argument to IFDEF or IFNDEF must be a symbol. Lines following IFDEF are assembled only if that symbol has been defined prior to the IFDEF. Lines following IFNDEF are assembled only if that symbol has not yet been defined.
The ELSE statement is optional; lines following the ELSE, if any, are assembled if the IF/IFDEF/IFNDEF condition is not satisfied.
INCBIN "ABCD"
INCBIN "prgmABCD"
INCBIN "Pic0"
Copies binary data from the given input file (either an AppVar, program, or picture file stored on the calculator) into the output program. You can use this if you have binary data (such as images, text, or compressed data) that you have generated using another program. (Note, however, that AppVar files usually contain a binary header of some kind, and INCBIN will include that header as well.)
ORG expr
Evaluates the given expression; the program counter is set to that value, and subsequent instructions will be stored starting at that address in the output file. (Sets both PC and LPC. Note that this is the behavior of ORG in most assemblers, but not SPASM. SPASM’s .ORG behaves as RORG, described below.)
All programs should begin with an ORG directive giving the address where the program will be loaded (normally userMem – 2.)
RORG expr
Evaluates the given expression, and sets the program counter without moving to a different location in the output file. That is to say, instructions following RORG will be stored in the output file as usual, but will be assembled as if they were located at the given address. Labels following RORG will also be adjusted accordingly. (Sets PC without affecting LPC.)
This is used when you have a block of code that will be copied to a different address before running it. For instance, if you have a routine that you want to copy to the appBackUpScreen area before running it, you could use RORG appBackUpScreen at the beginning of the routine. (This won’t actually copy your code into appBackUpScreen, of course; you have to do that yourself.) At the end of the routine, use RORG LPC to return to normal.
(Note that this is how the .ORG directive behaves in SPASM, although SPASM does not have an equivalent to LPC.)

About This Manual

Copyright © 2010 Benjamin Moody

Permission is granted to copy and distribute this manual, with or without modification, under any terms, provided that the above copyright notice and this permission notice are included in all copies.