Want to make your own shell? Then keep reading!

Before you learn to search the Variable Allocation Table (VAT or Symbol Lookup Table) we need to investigate where it is and how it's organized.

The VAT

The VAT is on RAM page 7. You can swap it in yourself or you can use one of TI-OS' calls to do the work for you saving one byte.
_RAM_Page_7	=$47f3
	call _RAM_Page_7	;swap in ram page 7
				;destroys none

Backwards, that's how it's stored. If you had a variable named 'Stupid', it would be stored as 'diputS' in memory.

Since the VAT is backwards and on RAM page 7, it starts at address $bfff. To swap in RAM page 7 and go to the start of the VAT...

_RAM_Page_7	=$47f3
start_of_vat		=$bfff
	call _RAM_Page_7	;swap in ram page 7
	ld hl,start_of_vat	;hl=beginning of first
				; variable name in
				; vat

There's a good reason behind making it backwards. Think of the variables' memory in the RAM as being one long block. We could store all the names in one area, and all the data in another but we might be wasting space or corrupting memory if the data runs over the name area. By having both areas (name and data) start at opposite ends and work towards the center, you will maximize the allotted memory so that each area only takes up as much space as needed. When you run out of memory for storing names, that means you're out of space to store the data. Want a visual example?

Data →

← semaN*

* That's 'Names' spelled backwards since the variable names are backwards in memory.

It's not just the names that are stored backwards, it's the entire variable entry (all the info associated with that variable). Let's say you were to swap in RAM page 7, at $bfff would be the first byte of the first entry in the VAT. Here's an example of what the first variable on page 7 would look like on a freshly reset calculator using my MemSee.asm program.

Address	Byte	ASCII
$bff5	74	t
$bff6	61	a
$bff7	74	t
$bff8	53	S
$bff9	78	x
$bffa	05	
$bffb	00	
$bffc	01	
$bffd	40	@
$bffe	00	
$bfff	04	
The variable data comes five different parts in the following order but backwards in memory.

Description Size (bytes)
Variable type 1
Absolute Address for start of variable data 3
Trash byte you can use to store anything you want. It's not used by TI-OS. 1
Length of variable name 1
Name of variable 1-8

After that all, the next variable follows in that same order. Download MemSee.asm to see this first hand if you're still unsure.

Searching the VAT

If you already know the variable's exact name, you ca use _FindSym, but that's not always the case.

There's several different ways to go about sifting through the VAT. One way, and probably the most used, is by searching for a certain variable type, most often a string ($0c) or program ($12). Another way is to search alphabetically. We're going to focus on searching by the variable type, and our examples will search for programs to execute.

Let's begin this section by explaining my simple routine to search the VAT: VATSrch.inc. It's a beginner's example of how to search the VAT. The best way to understand this routine is to get the code printout with line markings from the VAT Search Routine Printout page; then, follow along with the explanations on this page.

  1. _RAM_Page_7 =$47f3
  2. _PTEMP_END =$d29a
  3. vatsrch:
  4. call _RAM_Page_7
  5. ld bc,(_PTEMP_END+1)
  6. push hl
  7. or a
  8. sbc hl,bc
  9. pop bc
  10. ret c
  11. push bc
  12. ld b,h
  13. ld c,l
  14. pop hl
  15. cpdr
  16. ld d,a
  17. ld a,b
  18. or c
  19. ld a,d
  20. jr nz,good_found_one
  21. scf
  22. ret
  23. good_found_one:
  24. dec hl
  25. dec hl
  26. dec hl
  27. dec hl
  28. ret

Line(s) Explanation Bytes
1 This call swaps in RAM page 7 (the VAT) without destroying any registers. This three byte call is used instead of
	ld a,7
	out (5),a
none
2 _PTEMP_END is where the absolute address for the end of the VAT is. none
4 Swap in RAM page 7. 3
5 We just swapped in RAM page 7. _PTEMP_END is an absolute pointer with 3 bytes for addressing; but, if we have the correct memory page swapped in, we only need the last 2 bytes to make up a valid 16 bit pointer. We get that 16 bit address which tells us where the last byte of the VAT is. If we subtract the end from the start (Notice that we usually subtract the start from the end but the VAT is backwards.) resulting in the length of the VAT. 4
6 Hold everything! We need to check if there's VAT left to search. Since that will probably destroy hl, save it. 1
7-8 Sbc is the only 16 bit subtractor that we have. Clear the carry before you use it so you won't get your answer one off. The size of the VAT will be stored in hl (if everything went alright). 3
9 This might be a little tricky. We needed to push the address of where we are to start searching from so that it would not be effected in the subtraction. If the subtraction went wrong, we will be returning from the routine. We can't return, though, with something on the stack so we get it off, for a second, and then in line 11 we put it back. Note that we are saving it as bc because we want hl to still contain the size of the VAT. 1
10 The carry flag will be set if we don't have any VAT left to search, the subtraction was invalid. 1
11 Put back where we are to start from. This is setting us up for the cpdr on line 15. 1
12-13 Remember that the size of the VAT was stored in hl from our calculations on lines 7-8. Cpdr needs the size of bytes to search in bc. 2
14 Get back where we are to search from. Remember that we had temporarily saved it away in line 11 as bc so we could use hl in the subtraction on line 8. 1
15 Now we perform the actual search! Cpdr will search, starting at address hl for a byte with a value of a for bc amount of bytes or until it finds a match incrementing hl each iteration and decrementing bc at the same time.

