Created: 6th December 1999
Last Modified: 15th December 1999
This page will cover some of the more common optimisation tricks that are used. These are mostly just short, one or two instruction routines. It will also explain shell titles, code size and t-states.
Optimisation is making programs run faster and/or use less memory. One common side effect of optimisation is loss of code legibility, so comment your programs, even if you won't be releasing the source! I say this now because as soon as you start serious optimising you'll be tearing your hair out trying to figure out exactly what your own code does.
There are a number of reasons to optimise code. Firstly there is the code size issue.
Programs that take less memory leave room for more games, sorry, sensible work programs
(smirk), on your calculator. Secondly there is the code speed issue. A few years ago
everyone was using ASCR to draw sprites. About a year ago ZMR was released and the
standard of games increased dramatically, just because the routine was twice as fast.
Although you probably won't be writing routines that are that widely used, the standard
of your programs will be much higher if you spend time optimising your code. Of course,
the real issue is when people start reading your code (using an emulator if you don't
release the source) and they notice cp 0 in your code they'll not take you
seriously.
The two most common terms used in optimisation are bytes and t-states. Bytes are just how much space in memory an instruction takes. T-states are how long it takes the processor to run the given code (most people call these 'clock cycles', which, strictly speaking, aren't quite the same thing). As the CPU runs at approximately 6MHz (6000000Hz) it takes on average (number of t-states / 6000000) seconds to run a piece of code.
Optimisation can be a very time consuming process. You can sit for hours counting bytes and t-states of dozens of variations of the same piece of code (Assembly Studio contains a utility to do this for you) and end up with a millisecond faster routine that uses one byte less memory. Sometimes this is necessary. Mostly it is a waste of time. Some people take it to the other extreme. Anyone who's played Dying Eyes for the ti85 (can also be run on the ti86 if you know what you're doing) will know that it takes up most of your memory (~20Kb) and is very slow (it's still a good game though).
There are some tricks you can use to produce faster code with very little effort. The most common of these are listed below.
The chances are, if you've wanted to decrement a register and jump somewhere if it is zero (or not zero) you'll do this:
dec e ld a,e cp 0 jp z,SomeWhere
However, you only need to do this:
dec e jp z,SomeWhere
People often forget (or don't know) that almost every instruction sets the flags (the
most common ones that don't are the push and pop instructions)
depending on the result. You rarely have to include the cp instruction at
all.
If you want to compare the accumulator (the a register) to zero and can't
use the above technique you can still probably avoid using cp 0 - a much
faster alternative that is also a byte smaller is or a. This works
because (a or a) always equals a, and this instruction
also sets the flags.
Finally, djnz is not restricted to loops.
Always remember the two types of jump - relative (jr) and absolute
(jp). Absolute jumps take a byte more, but are slightly faster. It's up to
you which you use, but I'd stick with relative jumps where possible as the few t-states
difference mean little.
If you're going to jump to the same memory location from lots of different bits of code
there's a jp hl (Assembly Studio, TASM and certain versions of the
z80 technical data use jp (hl), but it does the same thing)
instruction which takes up less memory and is faster. If you need hl you could
use jp ix (or jp (ix)) or jp iy
(or jp (iy)) instead.
If you're going to call something and then ret immediately
afterwards you might as well just jp to whatever you want to call.
Don't use ld a,0. Use xor a.
Use call _clrScrn at the end of your program as it does more than clear
the screen - it also clears the text shadow (an area of memory that contains whatever's
on the home screen). If you want to clear the screen frequently during the middle of your
program you could call the following instead:
ClearScreenFast:
ld hl,$fc00
ld (hl),l
ld de,$fc01
ld bc,1023
ldir
ret
Consider the shift and rotate instructions (see the instruction reference) for multiplying
and dividing by two. Also, to divide a by 16, for example, you could
sla four times or you could rlca four times and then
and %00001111.
It is faster and takes one byte less memory to load a register with the value of another register than to load a register with a number.
If you've used a shell you've probably seen that some programs have 'titles'. If not, look at the screenshots below (they're in blue rather than green because I've got my emulator set that way - I can see greyscale better like that).
![]() |
![]() |
| ASE titles | Rascal titles |
![]() |
![]() |
| YAS titles | Tinux titles |
These shells share a common method for finding a program's title. They all compare the first few bytes of the program file for a certain pattern. If this pattern exists they carry on reading to get the program's title. A very simple program with a shell title is given below. Note that 179 is the ti86 character code for lowercase c cedilla (ç).
#include "ti86asm.inc" .org _asm_exec_ram ;Shell Title nop jp ProgStart .dw 0, ShellTitle ProgStart: call _clrScrn ;clear screen call _homeup ;cursor to top left ld hl,ShellTitle ;display program name call _puts call _newline ld hl,MoreText ;display more stuff call _puts call _newline call _pause ;wait for [ENTER] call _clrScrn ;clear screen and exit jp _homeup ShellTitle: .db "Tux Le Pinguoin!",0 MoreText: .db "C'est beau, ", 179, "a!",0 .end
![]() |
![]() |
| Shell Title in Tinux | Program Being Run |