The Parity Odd flag condition will occur if no match was found. We won't be using it, however. We'll check the value of bc on our own in the next few bytes.

2
16 We're about to check the value of bc now to see if there was a match found.

This routine will probably be called several times in a row. The user will not want to have to keep loading up a with the same Variable Type after each iteration. By our saving that value, we save the user this wasted effort at the cost of using d.

1
17-18 Now it's time to check the value of bc which, if it's zero, tells us to quit searching...there's nothing left.

We'll use or to see if any bits are set in either b or c.

2
19 We are still preserving the Variable Type byte in d. Let's put it back before we exit the routine. That way it's there if we exit or if we continue along. It was only needed for cpdr. Remember: ld does not affect the flags. Our or's results are not changed. 1
20 If bc wasn't zero after the or, then we continue right along with line 23. 2
21-22 Well, bc must have been zero. There's nothing left for us to search in the VAT. By setting the carry flag, we signal that there was an error of some sort.

Scf is a great way to set the carry flag. It can tell a user that an error just occured in that routine.

2
24-28 Recall that the VAT is backwards. We are currently at the Type byte of the variable, the first byte in the viariable's entry. Let's decrement the address past the type byte, past the three bytes for the Absolute Address pointer, and past the trash byte so we are now at the length index byte of the variable's name (all the user needs to reference the variable using _FindSym). 5

Check out VATSrch.inc's VATSrch and Copy_to_OP1 in action!

	ld a,$12		;$12 - program
				;$0c - string
	ld hl,$bfff		;absolute start of vat
				;the routine automatically
				; swaps in ram page 7 (the
				; vatiable allocation table)
				; so this is a valid address
	call vatsrch		;search starting at hl for
				; program
	ret c			;carry set tells us there was
				; an error or it reached the
				; end of the vat
	ld de,_OP1		;where we want to store
				; name at
	call copy_to_op1	;copy backwards vat name to
				; op1 the right way
	ex de,hl		;we need it in hl so we
				; can display it
	call _putps		;display length indexed string
				; at hl

Using _FindAlphaUp/Dn

VATSrch.inc is very fast; however, if speed isn't a necessity, you can use _FindAlphaUp=$514b and _FindAlphaDn=$514f.

_FindAlphaUp=$514b

WIDTH="15%">Description Finds the variable higher (closer to 'Z') alphabetically than the one stored in OP1 in Variable Name format.
Input OP1 - case sensitive variable name in Variable Name Format
a - if not equal to $00 then ignore type
zero flag set - search for same type variables (real or complex)
Destroys a, bc, de, and hl
Output Carry set - didn't find one
hl - address in VAT with RAM page swapped in
OP1 and OP3 - found variable in Variable Name format

_FindAlphaDn=$514f

WIDTH="15%">Description Finds the variable lower (closer to 'A') alphabetically than the one stored in OP1 in Variable Name format.
Input OP1 - case sensitive variable name in Variable Name Format
a - if not equal to $00 then ignore type
zero flag set - search for same type variables (real or complex)
Destroys a, bc, de, and hl
Output Carry set - didn't find one
hl - address in VAT with RAM page swapped in
OP1 and OP3 - found variable in Variable Name format

Speed is a huge drawback with these two; it's atleast 156,000 clock-cycles each time you call these which increases exponentially the deeper you are in the VAT. It's said to be the worst routine TI ever wrote; it's extremely slow! If you're only looking up one or two variables, OK. If you're making a shell that displays 30 variables, it could take upwards of 30 seconds!

	ld hl,beginning_var	;the variable name
				; to start searching up
				; from alphabetically
	rst 20h			;_mov10toOP1
	ld a,1			;ignore type
	call _FindAlphaUp	;find a variable higher
				; (closer to 'z') than the
				; one in OP1
				;hl=start of VAT entry
				;c - nothing found
				;nc - found one
				;OP1&3 - variable found
	ret c			;no such variable found
beginning_var:	.db $12,1,0	;0 is the single
				; character name
				;the lowest variable name
				; possible
				;$12=program type vari.

Shells

A Shell is a program on the calculator that will display programs in the VAT allowing you to browse through the names in order to execute them. There are endless variations to the basic shell, so your imagination is the limit!

For a basic rendition of a shell, check out the demo program Shell.asm. It gives you all the basics to make your own shell for running Asm programs. You can easily add support for running TI-BASIC programs, displaying pictures, editing equations, editing programs, renaming variables, folders, etc.!