Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

Beginning Assembly For The TI

Download as pdf or txt
Download as pdf or txt
You are on page 1of 219

I

'PP

1 -v.. ,

BEIN NI

fe

AS 'BEIViiiiLY LANGUAGE FOR THE


'

'

111
111111111111

BEGINNING ASSEMBLY LANGUAGE FOR THE

TI
ii

HOME COMPUTER

For corrHspondence regarding this book address the following:

D & D PUBLISHING Co. 3177 Bellevue Toledo, Ohio 43606

Copyright 1984 D & D Publishing Co. All rights reserved

No part of this boot . may be reproduced in any form or by any means, electronic or mechanical, including photocopying, without permission in writing from the publisher. Printed in the United States of America 1984

i.

INTRODUCTION
There is something really big underlying the BASIC language' Many gifted programmers have considered writing e:,citing games for the TI Home Computer only to be faced with the limitations of the cumbersome BASIC language. It does not take one long to realize that it is simply not possible to accomplish all that arcade style games entail using BASIC alone. BASIC is sometimes Just too slow. There is essentially nothing wrong with using BASIC if you re programming operations don't require a great deal of speed. But if you are writing programs which have a lot of things happening simultaneously, such as a number of obiects flying around the screen with the program trying to keep track of coincidence checks, BASIC Just can't do the ioh. BASIC by its very nature Lends to use up a lot of memory in a short period of time. For these reasons and the ones previously alluded to, you may want to consider adding program modules written in assembly language to your BASIC programs. Or even writing your complete program entirely in assemblv language. This boor is designed to help the beginner in introducing him or her to assembly language. The boor assumes that you have no previous egperience in programming other then BASIC. If you already r.now BASIC, that is fine. If you are already developing programs in assembly language, that is even better. This boor was designed as a study text. That is, it wa , ; meant to be read cover to cover, each chapter building on what was learned in the preceding chapters. If something is discussed that you do not quite understand after a thorough reading, go on as it will probably become clear in later sectaons. Take the time to complete the study questions at the end of each chapter. They will reinforce important concepts.
-1-

INTRODUCTION

This book begins with the fundamentals. Chapter 2 binary and hexadecimal numbering systems. It also important terms and concepts that will be carried boot, . Make sure you completely understand chapter proceeding.

covers the discusses throughout the 2 before

GICIFAMINIT9: IEJF

EaDICIIK

This bool contains 14 chapters. In chapter 2 you are introduced to the counting system that the computer uses to keep trac . [ of numbers. You are also introduced to the hexadecimal system which greatly simplifies programming. Chapter 3 discusses the assembler, memory utilization and the internal registers of your Home Computer. It also explains how assembly language programs are developed and written. Additionally, you are introduced to the source statement, which is a programing line in assembly language akin to a BASIC statement. Chapter 4 introduces the instruction set. The -first topic ta[c.n for discussion is Addressing Modes, or ways to inform the computer e-actly where data or information can be found in memory. Subsequent sections of this chapter introduce you to the Instruction Set with each Instruction discussed at length as tu its usage and purpose. Numerous e:\amples e used to dramatize important points. ln Chapter 5 you learn about Assembler Directives. These consist of instructions to the assembler program that can significantly reduce program development Lime on your part. Chapter 6 discusses Utility programs in-depth. These are already constructed assembly language programs that are available to you. Again, numerous examples are provided to illustrate important points. Chapters 7, 8 and 9 discuss screen Graphics, Sprites and Sound control. You learn how to control complex screen graphics as well as how to incorporate sound into your programs. Prior to chapter 10 this book discusses how to create assembly language programs using the Editor/Assembler package. Chapter lo is a complete description of how to create assembly language programs using the lane-by-line assembler and the Mini-Memory module. Explicit instructions are gaven e.:plaining the differences and how to create programs that will run with either system configuration. Chapter 11 outlines the conversion of many BASIC commands into their assembly language equivalents. This is done to illustrate

INTRODUCTION

general assembly language concepts. Chapter 12 outlines BASIC support routines that are available. It explains how to linF BASIC programs wit.h assembly language programs. It also outlines how parameters are passed between the two types of programs. Chapter presents a brief description of tho advanced mathematical routines that are available. Linking to console resident routines is also discussed. This book provides four appendices for your convenience. Appendix A contains tables that aids in interchangind decimal and hexadecimal numbers. Appendix B outlines the TMS990n instruction Set. Appendix C lists the Assembler Directive set. Appendi:. D is perhaps the most interesting, it provides some source code for frequently used assembly language game modules. You can operate joysticks, simulate gravity, scroll the screen, create delays ect...

DID IL Li CT.:

1, 1
11

CONTENTS
Chapter 1: Introduction Chapter 2: How A Computer Counts Chapter 3: The Assembler 1 5 15 25 65 77 97 115 127 139 149 169 183 195

Chapter 4: The Instruction Set Chapter 5: Assembler Directives Chapter 6: Utility Programs Chapter 7: Graphics Chapter 8: Those Spirited Sprites Chapter 9: Let There Be Sound

Chapter 10: The Line-by-Line Assembler Chapter 11: Converting BASIC to Assembly Language

I r I

Chapter 12: Linking With BASIC


i

Chapter 13: High Precision Mathematics Index

2 HOW COMPUTERS COUNT


The difficulties encountered in learning assembly language have often been greatly exaggerated. In fact, once the instructions and the rules that govern them are understood, programming in assembly language becomes almost as easy as programming in BASIC. All humans are born with ten fingers and toes and hence it was natural that our mathematics would develop along the base ten numbering system. However, there is no natural "law" that states this must be so. A computer is designed along a base 2 or binary numbering system. It is made up of only two digits, 0 and 1 (in contrast to the decimal system which is made up of the digits 0 through 9). When you are working with the binary numbering numbering system you are talking in the computers on language. The computer can act directly upon instructions rather then having to go through an interpreter first as is necessary with any higher level language like BASIC. There is one additional numbering system that you should become familiar with in this chapter. This is a base sixteen or hexadecimal numbering system or simple HEX. The HEX system is made up of the digits 0 through 9 and letters A through F. When programming in assembly language the computer assumes all numbers that you enter are decimal numbers unless you precede the number with a "greater than" symbol CO. The greater than symbol indicates to the computer that the number following it is in hexadecimal notation.

124

(Decimal)

>7C

(HEX)

This chapter is a basic introduction to computer numbering systems. It is aimed at those who have no or limited knowledge in this area. If you already understand these concepts and how they apply to assembly language programming, feel free jump ahead to the next chapter.

HOW A COMPUTER COUNTS


cD :E.1 I

"he

INI .1 hi E.c IE:1R.E3

The computer stores all the information contained within it in an area called the memory. Memory can be thought of as a large collection of electrical switches. Each switch can be either "on" or "off" and each can be set or reset by the computer as needed. Each individual switch can be thought of as the computers smallest single memory cell. This single memory cell is known as a BIT which is short for Binary DIgiT. A bit holds the smallest piece of information that the computer can handle. A bit is either on or off, true or false, plus or minus. It has no in-between states. The On and Off settings of the memory bits correspond to the two digits that make up the binary numbering system. The binary system consists of the two digits 0 and 1 and is the fundamental system the computer uses to keep track of numbers. The digits are represented by 0(Off) and 1(On). In your Home Computer groups of eight bits are lumped together to form a single byte. It might be easier if you think of a byte as a row eight lightbulbs mounted on a long board. Each lightbulb represents a single bit and can be either on or off. The entire board with its eight lightbulbs is taken as one byte. In the following sections we will see how the computer can use these bits and bytes to store information.

Looking at the above illustration of our byte we see that each of the lights (bits) are currently turned off. From this we can say that the byte is representing zero value. In computer language it is said to be "holding" a zero. Now consider that we want this byte to represent the number one instead of zero. As we watch the light (bit) on the far right comes on:

HOW A COMPUTER COUNTS

The column on the far right of our byte is the one's column and hence the byte on the preceding page would represent or "hold" a value of one. If we wanted our byte to hold a value of two instead we would turn on the next bit in the row like so:

And to represent the number three we simple add the values of the last two bits together like so:

By simply looking at a byte, checking to see which bits are turned on, and adding their values together the computer can tell the value of the number being held there. Each bit has its own special position on the byte. Starting on the right and proceeding to the left, each bit is worth twice what the one before it was. Another way to think about it is to consider each bit (from right to left) as an increasing power of two. Thus the rightmost bit is 2 to the power of 0 or 1, the next bit is 2 to the power of 1 or 2, then next 2 to the power of 2 or 4, and so on until the leftmost bit is reached which is 2 to the power 7 or 128. By adding combinations of bits that are turned on together the value of any number from 0 (all bits off) through 255 (all bits on) can be represented:

HOW A COMPUTER COUNTS

Lets review, eight bits together make up a single byte. A single byte can hold any value ranging from 0 to 255 decimal. The following examples are binary (byte) representations of some decimal numbers. Keep in mind that each 1 or 0 represents a bit that is either ON(1) or OFF(2). The bits are divided into two groups of four bits each to make them easier to read: BBNARY
-----------

DECIMAL

0010 0010 (32)+(2)=

34

0100 001 0

(64)+(2).=

66

Normally you would not have to add binary numbers together when programming, this function being performed by the computer. However, to provide a complete presentation we will briefly discuss the addition of binary numbers. When adding binary numbers together you follow essentially the same procedure as when adding two decimal numbers together. For example, when adding the values 6 and 8 together you must carry a 1 into the "tens" column in order to arrive at the correct result of "14". Similarly, when the two binary digits 1 and 1 are added together, a 1 must be carried into the two's column. Thus the addition of 0000 0001 with 0000 0000 becomes 0000 0001 and the addition of 0000 0001 with 0000 0001 becomes 0000 0010. The following illustrate some further examples of binary addition:

*
1 0101
+_0001 011.0

**
11
0111 + 0110 1101

**
11

*
1

*carried l's

0110 0110 + .,_(. .11_0911, ..21 1101 1001

The first problem involves a carry of one from the first column to the second (1+1). This carries over to the second column which contains only two 0's. Adding the carried 1 makes the result under this column a "1".

I 11441 la JD INI Li rai Et Fc


Up to this point we have been discussing how to represent positive numbers with the binary system (using bytes). To bits and bytes we must return to our row of eight bits that we discussed in previous sections. Remember that each bit represented

HOW A COMPUTER COUNTS

a certain value that was determined by its row position on the byte. To make them easier to refer to, bits are numbered 0 through 7 starting on the left and proceeding to the right (in contrast to their value which increases from right to left). The numbering of bits is illustrated below:

9 S

,C 7

Bits are also said to become more significant as they increase in value. That is, bit 7 is considered the least significant bit (LSB), and bit 0 is the most significant bit (MSB). Also, bit 0 is more significant than bit 1 and bit 1 is more significant than bit 2 and so on down the line. Significance than is tied to the relative value of a bit. As the relative value increases, so does the bits significance as illustrated below: \I! //

1:)

..".1*0"
When a byte holds a signed number, only the 7 least significant bits hold the value of the number (bits 1 thru 7). The most significant bit (bit 0) is reserved and is used to indicate the sign of the number being held. If this bit is set to "1" then it indicates that the number being held is a negative number. If this bit is reset to 0 then it indicates that the number being held is a positive number. As you may have already guessed, a byte that holds a signed number uses bit 0 to hold the sign. Therefore it can't hold as wide a range of values. Bytes holding positive numbers can only hold values ranging from 0 (binary 0000 0000) to 127 (binary 0111 1111) while bytes holding negative numbers can hold values ranging from -1 (binary 1111 1111) to -128 (binary 1000 0000). You may be wondering why -1 is represented in binary as 1111 1111 instead of 1000 0000. The reason for this is that negatively signed numbers are represented in what is known as their 2's compliment form. By using 2's compliment to represent negative numbers the dilemma of having zero be represented by all 0's (positive zero) and all O's with a 1 in the sign position (negative zero) are avoided.

10

HOW A COMPUTER COUNTS

To find the binary representation of a negative,number (that is, to find its two's compliment form) simply reverse each bit, that is change each 1 to 0 and each 0 t 1, then add 1 to the o result. The following example illustrates how to find the 2's compliment representation of -65: 0100 0001 1011 1110 1011 - iii1 +65 Reverse all bits. Add one. -65

The reverse procedure (reverse all bits and add 1) can also be used to find the positive form of a negative number.

wolIR-AD13
A bit is the smallest piece of information that the computer can hold. The computer lumps 8 of these bits together to form a single byte which it can use to store usable information. By now you should begin to see some limitations with this system. For example, using bytes alone you could only represent unsigned numbers whose values range from 0 to 255 or signed numbers whose values range from -128 to +127. To represent numbers larger than this we must devise some alternate scheme. The simplest approach would be to hook two bytes together in order to form a larger number of bits from which to draw information. Two bytes hooked together in this fashion are referred to as a single WORD. The left byte contains the first 8 bits that make up the left-half of the "word" while the right byte contains the second group of 8 bits that form the right-half of the "word". The bits are numbered consecutively left to right from bit 0, the left-most bit on the left byte, through bit 15 which is the rightmost bit of the right byte. The value of each bit is double as we move from right to left along the bits. For example:

lEc

-11-

INIUMEclaFc=
0 4 3 7

Q's dry

11

.r .r* .21 -2e

49

24

2 Xi

A4

Notice that by linking two bytes together in this manner to form a single word v%). can now represent a much greater range of

HOW A COMPUTER COUNTS

11

numbers. To sum up, in your Home Computer most chunks of information are processed in units referred to as words. Each word is made up of two bytes. Each byte is made up of eight bits. For words that contain signed numbers, bit 0 (the left-most bit of the left byte) is used to hold the sign of the number. Words can hold signed values that range from 0 (0000 0000 0000 0000) to 32,767 (0111 1111 1111 1111). Words holding negative numbers can hold values ranging from -1 (1111 1111 1111 1111) through -32,768 (1000 0000 0000 0000). Keep in mind that negative numbers are represented in their two's compliment form. The following is a graphic representation of -4356:

1.7" z...
-

ZS. 1 1 ET. X Pt I.) la


-1

I Irl A L._ IN 13 -T- Pr -11- I C3i IN1

When computers were in their infancy programmers had to enter each byte of binary code by hand. Not only was this a very tedious and time consuming process, but it was extremely prone to error as well. For example, a binary number like 0000 1110 could easily be transposed into the entirely new value 0000 1101. The HEX system (short for hexadecimal) was designed to speed up the process of writing in binary code. The following chart compares the Decimal, HEX, and Binary numbering systems:

DECIMAL o 1
CI -0, C,4t..)

HEy. >oo
>01 >02
>07:

BINARY
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001# 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111

7 8
9 10# 11 12 13 14 15

>04 >05 >06 >07 >08 >09 >OA >OB >OC >OD >OE >OF#

12

HOW A COMPUTER COUNTS

Note that (#) signifies that the digits begin to repeat on the preceding page (10's decimal, 16's HEX, 2's binary). If you study these systems you find that in decimal you begin 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, then start again in the 10's column: 10, 11, 12, 13, 14, ... and so on With HEX you count >0, >1, >2, >3, >4, >5, >6, >7, >8, >9, >A, >B, >C, >D, >E, >F, then start again in the 16's column: >10, >12, >13, >14, >15, ... >18, >19, >1A, >1B, >1C, ... and so on. In both decimal and hexadecimal numbering systems the individual digits have some "weight" which is a power of the base. In the HEX system the base is sixteen so each digit has a value 16 times the value of the digit to its immediate right (as opposed to the decimal system where each digit has a value 10 times the value of the digit to its immediate right). For example, the hexadecimal number >4CEF has a decimal value of 19,695 because:

(4x16 )+(Cx16 )+(Ex16 )+(Fx16 ) = 19,695 reduces to the decimal form: (4x4096)+(12x256)+(14x16)+(15) = 19,695 where C=12, E=14, and F=15 from the table on page 11. When writing in assembly language all HEX numbers are designated with a "greater than" sign (>) in front of them to differentiate them from decimal values. The following are some HEX equivalents of decimal values:

HEX
>0A >AA >B3F >FFFF >FE03 >0214

UNSIGNED NUMBERS DECIMAL


10 170 2,879 65,535 65,283 532

BINARY

0000 0000 0000 0000 0000 0000 1010 1010 0000 1011 0011 1111 1111 1111 1111 1111 1111 1110 0000 0011 0000 0010 0001 0100

>FC >E9 >08 >7FFF

SIGNED NUMBERS -4 1111 1111 1111 -23 1111 1111 1110 8 0000 0000 0000 32,767 0111 1111 1111

1100 1001 1000 1111

Learning to work with hexadecimal numbers is perhaps the biggest hurdle to get over when trying to master assembly language. You should not be disillusioned if everything is not

HOW A COMPUTER COUNTS

13

crystal clear up to now after all, this counting system is unnatural. You should spend some time now practicing the exercise at the end of this chapter. You should at least be fluent in converting hexadecimal numbers into their decimal equivalents and vice-versa before proceeding even if you don't quite understand what is going on yet. To sum up, in order to figure out the decimal value of a HEX number, simply multiply the second digit by 16, the third by 16 squared the fourth by 16 cubed and add all four values together. Thus >12A becomes (1x256)+(2x16)+(10x1)=298. HEX at first does seem impossibly confusing. Do not let this discourage you as the system will probably become second nature to you after you have worked with it for awhile. You can quickly look up HEX values that you need in a hurry in Appendix A at the end of this book. Remember, all HEX numbers are distinguished by placing a "greater than" sign (>) in front of them: >OA or >1222.

14

HOW A COMPUTER COUNTS

CHAPTER 2 STUDY EXERCISES


1. Convert the following decimal equivalents: (A) 15 (B) 24 (C) 30,121 values to their binary

(D) -10,250

7.

Convert the following unsigned binary values to decimal:


(A) 0100 (B) 0010 0100

1110 1101

(c)

1001

0000 0000 0000

.=.

Wrjte all four numbers in exercise 1 notation.

in hexadecimal

4.

List the decimal equivalent of >1C34 if (A) The value represents a signed number. (B) The value represents a unsigned number.

3 THE
In the last chapter we learned that the computer speaks in a binary code. We also learned that binary code is the most efficient and fastest executing language. In addition, we learned an alternate method of designating numbers; that being the hexadecimal system. Early on programmers found it difficult to program instructions into the computer using binary codes. For instance, to enter the instruction that would add two numbers together required having to type in the binary code 1010 0000 0000 0000, or the HEX equivalent, >A000. Likewise, to enter the subtraction instruction required having to enter the binary code 0110 0000 0000 0000, or the HEX equivalent, >6000. As can be easily seen, this is not only a time consuming process, but is extremely prone to error as well. Eventually someone got the idea to replace the binary commands with english abbreviations that programmers could easily remember. In this way an addition instruction could be typed in as "A" instead of 1010 0000 0000 0000, and a subtraction instruction could be written as "S" instead of 0110 0000 0000 0000. A separate program referred to as the "assembler" is then used to convert these abbreviations into their binary equivalents. When a program is first written in this "assembly language" it cannot be run on the computer yet since the computer does not understand the abbreviations. Before a program can be run it must be assembled by the assembler program. There are thus two versions of an assembly language program. The first version written by you using the abbreviations is termed the source program (or source code) while the second binary version created by the assembler program is termed the object program (or object code). In summary, the purpose of the assemble program is to convert the source code which you have written into object code which the computer can understand.

-15-

16

THE ASSEMBLER

:T.-

C7 -01I

Before we advance too far into assemble language programming proper, it would be useful for us to discuss how the computer keeps track of instructions and how it follows through with them in a neat, orderly manner. The electronic brain of your computer is the TMS 9900 processor. It has the capability to perform a wide variety of tasks quickly and efficiently. If we couid look down into the computer we would be able to see distinct areas that serve specific functions. One area is called RAM which stands for Random Access Memory. RAM contains a large number of free bytes. You can, as the name implies, randomly access any of the bytes located here. This is the area where your program instructions are stored when you type them into the computer. Thus, RAM can be though of as a blank slate waiting for you to type in information. Another area is referred to as ROM which stands for Read Only This is an area where the computer permanently stores a set of instructions that it can refer to when needed. For instance, when you type in a BASIC command, ROM is where the instructjons that translate the BASIC command into binary code reside.

Memory.

The third major area of the computer is termed the CPU or It is the heart and soul of the computer. The CPU continuously takes in numbers from memory locations all over the computer. These numbers can then be sent out unchanged to other locations, or they can be compared, added to, or otherwise modified before being sent back to RAM or ROM. The CPU can perform all these tasks with the help of some special "tools". These tools are referred to as Registers. A Register can be thought of as a memory word that is reserved for a specific purpose (remember, a word is made up of 2 bytes hooked together). Registers located in RAM that you can alter during programming are referred to as Software Registers. Registers located in ROM that can be used only by the CPU are termed Hardware Registers. A set of sixteen consecutive Registers is referred to as a Workspace.

Central Processing Unit.

It may be helpful to think of a Register as an area of memory where you can store information that you want the CPU to perform some operation on For example, suppose you wanted to add two numbers together. You would first place the values to be added in two Registers and then instruct the computer to add them together and place the sum into a third Register. Registers can be located anywhere in RAM as long as you tell the computer where they are. In later chapters we will discuss how this is done. In your Home Computer you have a total of sixteen Software
Registers (termed a workspace) available to you. Each Register is

THE ASSEMBLER

17

one word (2 bytes) in size. These sixteen Registers are numbered RO through R15. These sixteen Registers are collectively referred to as your Workspace Registers. In addition to the Software Registers available to you there are three Hardware Registers that are used by the CPU to keep track of things. These are as follows:

1. 2. 3.

PROGRAM COUNTER REGISTER WORKSPACE POINTER REGISTER STATUS REGISTER

The following sections describe the three Hardware Registers in great detail.

F"F:01D. R.' eAl M IC 01 L.JI INII -1- IU IR: F: U.

IBIe -riE:F:

(P-G)

The Program Counter Register (PC) keeps track of the location of the next instruction to be executed by the CPU when it is running a program. In this way a sequential and orderly flow of instructions is maintained.

WOIIRCK.SF- IAIDIa IFJ'01I1 8,4 -1-- laIR:

1F.ZIE: I S -Fla.F.: .

<WIF")

The Workspace Pointer Register (WP) keeps track of the location in memory of the current Software Workspace. This is the pointer that informs the computer where your Software Workspace area begins in RAM. Each byte in RAM is numbered so that the computer can find it. This number is referred to as the Address of the byte. This is similar to how the location of each house in a large city is designated by its street address. With this in mind it can be stated that the Workspace Pointer Register holds the beginning address of the current Software Workspace.

The Status Register is important in that it reports to the CPU about the current Status of things. For example, when the computer compares two numbers together it is useful to record the result of this comparison somewhere in memory. That is the purpose of the Status Register; it "holds" the information long enough for the CPU to make a decision based on it. Remembering that a Register is made up of sixteen bits, the Status Register reports various status conditions in the first six of its bits (0-5). The four least significant bits (12-15) hold information important towards interrupting the computer; but we will have more on interrupts

18

THE ASSEMBLER

later. Bits 7 through 11 are not used by the Status Register. Each bit in the Status Register can that signals some piece of information bit is set to 1, it signals to the CPU or ignore it depending on your program be thought of as a flag to the CPU. Every time a which may act on the flag, instructions.

The following figure demonstrates how the "flags" are arranged in the Status register:

L> A> EQ C OF OP X NOT----USED INTERRUPT MASK 0 1 ..) 3 4 ,, 2 6 7 8 9 10 11 12 13 14 15 E4 I ---ir INILJWIEKEEFR


L> -- LOGICAL GREATER THAN BIT A> -- ARITHMETIC GREATER THAN EQUAL BIT EQ X -- EXTENDED OPERATION C -- CARRY BIT OF -- OVERFLOW BIT OP -- ODD PARITY BIT

The Status flags signify the following conditions:

BIT 0: LOGICAL GREATER THAN (L>), is set to 1 if a larger unsigned number is compared to a smaller unsigned number. BIT 1: ARITHMETIC GREATER THAN (A>), is set to 1 if a larger signed number is compared with a smaller signed number.

As we have noted in the preceding chapter, the most significant


bit (bit 0) of a word holds the sign of the number (0 for positive, 1 for negative). For positive numbers, the remaining bits represent the binary value of the number. For negative numbers, the remaining bits represent the two's compliment form of the binary number.

EQUAL (EQ), is set to 1 when two numbers being compared BIT 2: are equal. The equal bit is set regardless if the comparison is between two signed numbers or two unsigned numbers. BIT 3: CARRY (C), is set to 1 if an add operation produces a carry or if a subtraction operation produces a borrow of bit 0; otherwise it is reset to O. The Carry bit also holds the value of a bit that has been rotated or shifted out of a Register or Memory location. BIT 4: OVERFLOW (OF), is mainly an error indicator. It is set to 1 when the addition of two like signed numbers, or the subtraction of two oppositely signed numbers, has produced a result that is too large or small to be represented correctly by a single word.
Additionally, the OF bit is set to 1 if, during an arithmetic left shift, the most significant bit of the Register being shifted

THE ASSEMBLER

19

changes value. Also, during divide operations the OF bit is set to 1 if the most significant 16 bits of the dividend are greater than or equal to the divisor.

BIT 5: ODD PARITY (OP), is set to 1 when the parity of the result of a byte operation is odd. The OP is reset to 0 when the parity of the result is even.
The parity of a byte is said to be odd when the number of bits contained within it having a value of 1 is odd. For example the byte 0001 1111 is said to have odd parity because it has an odd (5) number of bits set to 1. Even parity is just the opposite.

BIT 6: EXTENDED OPERATION (X), is set to 1 when software implemented extended operation is initiated. However, the instruction XOP (for extended operation) is not available on all Home Computers. The only way to see if your computer supports this instruction is to try it. BITS 7-11:
-

UNUSED

BITS 12 15: INTERRUPT MASK, allows the TMS 9900 to recognize interrupt requests from peripheral devices hooked into the system. If the peripheral device has a level number less than or equal to the value in the interrupt mask, it is permitted by the CPU to interrupt a running program. Thus, if the four bits making up the interrupt mask are set at 2 (0010), then any device with a level D, 1, or 2 may interrupt a running program. In your Home Computer the interrupt mask is always set at 2 (0010). Because of this only values of 2 and 0 are useful.
Everybody has interruptions in their lives. Some of these are necessary such as when a newborn cries for food, you must stop what you are doing attend to the infants needs. While other times you may be to busy to be interrupted, such as when the phone rings during your favorite T.V. show; you may choose to let it go unanswered! The same is true for the computer. Sometimes peripheral equipment needs information from a running program and interruptions are the only way they can get it. Also, some ROM routines such as automatic sprite motion or sound generating routines need to be able to interrupt your running program in order to execute.

When you first turn on the computer all the Status bits are reset to 0. Don't worry if your not quite sure yet as to the significance of the Status Register, it should become clearer as we progress.

20

THE ASSEMBLER

75,1 WIRI -TIP49

F1RADIFRIPIMB

When first putting a program together from scratch you should follow a certain logical sequence of steps. These steps are summed up below: 1. Decide first exactly what it is you want the computer to do. Rough diagramming a "plan" of the program, referred to as a flowchart, helps get your thoughts together. Start putting the instructions (referred to as source statements or code) down onto paper. Enter the instructions into the computer through an Editor program which we will discuss in greater detail later. Convert the source code you have written into object code that the computer can understand using an assembler program. If the assembler finds any errors, correct these and reassemble. Run the program on the computer. If it performs differently than what you had expected, you must debug the program. This involves taking a copy of your source code and changing it until you can get the program to run right.

2.

3.

4.

5.

mia

F.:nil- DER F.IRADGF,-A,m

The Editor is 'a program that we have not mentioned yet. The Editor program allows you to write out your source code and edit it directly on the screen before assembling it. The Editor program also allows you to save an incomplete source program on disc for later revision. This book assumes that you are already familiar with the Editor program. If you are not sure, refer to the instructions in the beginning of the Editor/Assembler manual that accompanies the software. If you are using the mini-memory module and line-by-line assembler refer to chapter 10.

fs-AoluIR.IDEE cf...DIDE:
Now that we have a general understanding about how to go about constructing source code, it is time to proceed along the specifics; namely creating a program. The source code is a logical sequence of instructions designed to guide the computer along a desired course. A source statement can be categorized as an instruction, pseudo operation, or an assembler directive.
-

THE ASSEMBLER

21

As we have mentioned before, an assembly language abbreviation (instruction) is a symbolic representation of a binary instruction. It is translated literally by the assembler program during the assembly process. Pseudo-operations and assembler directives give directions to the assembler program (not the computer) as to what to do with certain instructions or data. Assembler directives, pseudo-operations and assembly language instructions will be covered in greater detail in future chapters.

C:".", C11 NI

-I- ink P,II -T" B

I INI F" Ft: C3 B Ft: int 141 ri I !NJ constants into the computer you may use

When entering numbers or one of several forms:

1.

DECIMAL --

Entered as a base ten number. May be an unsigned number from 0 through 65535, or a signed value ranging from -32768 through 32767.

123 -2410 65535 2. HEXADECIMAL -Entered as a string of up to +our alphanumeric (A thru F) characters preceded by a greater than (>) sign. The following are valid examples of hexadecimal constants:

>OF >1AC >32FD 3. CHARACTER CONSTANTS -Entered as a string of ASCII characters enclosed in single quotes; for example 'A' or 'AD'. A character constant consisting of only two quotes (no characters) is also valid. The following are valid character constants:

Phac:t.Pr. '2'

(7

,:on0=NA

el!:-.)
1 (50)'

Yajqqs

'AB'
'307.'

'HELLO !' 4.

1 (65)(66)' '(51)(48)(37)' ' (72) (69) (76) (76) (79) (32) (33) '

ASSEMBLY-TIME CONSTANTS --

These constants are defined at the time of assembly. The are written in the operand field of an EQU instruction. We will spend more time explaining how these constants are used when we reach this instruction in later chapters.

'1 '1 .4-.4.

THE ASSEMBLER

Negative numbers are also easily specified. If the constant is in decimal form simply precede it with a minus sign (e.g.-23). If the number is in hexadecimal notation you must enter it in its two's compliment form. For example, -42 and >D6 both represent the same value.

MC:

(:31._

"1-sickMMIET4 -11-

Each line in an assembly language program is referred to as a source statement. Each source statement contains up to four Fields separated by a single blank space. The fields are positioned as follows:

Label Op code Operand(s) Comments


-

Of these four fields, only the op code field is always required for a valid source statement. The other fields may or maynot be required depending on the op-code used. The maximum length of a source statement is 80 characters, however only 60 of these will be displayed when using a list file. The first character typed on a line begins the label field. If you do not use the label field then the first character must be a blank space. All the fields are separated by at least one blank space. The following is an example of a single source statement that uses all four fields:
-

MYREG BSS

>32

*RESERVE MEMORY FOR MY WORKSPACE REGISTERS

The following sections will describe the four fields that make up a source statement.

IL_IrA]BEA__ V- I E... L_Eli . The label field is a name or label that you give to a source statement so that you can refer back to it. This label can then be used in other instructions to refer back to it. For example, when you instruct the computer to jump from one instruction to another, you give its destination by specifying its label. Unless the first character is a blank, the first character in a source statement begins the label. It can be up to 6 characters in length. A label can be made up of any alphanumeric characters, but the first character must always be alphabetic. If you elect to omit the label field the first character of the source statement must be a blank space. Also, you are not allowed to put a blank space in the middle of a label; ie: MYREG not MY REG.

Labels are usually used to identify the target of a jump instruction.

THE ASSEMBLER C3F"ICC3 rip


F- I

23

a 1...... ID

known as the one to four letter acronym for the microprocessor instruction. When the assembler program is run it uses an internal reference table to translate each acronym into the appropriate binary code. The type of op-code used determines how many and what type of operands should be found in the operand field.

The op-code field (short for operation code) is also mnemonic field (pronounced knee-mon-ik). It holds the

10F.*IFc Pt Ni r)

F- I

la L.... ID

The operand field contains the data or the location of the data needed by instruction in the op-code field. Some op-codes do not require an operand while others require one or more. If more then one operand is required they are separated by a comma. The operand field may contain one or more terms, expressions, or constants depending on the needs of the instruction in the op-code field. To sum up, the operand field contains the data that the instruction in the op-code field refers to. For example, in this ADD operation:

RO I R1

the ADD (A) instruction refers to the addition of the value in Workspace Register 0 to the value in Workspace Register 1.

The comment field is an optional field that begins one space after the operand field ends. It is always begun with an asterisk (*). The comment fields contains comments written by the programmer as a reminder to what the source statement does. These statements are ignored by the assembler program during the assembly process. Comments are utilized to remind you what the function of a source statement or group of source statements is. For example, the statement:

MYWSP EQU

>8300

*BEGIN WORKSPACE AT THIS ADDRESS

reminds you that your workspace was begun at the specified address in memory. Comments can also stand alone on a line if the line begins with an asterisk (*). In this way entire blocks containing just comments can be constructed: ************************************************ * * * DEFINE EQUATES * ************************************************

24

THE - ASSEMBLER
74:1

CHAPTER

STUDY EXERCISES

1. What is the name of the program that converts sourFe code into ti# 'object code? 0 42. A Software Workspace area consists 'O-( how many registers? 3. Which bit of the Status Register is set when the result of arithmetical expression is too large to be represecited ih two's compliment form? 4. Regarding the four fields in the source statemeht? (a) (b) Which three of the fields may be optona_1? : _ Which character always begins a 3ine of comment or the first letter in a comment field. Which field of a source statement is al I ways.requi -P red? ,
is

(c)

5. What is the difference between an assembler directive and a instruction. 6. Is the followinga valid_he,xadecim,al,number? . ,
ti

t".4

6 0

>DEFG

.t7

7. Which portion of a source statement ,determines which and what type of operands are required.
;7,

re m ;,

-;

V
*.f

-I
';-

tri

=4 .5

"3

THE INSTRUCTION SET


For a quick review, remember that the location of each byte in RAM is designated by an address, much like the location of each house in a city is specified by its address. Also keep in mind that the number held at a particular address could in turn specify another address where information is located. With this in mind we will proceed with a discussion on addressing modes which simply stated, are ways of telling the assembler program exactly at what address in RAM needed information is located.

zi_o dembnnexiNie mcim.9


Your Home Computer provides a variety of ways to access the numbers that your programs perform operations on. These numbers are referred to as operands and specific ways to address them are referred to as addressing modes. There are a total of five addressing modes available when programming, they are

1. WORKSPACE REGISTER AND IMMEDIATE ADDRESSING 2. WORKSPACE REGISTER INDIRECT ADDRESSING ... SYMBOLIC REGISTER ADDRESSING 4. INDEXED MEMORY ADDRESSING 5. WORKSPACE REGISTER INDIRECT AUTO-INCREMENT ADDRESSING
The operand is the actual value that is to be "operated on" by the instruction. How you want to specify the operand determines the addressing mode that you will use. In the sections that follow each addressing mode is discussed in detail. An example is provided of each modes usage.

-25-

Zez

II1L iNbIKULIWN bEF

VII C3 Fc IF< ', F" ite:4 IC E IF: EGIB -11- IR: enk ID Ell IR: 1E 9-. 9 I NI In Workspace Register Addressing The operand is located in the specified register. Remember that a Workspace consists of sixteen consecutive Registers labeled RO through R15. Workspace Register 5 would thus be referred to as "R5". You specify in the beginning of your program where these registers will be located in RAM. We will have more on this later. An example of Workspace Register Addressing is the statement:

MOV R2,R4
which moves a copy of the contents of Workspace Register 2 (R2) into Workspace Register 4 (R4). Another example:

R6,R7

adds the contents of Workspace Register 6 (R6) to the contents of Workspace Register 7 (R7). The result is then placed in R7. When using Workspace Register Addressing Mode it is important to remember that the operand is found in the Register specified. :I. Pi pi 1E: ID :11: ons "T. P.' onk 13 ID Fi: E !E73 E3 I: NI C" :3
-

You can also specify a constant as a source operand. In this way the value is right there for the assembler to get and does not have to be located in a Register or found at another address. This is termed Immediate Addressing. An example is the following statement:

LI

R0,324

which places (loads) the value 324 into Workspace Register 0, and the statement:

LI

R9,>144

which loads the value >144 (324) into Workspace Register 9, and the statement: LI R6,-32

which loads the value -32 into Workspace Register 6. NOTE: Remember when using signed numbers the most significant bit holds the sign of the number. This limits signed values to numbers that can be represented with only 15 bits. The signed values thus range from +32767 (>7FFF) to -32768 (>8000). Unsigned numbers, however can range from 0 (>0000) Lo 65535 (>FFFF) since bit 0 does not have to be used to hold the sign of the number.

THE INSTRUCTION SET

27

I rq ID I IFC

-11- IA ID ID FZ.

I t 10

With this type of addressing, the register specified contains the address of the operand instead of the operand itself. An indirect Workspace Register Address is preceded by an asterisk (*). For example, the statement:

MOV *R3,*R0
copies the word at the address given in Workspace Register 3 into the address found in Workspace Register 0. Notice how both R3 and RO are indirectly addressed, that is they both contain the address of the information rather then the information itself. Another example is the statement:

A *R4,R6
which adds the contents of the word being held at the address given in Workspace Register 4 to the contents of the word in Workspace Register 6. The result is then placed in Workspace Register 6. Notice how in this case R4 is indirectly addressed while R6 is directly addressed.

I NI ID I IF:

IC -1- anli Li -11.

rA

Fel ff.: NI in

Ea) F:: IE.:

E3 NI C3

With this type of addressing the register specified contains the address of the operand as with indirect addressing. After the address is obtained from the Workspace Register, the address in the Workspace Register is incremented by 1 for a byte instruction or by 2 for a word instruction. This allows you to access data in memory in a sequential manner from a given starting point. A Workspace Register auto-increment address is preceded by an asterisk (*) and followed by a plus (A-) sign. For example, the following statement:

A *R3+,R1
adds the contents of the word found at the address given in R3 to the contents of Rl. The result is placed in R1. The address in R3 is then incremented by two ('A' is a word instruction). Another example is the statement:

MOV R9,*R10+
which copies the contents of R9 into the address given in R10 and increments the address in R10 by two. Now lets consider an example using real values. Suppose R1 contains >0004 and R2 contains >000A and address >0004 contains the value >0010, then the statement:

A *R1+,R2

28 THE INSTRUCTION SET

adds the value found at address >0004 which is >0010, to the value found in R2 which is >000A. The result, >001A is placed in R2. The value in R1 is then incremented by two (A is a word instruction). Thus, after completion of this statement R1 contains >0006, and R2 contains >001A.

miampliFey AnniFoIp41E3
This type of addressing allows you to use a symbol to represent the address that contains the operand. The symbolic memory address is preceded by an "at" character (@). For example, if RO contains >0002 then the statement:

JOYI EQU >00FF

@JOYI,R0

adds the contents of RO with the contents at "JOYI" (in this case >00FF) the result, >0101, would then be placed in RO. Another example is the statement:

MOV @>AA03,@>0E3F
which copies the word at address >AA03 into location >0E3F.

1-11-1o1F
With indexed addressing, the effective address is gotten by adding the value of an index register to a displacement variable. You often use this addressing mode to access elements in a table. In such a case the value in the index register points to the beginning of the table, and the displacement to an element in the table. The indexed memory address is preceded by an "at" sign (@) after which comes the displacement value followed by the index register which is closed in parentheses. For example,

@4(R4),R1

gets the word found at the address computed by adding 4 to the address in R4. This word, in turn, is added to the word found in Rl. The result is then placed Rl. Another example in the statement:

MOV R5,@TABLE+3(R7)
which copies the contents of register 5 into a memory word. The address of this memory word is determined by taking the sum of

THE INSTRUCTION SET


TABLE plus 3 and adding it to the contents of register

29

7 (R7).

note: Workspace Register 0 (RO) is reserved and may not be specified as an indeg register.

F-F-Reic.31 locluitNimIF: IFcIL_PcirI.

rvIDDIR78eIlNic3

This addressing mode can only be used in the operand fields of "jump" instructions the program counter relative address is written as an expression that corresponds to an address at a word boundary. An Example is the statement:

JMP GETKEY
which jumps unconditionally to location GETKEY. GETKEY is a label that you gave another source statement in the program. It should be noted that when an expression (like GETKEY in the last example) is evaluated it is subtracted from the value of the current location plus two This value is then divided by two with the result being placed in the object code. This value must fall between the values -128 through 127 or the jump will not be executed. This means that the destination of a jump cannot be any farther than 256 (>100) bytes from the current address in the program counter. To sum up you are not allowed to make a jump (using JMP) in your program greater than >100 bytes in length.

IPAF:I -FIAMIa VIIC

DIF*IEF;:iPlirIIDINVe

When programming you will have occasion to add, multiply or otherwise manipulate numbers. The TMS9900 allows addition (+), subtraction (-), multiplication (*), and signed division (/). When an expression is evaluated, the assembler first negates all constants or symbols preceded by a minus (-) sign. All succeeding operations are carried out from left to right. Precedence is only given to the negation of symbols and constants, not to any other procedure. Therefore 4+6/2 is evaluated as 5 and not as 7. A remainder is disregarded in division, thus 5/2+4 equals 6. Parentheses cannot be used to alter the order that an expression is evaluated in.
4t
-

'_2 7

-T- FAI

IINIB

IIIIDINI

EE -T-

The TMS9900 recognizes a number of different instructions. Table 4.1 lists the assembler mnemonic for each instruction and explains what each mnemonic stands for. Also listed is the required operand(s) and operand format for each instruction. You should

30

THE INSTRUCTION SET

have a thorough understanding of addressing modes before proceeding to the instruction set. TABLE 4.1 INSTRUCTION SET MNEMONIC A AB ABS AI ANDI B BL BLWP C CB CI CLR COC CZC DEC DECT DIV INC INCT INV LDCR LI LIMI LWPI MOV MOVB MPY NEB ORI RTWP S SB SDO SBZ SETO SLA SOC SOCB SRA SRC SRL DESCRIPTION OPERAND(S) & FORMAT G,(G) G,(G) G (W),# (W),# G G G 8,8 G,G W,# G G,W G,W G G G,W G G G G,#* (W),# # # 8,(6) G,(G) G,(W) G (W),# G,(G) G,(G) CRU CRU G (W),#** G,(G) G,(G) (W),#** (W),#** (W),***

ADD WORDS ADD BYTES TAKES ABSOLUTE VALUE OF OPERAND ADDS AN IMMEDIATE VALUE TO WORKSPACE REG. LOGICAL AND IMMEDIATE VALUE BRANCH BRANCH & LINK BRANCH & LINK WORKSPACE POINTER COMPARE WORDS COMPARE BITS COMPARE IMMEDIATE VALUE CLEAR COMPARE ONES CORRESPONDING COMPARE ZEROS CORRESPONDING DECREMENT DECREMENT BY TWO DIVIDE INCREMENT INCREMENT BY TWO INVERT LOAD CRU LOAD IMMEDIATE VALUE LOAD INTERRUPT MASK WITH IMMEDIATE VALUE LOAD WORKSPACE POINTER W/ IMMEDIATE VALUE MOVE MOVE BYTE MULTIPLY NEGATE LOGICAL OR IMMEDIATE VALUE RETURN WORKSPACE POINTER SUBTRACT SUBTRACT BYTES SET CRU BIT TO ONE SET CRU BIT TO ZERO SET TO ONE SHIFT LEFT ARITHMETIC SET ONES CORRESPONDING SET ONES CORRESPONDING, BYTE SHIFT RIGHT ARITHMETIC SHIFT RIGHT CIRCULAR SHIFT RIGHT LOGICAL

THE INSTRUCTION SET

31

TABLE 4.1 INSTRUCTION SET (CONTINUED)


MNEMONIC JEQ JGT JH JHE JL JLE JLT JMP JNC JNE JNO JOC JOP STRC STST STWP SWPB SZC SZCB TB X XOP XOR DESCRIPTION JUMP IF EQUAL JUMP IF GREATER THAN JUMP IF LOGICAL HIGH JUMP IF HIGH OR EQUAL JUMP IF LOGICAL LOW JUMP IF LOW OR EQUAL JUMP IF LESS THAN JUMP JUMP IF NO CARRY JUMP IF NOT EQUAL JUMP IF NO OVERFLOW JUMP ON CARRY JUMP IF ODD PARITY STORE CRU STORE STATUS STORE WORKSPACE POINTER SWAP BYTES SET ZEROS CORRESPONDING SET ZEROS CORRESPONDING, BYTE TEST CRU BIT EXECUTE EXTENDED OPERATION EXCLUSIVE OR OPERAND(S) & FORMAT P P P P P P P P P P P P P (G),#* W W G 8,(G) GOO) CRU G (3,#*** G,(W)

* This operand represents the number of bits to be transferred. This value ranges from 0 through 15 with 0 indicating 16 bits. ** This operand is the shift count. ***This operand specifies the extended operation. G - Indicates a general address which can be in one of any of the following modes: a) Workspace Register b) Indirect Workspace Register c) Symbolic Memory d) Indexed Memory Address e) Indirect Workspace Register Auto-Increment W - When this is specified the operand has to be a Workspace Register Address. # - Value entered as a constant. P - This operand is a program counter relative address. CRU - Give CRU bit address. ( ) - The address at which a result is placed when two operands are required.

-7 ,1 ...)

.e.:.

THE INSTRUCTION SET

The instruction set can be divided into the following 7 functional groups:

1. 2. 3.

DATA TRANSFER INSTRUCTIONS or LOAD AND MOVE


Instructions allow you to move information between registers and memory locations. ARITHMETIC INSTRUCTIONS allows you to perform arithmetic operations. JUMP AND BRANCH INSTRUCTIONS performs jumps, calls to procedures, and returns from procedures, in this way you can control the order in which the program executes. COMPARE INSTRUCTIONS let you compare words, bytes, or immediate values with each other. They even let you compare groups of bits within a byte or word that may correspond with each other. These instructions only affect the Status Register. LOGICAL INSTRUCTIONS permit the performance of logical operations on workspace registers and memory locations. SHIFT INSTRUCTIONS allow you to shift the bits in a Workspace Register a specified number of positions. BIT INPUT/OUTPUT INSTRUCTIONS allow you to manipulate the LRU bits.

4.

'''' 6. 7.

:0 ifnil "T de-211

" 1-- 47-7 IP, NI 13 IF7 E.::: Uzi: ,7.

I IMI 1E-3 1- IR! LOC: "T I CI ith4 1:3,

Data transfer instructions move numbers between registers and memory locations. Table 4.2 outlines the format of each insLruction as well as which bits of the Status Register are affected by each instruction.

TABLE 4.2
Status Register Bits (;) indiGates bits affecLed by instruction MNEMONIC FORMAT

L> A> EQ C OV OP X X X X
-

INT MASK
11N.. - -

MOV MOVB LI LWP1 LTM1 STST STWP SWF'S

6,(6) 6,(G) (W),# # # W W 6

X X X
-

X X X
-

A 1-

- - - -

X
-

- -1. - - - -

_ -

1-

_ -

1_

XXXX
- _ _ _ - - -

THE INSTRUCTION SET 33


C:0 ) Pi C3 '1/4.11 lE". VI C3

One of the foundational instructions in assembly language is the "move word" (MOV) instruction. It can transfer a word from a source operand into a destination operand. The destination operand is then compared to zero and sets (or resets) the L>, A>, and ED status bits accordingly. The following are examples of operand combinations that are legal:

MOV MOV MOV MOV

@HERE,@THREE @HERE,R7 R3,R4 R7,@DEST

*MEMORY TO MEMORY (COPY INTO THERE) *MEMORY TO REGISTER (LOAD REGISTER) *REGISTER TO REGISTER *REGISTER TO MEMORY

Another use of the MOV instruction is to compare a memory location to zero. For example, the following source statements:

MOV R5,R5 JEQ CHECK

*Move R5 into itself and compares it to 0. *Jump to location "CHECK" if R5=0.

move Workspace Register 5 into itself and then compares the contents of R5 to zero. If R5 is equal to zero than the EQ bit is set and the JEQ instruction will cause the program to "jump" to location "CHECK".
1F3
-

IEE.

Et 14fer 'T. ET .

This instruction copies the most significant byte of the source operand into the destination operand.. For example suppose memory location >2E32 contains the value >23A6 and HOLD is located at address >2E32, and if R2 contains >34CC then the statement:

MOVB @HOLD,R2
changes the contents of R2 to >23CC and compares the contents of R2 to zero. As a result of this comparison and the logical greater than, arithmetic greater than, and odd parity bits are set, while the equal status bit is reset.

Places a given number in a specified Workspace Register. The contents of this register is compared with zero and the results of this comparison affect the L>, A>, EQ bits of the Status Register accordingly. For example, the statement: LI R2,>23 *Load Workspace Register 2 with >0023.

loads R2 with >0023 (35) and sets the logical greater than, arithmetic greater than, and resets the equal status bits.

54

THE INSTRUCTION SET

IL.WIF" I >

F"

IE: IF"01 I NI -FE:

im

Y..> I Ir:41 -11- E:

Places the Workspace Pointer at the address specified by the immediate operand. For example, the statement: START LWPI >20BA *SET START EQUAL TO >20BA Sets START equal to >20BA and also sets the Workspace Pointer to location >20BA. The LWPI instruction has no effect on the Status Register. Pell I > C3IA:ID, I Kg
01-21...F3 1-:( I rail pi Ern I ir- , A

This instruction loads the interrupt mask of the Status Register (bits 12-15) with a specified value. For example, the statement: LIMI 2 sets the interrupt mask at 2 (>0010) and enables interrupts at levels 0, 1, and 2. While the statement: LIMI 0 disables all interrupts and is the normal state of the computer (>0000).
,

7,0

El;

tE.:3 --r

Lit E3

113

E3 -11-

Stores the current contents of the Status Register in a specified Workspace Register. For example the statement: STST R5 stores the current Status Register contents in Workspace Register 5.

--r 11.4F- >

Ft:

WIDIE4i:II<E3F"IPICAE FAD

This instruction saves a copy of the contents of the Workspace Po*nter Register in a specified Workspace Register. For example, the statement: STWP
R4

stores the Workspace Pointer value in R4.


$3.3

E3WtqlF"

Y -I FEE];

This instruction switches the most si gnificant byte with the least significant byte in a General Register. In other words, SWPB

THE INSTRUCTION SET

? IC ....),)

exchanges the left and right bytes of a specified word. For example, the statement: SWAP SWPB R2 replaces the most significant byte of register 2 (bits 0-7) with a copy of the least significant byte (bits 8-15) contained within the register. Conversely, the least significant byte of register 2 is replaced with a copy of the most significant byte. In this way bytes can be interchanged in anticipation of various byte instructions. In another example, suppose RO contained the value >2244, and memory location >2244 contained the value >FF33, the instruction: SWPB *RO would change the contents of memory location >2244 to >33FF. In summary, the SWPB instruction exchanges left and right (least/most significant bytes) of a word specified in a general register. The SWPB instruction has no effect on the Status Register.

.4.

-4

1-- 11-11 E:::

IC% F-*". -4,

I "T 1-11 tri E:: -11- I C.::

I V1/4.11 E3 -IF Fi: t.....11 Cf.:, -11- I. ID trA :E.3% '

Arithmetic instructions allow you to perform a variety of arithmetic operations in your program. Table 4.3 shows which bits of the Status Register that are affected by each instruction. TABLE 4.3 ARITHMETIC INSTRUCTIONS

---_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-___
Mnemonic
A

Format
6,(G)

STATUS REGISTER BITS (X) INDICATES BITS AFFECTED BY INSTRUCTION INT MASK L> A> EQ C OV OP X
X X X

AB
ABS AI DEC,
DECT DIV I NC I NCT MPY NEB S GB

G,(G)
G (W),# G
G

- - X X - - - X X X X ^ X X X X X X X X X X - - - X
X X X X X Y._ - 1-- 1-- -

X X

X X X

...-

...-

---

G,(W)
G G G,(W) G G,(G) G,(G)

X X X X X - - - - - Y._ X X X X X - - - - - - - - - X X X - X - - - _ - - ^ X X X X X - - - X X X X X X

36

THE INSTRUCTION SET

13 r)

tAi

F: 1.3 E3

This instruction adds a copy of the source operand to a copy of the destination operand and places the sum in the destination operand. For example, the statement: A *R3,*R4+ adds the contents of the word found at the address in R3 to the word found at the address in R4. The sum is placed at the address given in R4 and the address in R4 is incremented by two (Workspace Register auto-increment addressing). The sum is compared to zero and the results of the comparison are reflected in the Status Register. Another example we can look at supposes that the address labeled TABLE contains >2123 and R2 contains >000B, the statement: A R2,@TABLE then causes the contents at TABLE to change to >212E. The logical and arithmetic greater than bits are set and the equal, carry and overflow bits are reset in the Status Register. The contents of R2 remain >000B.
dcb ) E> :E.1 'Ye 11- 1E1 E3

This . instruction adds the left most byte (bits 0-7) of the specified source register to the left most byte of the destination register. The result is placed in the left-most byte of the destination register. For example, in the statement: AB R3,R4 the left byte of R3 is added to the left byte of R4 and the sum is placed in the left byte of R4. Another example, suppose that R2 contained the address >23FA at which was located the memory word >2233, and 'R3 contains >DD8B, then the statement: AB *R2+,R3 changes the contents of R3 to >FF88 and increments R2 by one to >23FB. This result is obtained by taking the left most byte of the memory word specified in the address given in R2 (>22) and summing it with the left most byte in R3 (>DD) coming up with >FF. This sum is then placed in the left most byte of R3 and R2 is incremented to >23FB. Comparison of the sum with zero sets the logical greater then, overflow, and odd parity bits of the Status Register while it resets the arithmetic greater than, equal, and carry status bits. Another example, R4 contains >8100, and

THE INSTRUCTION SET

39

The instruction is ignored and the overflow status bit is set while the source and destination operands remain unchanged. Lets take some time now to look at a few examples to see if we can clarify things. Suppose that memory location LOCA contains >0005, R2 contains >0001 and R3 contains >000D, then the statement:

DIV @LOCA,R2
divides 65549 (>0001000D) by 5 and places the quotient 13109 (>3335) in R2 and the remainder, .2 (represented as "2") in R3. In another example suppose that LOCA contains >0002 and R2 contains >0004, also R3 contains a zero, then the statement:

DIV @LOCA,R2
attempts to divide 262144 (00040000) by 2. The resultant quotient, 131072, cannot be represented in a 16-bit word. The result is that the overflow bit is set in the Status Register and the operation is canceled. In summary, the destination operand is a consecutive 2-word area of a Workspace Register. It should be noted that if the destination operand is Workspace Register 15 (R15) the first word of the destination operand is in R15 and the second word is in the memory location immediately following the Workspace area. Note that the DIV instruction does not let you divide by an immediate value directly. To do this, you must put the immediate value into a register a Register or memory location. The following examples illustrates this point.

HERE EQU >14 THERE EQU >05 ZERO EQU >00 MOV MOV MOV DIV @HERE,R7 @THERE,R5 @ZERO,R6 R5,R6

*
* Load equates

*
* Move values into * Computes
20/5,

Registers result goes in R6.

Another example,

LI R5,>05 LI R6,0 LI R7,>14 DIV R5,R6


IN.11

*
* Load Registers

*
* Computes 20/5, result goes in R6.

IR EL: r-1 FE: INI -r"

This instruction increments the source operand by one (1). The result then replaces the source operand. The computer compares the new value to zero and sets/resets the status bits accordingly.

40

IHE INSTRUCTION SET

With a carry of bit 0, the carry bit is set. With an overflow, the overflow bit is set. An example of the INC instruction is the statement: INC @ADRS which increments the value specified at location ADRS by one. ( I

I INJFe.:1E:FIE .. INUT-

FAN'

1- 104101

This instruction increments the source operand by two (2). The result then replaces the source operand. The computer then compares the sum to zero and sets/resets the status bits accordingly. When there is a carry of bit zero the carry bit is set. With an overflow, the overflow bit is set. Lets consider an example where R3 contains >0022: INCT R3 this statement then increments R3 by two and places the result (>0024) in R3. The arithmetic greater than, logical greater than status bits are set while the equal, carry, and overflow status bits, are reset. Both the increment and the decrement instructions are useful to index byte arrays while the increment and decrement by two instructions are useful to index word arrays.

The MPY instruction performs a multiplication. The source operand is multiplied by the destination operand. The product is then placed in the 2-word destination operand. For example if RO contains the value >0003, R3 contains the value >0005, and R4 contains the value >0EA7, the statement: MPY R0,R3 multiplies the contents of RO and R3 together to get >000F and places this value in R4. R3 now contains a zero (>0000). The Status Register is unaffected by the MPY instruction. Another example supposes that the memory location HERE contains >FFFF and R3 contains >0002, then the statement: MPY @HERE,R3 multiplies the contents HERE (65535) to the contents of R3 (2). The product 131070 (>0001FFFE) is placed into R3 (>0001) and R4 OFFFE). Memory location HERE is unchanged as is the Status Register. If the destination operand is specified as R15 the product is placed into R15 and the first memory word immediately following the workspace memory area.

THE INSTRUCTION SET


c t.,41 e )
IA la ID IA --r

41

This instruction replaces the source operand with its additive inverse. The computer then compares the result to zero and sets/resets the status bits to reflect this comparison. Suppose memory location VALUE1 contains the value >9BC1, then the statement:

NEB @VALUE1
changes the contents of VALUE1 to >643E. The logical greater than and arithmetic greater than status bits are set in the Status Register while the equal and overflow status bits are reset.

This instruction subtracts a copy of the source operand from a copy of the destination operand and places the result in the destination operand. The result is compared to zero and the status bits are set/reset accordingly. When there is a carry of bit zero, the carry bit is set. When there is an overflow, the overflow bit is set. For example, suppose that memory location HERE contains >2123 and memory location THERE contains >AA33, then the statement:

S @HERE,@THERE
changes the contents of THERE to >8E10 (>AF33->2123). The logical greater than, arithmetic greater than, carry and overflow status bits are set, while the equal status bit is reset.

< 9 Ec )4

9 Li - -11- IF IPI 1177; 11 - E:4 No' 11- E-17. 9; .1a

This instruction subtracts the source operand, whiLh is a single byte, from the destination operand, which is also a single byte. The difference is then p]aced in the destination operand. The computer compares the resulting byte to zero and sets/resets the Status Register bits to reflect the results of this comparison. When there is a carry of the most significant bit of the byte (bit 0), the carry status bit is set. When there is an overflow, the overflow status bit is set. If the resulting byte has an odd number of bits set to one, then the odd parity bit is set. If the operand is specified in a Workspace Register, then only the left most bits (bits 0-7) are used. For example the statement:

SB RO,R1
which subtracts the left-must byte of RO from the left-most byte of R1, and places the difference in the leftmost byte of Rl. Another example supposes that memory location ADDR contains the value >131D and R5 contains the value >23F5, then the statement:

42

THE INSTRUCTION SET

Sb R5,@ADDR changes the contents of R5 to >F610. The logical greater than bit is set, while the other status bits affected by this instruction are reset.

aumF-

EcIF:021rAIGFA

Jump instructions as well as branch instructions are used to transfer control from one area of the program to another. This control transfer may be conditional or nonconditional. These instructions are mainly used to control the sequence in which a program executes. Table 4.4 outlines the conditional and nonconditional branch and jump instructions and the status bits tested by each instruction:

TABLE 4.4 JUMP & BRANCH INSTRUCTIONS


STATUS REGISTER BITS TESTED/AFFECTED (t) indicates bits tested by instruction L> A> EQ C OV OP X INT MASK

Mnemonic Format

UNCONDITIONAL TRANSFERS
BL BLWP jivIP RTWP .

^ -expression
*X

M.. M.. x

1x

_ -

_ ^ -

_ x

^ _ x

^ - _ _1- - _ - - _
x
x x x

x x

CONDITIONAL TRANSFERS
JEQ JNE JH JL JHE JLE JOT** JLT** JNC JOC JNO JOP expression expression expression expression expression expression expression expression expression expression expression expression t t t t -

t t -

t t t t t t t -

_ _ _ -_ ^ t _ t _ - t -_ r-

^ _ _ -

^ - - _ M.. ^ ^ - - - y- _ _ _ _ ^ - - _ - - - _ _ - _ - -

ITERATION CONTROLS
X XOP ***x source source,operation x x x x x x x x x x

t=tested status bit, x=affected status bit

THE INSTRUCTION SET

43

* Restores all status bits to the value contained in Workspace Register 15 (R15). ** Only JGT & JLT instructions use signed arithmetic comparisons. All other comparisons are logical (unsigned) comparisons. *** The instruction 'X' does not directly affect any status bits, however the executed instruction affects the Status Register accordingly.

This instruction transfers control to another line in the program. It does this by replacing the contents of the Program Counter Register with the address specified in the operand. This instruction has no affect on the Status Register. For example, if R4 contains >32F1, the statement: B *R4 causes the word at location >32F1 to be placed in the Program Counter Register. This has the effect of letting the word at location >32F1 be used as the next instruction executed by the program. Ec L... lB IA NI IC FI

Nur)

L._ I 104

This instruction transfers control to another line in the program. It also stores the address of the instruction immediately following the BL in RII. The transfer of control is accomplished by replacing the value in the Program Counter Register with the value specified by the source operand. The BL instruction has no affect on the Status Register. For example, if the statement:

BL @SUBL
occurs at memory location >06CA, the instruction places the value >06CE in RII and places memory location SUBL in the Program Counter Register. note: The instruction code which are Therefore, the second word is L.4 F" BL @SUBL requires two words of machine placed at addresses >06CA and >06CC. word address immediately following the >06CE which is the value placed in RII.

ED: FR 01 P4 IC ir.41 V4 11) L_ C3 ir; 13 1,0,41 C3 FR E3 IF" EE IF- C3 rA

IF:

When this instruction is implememnted the following occurs: 1) The source operand is placed in the Workspace Pointer Register.

44
2)

THE INSTRUCTION SET


The word immediately following the source operand is placed in the Program Counter Register. The previous contents of the Workspace Pointer Register are placed in new Workspace Register 13 (R13). The previous contents of the Program Counter Register (the address of the instruction immediately following BLWP) are placed in new Workspace Register 14 (R14). The contents of the Status Register are placed in the new Workspace Register 15 (R15).

3)

4)

5)

When all operations are finished, the computer transfers control to the new value in the program counter. With the BLWP instruction you can link to subroutines and program modules that do not necessarily share the calling programs workspace.

( ..31"1 F' )

IA PA

CI( PA ID :t -11- I Ch I-A Pk L.

0 1.....JI t1/41F-

The JMP instruction allows you to move around in your program. It is similar to the GOTO instruction in BASIC. The JMP instruction causes the computer to take its next instruction from another location. It does not affect the Status Register. It's clean and simple. The following are examples of the JMP instructions usage:

1) 2)

JMP THERE * Jumps to location THERE. JMP >11AF * Jumps to address >11AF.

Keep in mind that when using 'jump' instructions the address you are jumping to has to be within >100 bytes of the address of the jump instruction or the instruction is ignored.

( IR 1- 1AP F" )

FR lc= 1- Li Fiz PA

lAil C) Fc. I< :E.3 F-- IA C:::: lE:-.: F" DI NI 1- IE.. IF: -:"

This instruction serves to return the computer to how things were before the calling of a subroutine through use of a BLWP instruction. Also returns from an interrupt or XOP instruction. The RTWP instruction accomplishes this in the following steps: 1) Replaces the contents of the Workspace Pointer with a copy of R13. Replaces Lhe value in the Program Counter Register with a copy of R14. Replaces the contents of the Status Register with a copy of R15.

2)

3)

In summary, the RTWP instruction restores the execution environment after completion of a BLWP instruction, interrupt, or XOP instruction.

THE INSTRUCTION SET


C.31 NI ic) 1 -r 1 pi rA ph IL.... 7- IR ink IN1 B F- FC B

45

There are 12 different instructions that allow your computer to make a "decision" before proceeding along a course of action. These decisions are based on the contents of the Status Register. Some of the conditional jump instructions test to see if the carry (C) bit has been set others test differing combinations of bits. For instance, the instruction Jump on Odd Parity (JOP) jumps only when the Odd Parity (OP) bit is set, others such as the Jump if logical High (JH) only jump if the logical greater than (L>) bit is set to 1 and the equal (EQ) bit is reset to 0. The conditional jump instructions do not change any of the status bits; instead they are the instructions which look at the bits in the Status Register. They are the only instructions which base their activity on Status Register settings. They are the

reason the Status Register exists at all.

All conditional transfer "jump" instructions occupy 2 bytes in memory. The first byte holds the operation code, while the second holds the relative displacement. You should always try and construct your programs so that the expected outcome executes when the jump is not taken. Here are a few examples of conditional transfer "jump" instructions:

1)

A R0,R1 * Jumps to location BIG if the add instruction JOC BIG * produces a carry. S R4,R5 * Jumps to location ZERO if the result of this JEQ ZERO * subtraction operation is a O.

2)

You can also check to see if a Register contains a zero by using a MOV instruction, as in the following example:

3)

MOV R4,R4 * Copies the contents of R4 into itself and * compares the result to zero. JEQ ZERO * Jump to location ZERO if EQ bit set.

You can also set up a counter in a program for use in creating delays, loops, arrays, or printing to consecutive screen locations. Counters have the general format:

4)

LI R1,1000 * Put 1000 in R1. DELAY DEC R1 * Decrement R1. MOV R1,R2 * Copy R1 into R1 and compare R1 to O. JNE DELAY * Jump if R1>0 (EQ=0) to DELAY. . * Continue program.

46

THE INSTRUCTION SET


Conditional jump instructions have the general format:
j--

expression

is a one or two letter modifier. The expression may be a constant or symbol. Looking at Table 4.5 we see a summary of the conditioina' jump instructions, as well as the conditions that cause a jump to occur. 'jump...if' refers to status bit settings.

where (--)

TABLE 4.5 CONDITIONAL JUMP INSTRUCTIONS Instruction Description


JEQ JNE JH JL JHE JLE JGT* JLT* JNC JOC JNO JOP JUMP JUMP JUMP JUMP JUMP JUMP JUMP JUMP JUMP JUMP JUMP JUMP IF IF IF IF IF IF IF IF ON ON IF IF EQUAL TO ZERO NOT EQUAL TO ZERO LOGICALLY HIGHER THAN ZERO LOGICALLY LOWER THAN ZERO LOGICALLY HIGH OR EQUAL TO ZERO LOGICALLY LOW OR EQUAL TO ZERO GREATER THAN ZERO LESS THAN ZERO NO CARRY (CARRY BIT RESET) CARRY (CARRY BIT SET) NO OVERFLOW ODD PARITY

'Jump if....'
EQ=1 EQ=0 L>=1 L>=0 L>=1 L>=0 A>=1 A>=1 C=0 C=1 OV=0 OP=1

& EQ=0 & EQ=0 or EQ=1 or EQ=1 & EQ=0

-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_____

*signed comparisons/all others use unsigned (logical) comparisons

The execute instruction allows you to utilize a source operand as an instruction. The X instruction does not alter the Status Register, but the inserted instruction affects status bits normally. If a jump is executed (that is if the status test for a jump is passed) the jump is executed from the location of the X instruction. The X instruction can specify an instruction one, two, or three words in length. Th .-. Program Counter Register is then incremented the required one, two, or three words required by the source operand. The X insLruction is mainly used when the instruction needed is dependent upon a variable factor.

It is very useful to compare various values when computing. That is the purpose of the compare instruction set. Compare instructions have no effect other then to set or reset various status bits. They are used in combination with conditional jump instructions to help the program make decisions. The compare instructions make simultaneous logical and arithmetic comparisons.

THE INSTRUCTION SET

47

Arithmetic comparisons compare the two operands as two's compliment values. A logical comparison compares them as unsigned numbers. Table 4.6 outlines a summary of the compare instructions and the status bits each affect:

TABLE 4.6 COMPARE INSTRUCTION SET


Status Register Bits (x) indicates bits affected by instruction Mnemonic C CB CI CDC CZC Format G,G G,G W,# G,W G,W

L> A> EQ C OV OP X
x x x x x x x - x x x - x x -

INT MASK
- - - - - - - - -

( ir )

c---.... co pit IF" Ink FC IE. lAi 01 Ft: 11D 9 _

This instruction compares the source operand, which is a word of memory, with the destination operand which is also a word of memory. The result of this comparison is then reflected by the Status Register. The arithmetic greater than and equal status bits reflect a signed comparison while the logical status bit reflects an unsigned (16 bit) comparison. The operands are left unchanged. The compare instructions act very much like the subtract (S) instruction in that the compare instructions subtract a source operand from a destination operand. The difference is then compared with zero with the Status flags being set accordingly. But unlike the Subtraction instruction, the compare instructions do not save the result; the operands remain unchanged. The sole function of the compare instructions is to set/reset status bits in the Status Register for decision-making by conditional jump instructions. An example of the compare word (C) instruction is the statement:

C RO,R1
which compares RO with R1 (the contents of RO are subtracted from the contents of R1; the difference being compared to zero). The Status Register is then set/reset to reflect the result of the comparison. Table 4.7 gives some examples of the compare words (C) instruction:

48

THE INSTRUCTION SET

TABLE 4.7 COMPARE WORDS INSTRUCTION


Status Register settings after

Source op
-

Destination op
-

'C' instruction Logical (L>) Arithmetic (A>) Equal


1 1
1

>FFFF >7FFF
>s000

>0000 >0000
>0000

>3FB2 >F214 >6000

>3FB2 >B345 >5FFF

0 1 0

0 1 0 0 0 0

0 0 0 1 0 0

The compare bytes instruction is very similar to the compare words instruction we have just covered. The exception is that two bytes are compared instead of two words. For example, the statement:

CB

RO,R1

compares the left byte of RO with the left byte of Rl. The result of this comparison will set or reset the appropriate status bits. The operands are unaffected. In addition to the L>, A>, and EQ status bits, the OP (Odd Parity) status bit is set when the result of the CB operation (really a subtraction operation) contains an odd number of logic one bits. Table 4.8 gives some examples of the use of the CB instruction:

TABLE 4.8 COMPARE BYTES INSTRUCTION


-------------,.---.+- -.

Status Register settings after

'CB'

instruction

Source op
-

Destination op
-

L>
1 1

A>
0 1

Equal
0 0

Odd Parity
0

>00 >00

>FF >7F

>7F >7F
>80

>BO
>7F >7F

1
0 0

0
0 1

0
1 0

1 1
0

THE INSTRUCTION SET

37

address >2232 contains >F411. Also R5 contains >2233, the statement:

AB R4,*R5
then changes the memory word >2232 to .>F492 because >el (the value of the left most byte in R4) plus >11 the (the value in memory byte >2233) equals >92. The left byte in memory word >2232 is unchanged. In this example the logical greater than, overflow, carry and odd parity bits are set, while the arithmetic greater than, and equal bits are reset. dcrEle

e;

This instruction takes the absolute value of an operand. It first checks the sign bit (bit 0) to see if it is equal to on It it is then the two's compliment of the number is taken. If the sign bit is equal to zero, then the number is already positive and the source operand is unchanged. For instance, if RO contains the value >FE00 then the statement: ABS RO changes the value of RO to >0020. In this case when the result is compared to zero, the logical greater than and arithmetic greater than status bits are set, while the overflow, and equal status bits are reset.

Pk I)

Ann I ri

1E2. ID I. ir'Al -11- E.::

This instruction adds an immediate value to a specified Workspace Register and places the result in the Workspace Register. The sum is then compared with zero and the Status Register bits are set/reset accordingly. For example, the statement: AI

R2,8

adds the value 8 to the contents of R2 and places the result in R2. Another example supposes that R5 contains >0006:

AI R5,>23
the value >0029 is placed in R5. In this case the logical greater than and arithmetic greater than status bits are set, while the equal, carry, and overflow bits are reset.

This instruction decrements the contents of a specified general register (or a memory location specified in the address) by one (1). The result then replaces the source operand. The result is

3e

THE INSTRUCTION SET

compared with zero setting/resetting the Status Register accordingly. For example, the statement:

DEC *R4
decrements by one, the word starting at the address given in R4. The DEC instruction is very helpful in counting and indexing of For example, if memory location TABLE contains the byte arrays. value >0001, then the statement: DEC @TABLE places a value of zero in location TABLE (>0000). As a result of this the equal and carry status bits are set, while the logical greater than, and overflow status bits are reset.

( IDEE.C.L'T 3

Di E:-.. C.:: FC. IFE: PI E: INI -11-- IB "N"

-1- LN0 C3

This instruction decrements the source operand by two (2). The result then replaces the operand. For example, the statement:

DECT @ADDR1
decrements the contents of ADDR1 by two. The result is compared to zero with the results of this comparison setting or resetting the status bits accordingly. The carry bit is set if there is a carry of bit zero. The DECT instruction is very helpful in counting and indexing word arrays. For instance, suppose memory location TABLE contains the value >2AEO then the statement:

DECT @TABLE
places a value of >2ADE in TABLE. The logical greater than arithmetic greater than and carry status bits are set, while the equal and overflow status bits are reset.

This instruction divides the destination operand (which is a consecutive two (2) word area of a Workspace Register) by a copy of the source operand (one word from a general Register). For example the instruction:

DIV R1,R2
divides the contents of Workspace Registers 2 and 3 by the contents in Workspace Register 1. It should be remembered that when the source operand is greater than the destination operand, normal division occurs. However, if the source operand is less than or equal to the first word in the destination operand, then the quotient will be too large to be represented in a 16 bit word.

THE INSTRUCTION SET

49

(I)

4:11MF"AlF.0

Immianiic4m

This instruction compares the contents of a Workspace Register to some immediate value. For example, the statement: CI R3,>21 and the statement: CI R3,33 both compare the contents of R3 with the number 33. The comparison is accomplished in the same manner as with the C instruction. The Status Register bits are set/reset to reflect the results of the comparison.
OC101) ICIE 101"41 C21011 104%.113I104 10

This instruction will set the EQ status bit if the bit positions set to 1 in the destination operand correspond to the bit positions set to one in the source operand. For example, the statement: COC @TEST,R3 compares the logic bits set to 1 in TEST with the bits set to 1 in R3. In another example, suppose MASK contains the word >D012 and R3 contains the value >F693, then the statement: COC @MASK,R3 sets the equal status bit to 1 for we see that: >D012 = 1101 0000 0001 0010 and >F893 = 1111 1000 1001 0011 for each bit set to 1 in the source operand there is a 1 bit in the corresponding bit position of the second operand. If R3 had contained >F890, the equal status bit would have been reset. .ZC:::) ((--

icril

zIEEF.copc _3

icoliFe

cliNinIp4

This instruction will set the EQ status bit if the bits in the source operand that are set to 1 correspond to the bits set to 0 in the destination operand. For example, the statement: COC @MASK,R3 compares the bits set to 1 in MASK, with the bits set to zero (0) in R3. In another example, suppose MASK contains the word >A632, and R3 contains the value >44DF, the above instruction sets the

50

THE INSTRUCTION SET to 1 because:

equal (EQ) status bit

>AB32 = 1010 1011 0011 0010 and >44DF = 0100 0100 1101 1111 1 k \ I
for every logic bit set to 1 (one) in)the source operand (>AB32), there is a logic bit set to (0) zero(In the corresponding bit position of the destination operand (>44DF). However, if R3 had contained the value >44DE the EQ bit would have been reset because:

>AB32 >44DE

= =

1010

1011

0011

0100

0100

1101

0010 and 1110

in the destination operand (>44DE), in bit position 15 (least significant bit) the bit is not set (not=1). The COC and CZC instructions are used to compare a word with a mask in order to see if either its one bits correspond or its zero bits correspond. To sum up, the COC instruction is used to determine if the word in a Workspace Register has l's that correspond to the l's in a mask that you specify. Conversely, the CZC instruction is used to determine of the word in a Workspace Register has O's in the bit positions indicated by l's in a specified mask.
-411- . -7 IL.... ID 1G I C- itclk ....

L.

2 .,: I NI E3 11-- IF4'. Li C-.: -T. I C3 1",41 c3

Logical instructions are so named because they operate according to the rules of formal logic as opposed to the rules of mathematics. When dealing with logical instructions it is helpful to think in terms of bits set (=1) as "true" and bits reset (=0) as "false." There are ten instructions that allow you to perform various logical operations on memory locations and/or Workspace Registers. These instructions are outlined along with the status bits they affect in Table 4.9.

TABLE 4.9 LOGICAL INSTRUCTION SET ____________________________________________________________


Status Register Bits (x) indicates bits affected by instruction L> A> EQ C OV OP X INT MASK x x x x x x x x x x x x x x x x x x x x x x x x -

Mnemonic Format
ANDI ORI XOR INV CLR SETO SOC SOCB SZC SZCB (W),# (W) ,# G,(W) G G G G,(G) G,(G) GOB) G,(G)

x
-

THE INSTRUCTION SET

51

( ink Ni r) 1 )

( X COIR )

L.. a G I 10 ina IL. Pr NJ D. X 'CLUB I 14,11 1COS:

Logical instructions are primarily used to manipulate the individual bits of an operand. This is opposed to manipulating an entire group of bits as we will learn to do in later sections of this chapter with "shift" instructions. The ANDI instruction utilizes the rule of logic stated:

If A is true and B is true, then C is true.


Specifically the 16 bit value in a Workspace Register is compared bit-by-bit (ANDed) with an immediate value that you specify. If both bits are "true" (that is =1) than the resultant bit is true (set). This procedure is repeated for each bit, with the resultant value obtained being placed in the Workspace Register. For example, if R2 contains a value of >A3D4, the statement:

ANDI R2,>6C4E
then places the value

>2044 in R2 because:

>A3D4 = 1010 0011 1101 0100 ANDed >6C4E = 0100 1100 0100 1110 with this >2044 = 0010 0000 0100 0100 results in this
Notice how if two "set bits" are compared it results in the setting of the corresponding result bit, however, if the bits do not match the corresponding bit is reset. Table 4.10 is a "truth table" which gives the result of all possible combinations of zeros and ones that can be "ANDed" together:

TABLE 4.10 LOGICAL AND IMMEDIATE


Workspace Register bit Jmmediate operand bit ANDI result

0 1 0 1

0 0 1 I.

0 (T)

0 1

The logical-or immediate (ORI) instruction compares the 16 bit value in a specified Workspace Register with some immediate value. The logical "OR" utilizes a slightly different version of the previously stated logic rule:

If A is true or B is true, then C is true.

THE INSTRUCTION SET

Specifically, the 16-bit value in a Workspace Register is compared bit-by-bit (ORed) with some immediate value that you specify. If either of the two bits being compared is "true" (set to 1), then the resulting bit is also true (set=1). This procedure is repeated for each successive bit with the resulting value being finally placed into the Workspace Register. For example, if R3 holds the value >A3D4, then the statement:

ORI R3,>6C4E
places the value >EFDE in R3 because: >A3D4 = 1010 0011 1101 0100 ORed >6C4E = 0 110 1100 0109 .kilp with this >EFDE = 1110 1111 1101 1110 results in this Notice that if either bit being compared is set (=1), then the resultant bit is also set. If neither bit being compared is set, then the resultant bit is reset (=0). Table 4.11 is a 'TRUTH' table listing the result of all possible combinations of bits that can be ORed together.

TABLE 4.11 LOGICAL OR IMMEDIATE


Workspace Register Bit
0 1 0
1

Immediate Operand Bit


0 0 1 1

ORI result

a
1 1 1

The logical exclusive-or [XOR] utilizes the rule of logic which states:

If either A is true or B is true but not both, then C is true.


The format of the XOR instruction is slightly different then for the ORI and ANDI instructions. The XOR instruction allows the source operand to be specified by any of the general addressing modes while the destination operand must be in a Workspace Register. For example, the statement:

XOR @WORD,R5
exclusive-OR's the contents of memory location WORD with the value in R5. The result of this exclusive-OR operation is then placed in R5. The instruction XOR takes the source operand and
does an

THE INSTRUCTION SET

53

exclusive-OR on a bit-by-bit basis with the destination operand. The result of this operation replaces the destination operand. If either of the two bits being compared is "TRUE" (that is =1), but not both, then the resulting bit is also true (set =1). However, if both bits are reset (=0), or both bits are set (=1) then the resulting bit is reset (=0). For example, if R4 contains >A341 and memory location WORD contains >C5F4, then the statement: XOR @WORD,R5 places the value of >66B5 in R5 because: >A341 = 1100 0101 1111 0100 XORed >C5F4 = 1010 0011 0100 pool with this >66B5 = 0110 0110 1011 0101 results in this Notice that if either bit being compared, but not both, is set (=1) then the resulting bit is also set. If neither bit being compared is set then the resulting bit is reset (=0). Table 4.12 is a 'TRUTH" table listing the result of all possible combinations of bits that can be exclusive-ORed together: TABLE 4.12 EXCLUSIVE-OR LOGIC TABLE First Operand Bit 0 1 0 1 Workspace Register Bit 0 0 1 1 XOR Result 0 1 1 0

The value that results from the logical operations ANDI, ORI, and XOR is compared with zero before being placed in the Workspace Register. The results of this comparison then affect the first three bits (L>, A>, EQ) of the Status Register accordingly. For example, if R3 contains >A3D4 then the statement: ORI R3,>6C4E places the value >EFDE in R3, sets the logical greater than bit of the Status Register while resetting the arithmetic greater than and equal status bits. The following chart combines all three 'TRUTH' tables. This chart summarizes the effects of the three logical operations: 0 0 1 1 ANDI AND 0 AND 1 AND 0 AND 1 = = = = 0 0 0 1 0 0 1 1 ORI OR 0 OR 1 OR 0 OR 1 = = = = 0 1 1 1 0 0 1 1 XOR XOR 0 XOR 1 XOR 0 XOR 1 = = = = 0 1 1 0

54

THE INSTRUCTION SET

This instruction takes the source operand and reverses all the logic bits. It has the effect of changing each zero in the source operand to one, and changing each one to zero. This is referred to as "taking the one's compliment of a number'. The resulting value is then compared with zero and sets/resets the Status Register accordingly. The new value also replaces the source operand. For example, if R3 contains >3EF4 and memory location >3EF4 contains >A6CC the statement: INV R3 places >C10B in R3 and sets the logical greater than, as well as resetting the equal and arithmetic greater than bits in the Status Register because:

>3EF4 = 0011 1110 1111 0100 becomes >C1OB = 1100 0001 0000 1011 on bit-by-bit reversal

CICIL_Fc)

lEA__ETrAF: wollFcn

This instruction changes the source operand (16 bit) to zero. That is, all bits are reset. For example, if R6 contains >3001 then the statement:

CLR *R6+

clears the contents of memory locations >3000 and >3001 to zero. R6 is then incremented by two (word instruction) so R6 now contains the address >3003. Word operations such as CLR operate on the next lower address when an odd address is specified as the operand, since all memory words have to begin at an even address. The CLR instruction does not affect the Status Register.

cls;E:moo

$3E:T. wicuRn

-rot

DINE:

This instruction is the opposite of CLR in that it replaces the source operand with a full 16-bit word of ones. It does not affect any Status Register bits. For instance, the statement:

SETO

@BUFF(R3)

THE INSTRUCTION SET

==

places the value >FFFF at the address found by adding R3 to the contents of BUFF. The SETO instruction is useful to signify the end of a file or in the setting up of flag words. ( EiC)C:: ) E3IEE -11CIIINIFE.:Eis ICIDFRFRF..7.:'.1:31F"CIPAID I 111,4113. . IIAIIIIDIR.:13

This instruction compares two words (16 bits) together. The source operand compares its bits set (1) against the destinaLion operand. All corresponding bits are set in the destination operand regardless of their previous condition. For example, if R3 contains >A3E4 and R4 contains >IC33, then the statement: SOC R3,R4 changes the contents of R4 to >CFF7 because: >A3E4 = >1C33 = >OFF7 = 1010 1001 1011 0011 11 00 1111 1110 11 1111

00

0100 source operand pou destination operand 0111 resulting destination operand

This instruction will set the logical greater than bit of the Status Register and reset the equal and arithmetic greater than bits. Notice that the SOC instruction is really an OR operation that can operate on two operands through any general addressing mode. ( BOIC::1E.c ) BEIT -11CDIONIEE:E; C..":1DIR 1:::-4'. 1E7.. E3 F " C:1 NI ID. :lc IN1C3 ., .
Ery -.11- EI:

This instruction compares the source operand (byte) with the destination operand (byte). It is an OR operation in that if a bit is set in the source operand the corresponding bit is set in the destination operand. The result of this bit-by-bit comparison replaces the destination operand and is then compared with zero. The Status Register bits are set/reset to reflect the results of this comparison. If a word of memory is specified as one of the operands, only the most significant byte (bits 0-7) are OR'ed together. For example, if R3 contains >AA33 and memory location BEST contains >F731, then the instruction: SOCB R3,@BEST places the value >FB31 at location BEST and sets the logical greater than and odd parity status bits while resetting the arithmetic and equal status bits because:
>AA33 =

>FC31 = >FB31 =

1011 1111 1111

1010 1011 1011

0011 0011 0011

0011 source operand 0001 destination operand 000 resulting destination operand

56 THE INSTRUCTION SET

(e.- zic) edE:ir zuFRIDE3 (7ADI:F.c -Jmnir4c3, wpm)


This instruction compares the O's in a source operand (word) with the 0's in a destination operand (word). If a zero bit corresponds then it is not affected. If a zero bit in the source operand corresponds with a one bit in the destination operand, then that bit is reset to zero. The result of this operation is placed in the destination operand. The result is compared with zero and the status bits are set/reset accordingly. For example, if R3 contains >2133 and R4 contains >3399, then the statement:

SZC R3,R4
places >2111 in R4 and sets the logical greater than, arithmetic greater than status bits while resetting the equal status bit because:

>2133 = >3399 = >2111 =

0010 0001 0011 0011 source operand 0011 0011 1001 1001 destination operand ow gool pogl ppoA resulting destination operand

Notice that if the source operand bit is zero it resets the corresponding destination operand bit. This is a logical OR operation dealing with zeros instead of ones. The opposite of the SOC instruction.

(ESZtOrii) BEECT" 2711EF;;A:09; ICADFRRAEEIF - CANIE), IMCJi, E01(11-

This instruction compares the 0 bits in a source operand (byte) with the 0 bits in a destination operand (byte). If a zero bit corresponds then it is not affected. If a zero bit in the source operand corresponds with a one bit in the destination operand, the destination operand bit is reset to zero. The result of this operation is placed in the destination operand. The resulting binary number from this operation then replaces the destination operand. It is compared with zero and the results of this comparison set/reset the status bits accordingly. For example, if R11 contains the value >2001, location >2001 contains >7D, and location MASK contains >90, then the statement:

SZCB @MASK,*R11

results in the contents of memory location >2001 being changed to >11 and the logical greater than, arithmetic greater than status bits being set while the equal bit being reset because:

MASK = 1001 0000 source operand >7D = 0111 1101 destination operand >11 = 0001 0000 resulting destination operand

THE INSTRUCTION SET E3 I-1 F-7 .1r.

57

I NJ E3

"T" 01 Ei;

Where as logical instructions allow you to manipulate individual bits, Shift instructions allow you to manipulate entire groups of bits. There are four instructions that allow you to shift the contents of a Workspace Register one or more bit positions to the left or right. With all four shift instructions the carry status bit (C) holds the value of the last bit shifted out of the register. For example, if a Register is shifted to the right 6 bits, and the sixth bit is a '1', the carry bit in the Status Register is set. Shift instructions can be divided into two groups; Logical shift instructions and arithmetic shift instructions. Logical shift instructions displace an operand without regard for its sign. They are used on unsigned numbers and non-numbers such as masks. Arithmetic shift instructions preserve the sign bit. They are used to operate on sinned numbers. All four shift instructions require two operands; a Workspace Register containing a sixteen bit word and a shift count. The count may be any number from 1 to 16. Table 4.13 outlines the shift instructions and indicates which status bits are affected.
TABLE 4.13 SHIFT INSTRUCTIONS

Status Register Bits (x) indicated bits affected by instruction Mnemonic SRA SLA SRL SRC 9Fc.(-4
IL_ (-4 )

Format (W),# (W),# (W),# (W),# 9fr -II


A-1 1:71:.

L> A> EQ C OV X INT MASK

X X X X
13 I-1

X X X X

X X X X
AIR'. IR:

X X X X

X -

I= F.."

L._ IE..

-111-11101

112: :I IC:

These two instructions shift signed numbers. The SRA instruction preserves Lhe sign by replicating the sign bit throughout the shift operation. The SLA instruction on the other hand does not preserve the sign bit, but puts a 1 in the overflow bit of the Status Register if the sign of the number changes after the shift operation. With each bit position shift using SLA, the vacated bit positions are replaced with zeros. When using shift instructions the first operand is the word to be shifted. The second is the number of bits to be shifted (shift count) which ranges anywhere from 1 to 16. If the shift count in

58

THE INSTRUCTION SET

the instruction is zero, the shift count is taken from Workspace Register RO; bits 12 through 15. If bits 12 through 15 in RO are all zero then the shift count is 16 bit positions. If a shift count is specified that is greater than 15, then the value is placed in RO and the least significant four bits are taken as the shift count (bits 12-15). If you specify 0 as the shift count the shift count is 16 bit positions. For example, the statement:

SLA R2,4
shifts R2 left four bit positions, if the sign changes the overflow (DV) bit of the Status Register is set. After a shift takes place, the result is compared with zero and the Status Register bits are set/reset to reflect this comparison. The following are examples of arithmetic shift operations: 1. If R3 contains >12F3 then:

SLR R3,1
places a value of >25E6 in R3 and sets the logical greater than and arithmetic greater than status bits while resetting the equal, carry, and overflow status bits because:

>12F3 = 0001 0010 1111 0011 R3 >25E6 = 0010 0101 1110 0110 R3 result (all bits shifted left 1 bit)
n

If R4 contains >FA97 then:

SLA R4,5
places a value of >62E0 in R4 and sets the logical greater than, carry, and overflow status bits while resetting the equal status bit because:

>FA97 = 1111 1010 1001 0111 R4


... - -^

>62E0 = 0101 0010 1110 0000 R4 shifted left 5 bits


Note sign change (hit 0), and that the fifth bit shifted out is a one so the carry and overflow bits of the Status Register are set.

3.

If R5 contains >6CFD

and RO contains :::F7 FA then:

SLA

R5,0

THE INSTRUCTION SET

59

places a value of >F400 in R5 and sets the logical greater than, carry, and overflow bits of the Status Register, while resetting the arithmetic greater than bit because:

>6CFD = 0110 1100 1111 1101 R5 >F400 = 1111 0100 0000 0000 R5 LEFT SHIFT >A BITS.
4. If R6 contains >B690 and RO contains >A3B0 then:

SRA R6,0
places a value of >FFFF in R6 and sets the logical greater than, and carry status bits while resetting the arithmetic greater than and equal status bits because:

>B690 = >FFFF =

1011 1111

0110 1111

1001 1111

0000 R6 1111 R6 right shift 16 bits sign bit replicated

(*. B F.:

IF-1 I IF7

I C5- I-1"T L.. C3 10 I C: le; L...

This instruction shifts unsigned numbers to the right. The vacated bits are filled with zeros. The carry bit of the Status Register holds the value of the last bit shifted out. The shift count is specified in the same manner as with the SRA and SLA instructions, that is if 0 is specified as the shift count, the shift count is taken from bits 12-15 of RO. If these bits equal 0, then the shift count is 16. The result of the shift is placed in the Workspace Register and compared with zero. The Status Register is set/reset to reflect the results of this comparison. The following are some examples of the SRL instructions usage: 1. If R3 contains >FFFF, then the statement:

SRL R3,6
places the value )03FF in >R3, sets the logical greater than, arithmetic greater than, and carry status bits while resetting the equal status bit because:

>FFFF = 1111 >03FF = 0000

1111

1111

1111 R3

0011 1111 1111 R3 shifted right 5 bit positions

If R4 contains >731F, then the statement:

SRL R4,456

60

THE INSTRUCTION SET

has a shift count of

8 because:

R0.= 456 = 0000 0001 1100 1000 ---- last 4 bits = 8 The logical and arithmetic greater than status bits are set, while the equal and carry bits are reset. ir,:".F.,. '.C.-- ) % '
Ei; 1-11 I IF- -11FR I C-3, 1-11 --IF C.: I F-R.' IC Li L._ At IR

This instruction shifts the contents of a Workspace Register to


the right a specified number of bit positions. The displaced bits are then used to fill the vacated bit positions on the left. The carry status bit contains the value of the bit shifted out of bit position 0 (sign bit with signed numbers). The resulting value is then placed in the Workspace Register. It is compared with zero and the status bits are set/reset to reflect the results of this comparison. For example, if R2 contains >EC62, then the statement:

SRC R2,6
results in the value >BBE41 being placed in R2. The logical greater than, and carry status bits are set while the equal and arithmetic greater than bits are reset because:

>EC62 = 1110 1100 0110 0010 R2


-------------

>8881 = 1000 1011 1011 0001 R2 shifted right 6 bits


Note that this instruction fills vacated bit positions with the bits shifted out of position 15. In this example the bit shifted out of bit 0 was one, so the carry bit in the Status Register is set. There is no "Shift Left Circular" instruction because the same effect can be accomplished with SRC. To shift left a specified count simple shift right a count equal to 16 minus the number. For example, to shift left circular 9 bits use the statement:

SRC R2,16-9 or SRC R2,7


The shift instructions also can be used as fast-executing multiply and divide instructions. For instance, shifting the operand one bit position to the left doubles its value (multiplies by 2) and shifting the operand to the right one bit position halves its value (divides by 2). The following shift instructions show you how to multiply or

THE INSTRUCTION SET


divide the contents of a Workspace Register by 4:

61

SRL R5,2 SRC R5,16-2 SRA R5,2 SLA R5,2

* * * *

DIVIDES UNSIGNED NUMBER BY 4. MULTIPLIES AN UNSIGNED NUMBER BY 4. DIVIDES A SIGNED NUMBER BY 4. MULTIPLIES A SIGNED NUMBER BY 4.

These shift procedures can save you considerable program execution time when multiplying or dividing numbers. Each shift operation takes a fraction of the time to complete then does a DIV or MPY instruction. Of course there are limitations, you can only multiply or divide with the shift instructions using multiples of two. You can get around this obstacle by juggling some registers. For example, to multiply the contents of R3 by 10, use the following sequence of instructions:

MOV SCR A SRC

R3,R4 R4,16-2 . R3,R4 R4,16-1

* * * *

Put a copy of R3 in R4. Shift R4 by 14 (multiply by 4). Add original R4 (multiply by 5). Shift R4 by 15 (multiply by 10).

This is the same as:

E(R3*4)+(R3)3*2=R3*10
This instruction sequence involves four steps as opposed to the simple instruction sequence:

LI MPY

R4,10 R3,R4

which only requires two sLeps. However, the former sequence is almost three times faster then the single MPY instruction! 41
-

ic?

11=" $.9; Ia. Li 1.3

---

14,11 9 -Ir. FZ.

C: "T. :I tEL1.1

..F.3

As mentioned in earlier sections, pseudo-instructions are not really machine language instructions, but rather provide some direction to the assembler as to what to do under certain circumstances. There are two pseudo-instructions that are outlined below in Table 4.14:

TABLE 4.14 PSEUDO INSTRUCTIONS


-

Mnemonic NOP RT

Description No operation Return ---------------

62

THE INSTRUCTION SET

The NOP pseudo-instruction performs no operation when run. It only serves to slow the execution time of the program. No operands are specified and the Status Register is unaffected. The NOP pseudo-instruction is most often used with the minipemory assembler to allow you to leave "holes" in your code that you may want to come back later and fill with some additional instructions.

This instruction tells your computer to return back to a calling program from a subroutine called up by a BL instruction. For example, the instruction sequence:

line# >0001

Label MAIN

OP-C Operands Comments . . BL . . .

>0200

@SUB1

>0201

START

* Branch to location SUB1 and store * Return address of next * Instruction in R11.

>0800 >0E105

SUB1 .
RT

* Beginning of subprogram SUB1.


*

Go back to location START.

branches to location SUBP, carries out a sequence of instructions and then returns via the RT to the point just after the BL instruction (in this case we would return to location START). When the RT instruction is specified the assembler supplies the logic code for the following:

B *R11
Remember that when control is transferred by a BL instruction, the link to the calling routine (the Program Counter setting just after the BL instruction) is placed in R11. The RT pseudoinstruction returns control of the program to the instruction following the BL command. Do not alter R11 unless you first_ save the address somewhere. Do not forget to reload the address in Rll before RT or there is no telling where you will end up!

THE INSTRUCTION SET 63

CHAPTER 4 STUDY EXERCISES

1.

Construction an instruction sequence that will multiply a number by 12 using only shift instructions. Where is the return address stored when a BL (Branch & Link) instruction is called? How far can a "jump" be specified in your program? The sole purpose of the Status Register is to provide information on which decisions are based to what group of instructions? What pseudo-instruction is used in combination with the BL instruction? Identify the addressing mode used in each of the following examples: (a) (b) MOVB R1,*R2 A *R1+,R2 (c) C @OA,@VALUE1 (d) MOV R6,@NUM1+S(R2)

2.

3. 4.

5.

6.

5 ASSEMBLER DIRECTIVES
As we have mentioned before, the purpose of the assembler is to convert your source code into the appropriate object code. That is, the assembler program takes your opcodes and their operands, translates them into the appropriate binary numbers, and places them in memory for you. This is the assembly process in its simplest form. By providing some additional commands you can "teach" the assembler program to assist you in creating your assembly program. This is where Assembler Directives come in. They are not part of the computers instruction set. They are directions for the assembler to follow during the assembly process. Sometimes they are referred to as "pseudo-instructions" as are NOP & RT, but for now we will put them in a distinct category and refer to them separatly as assembler directives. There are 28 separate directives that are available, however with the assebler and loader we are using only 22 directives are useful. These will be the ones that we will discuss. The directives can be divided into 5 separate groups based on their functional similarities.

-65-

66

ASSEMBLER DIRECTIVES

The assembler directives can be divided into the following 5 functional groups:

1.

LOCATION COUNTER DIRECTIVES.

These directives affect the location counter in some way. The location counter is the pointer that determines where the assembler is in the assembly process. It keeps an orderly flow of where data and/or instructions are stored in the memory.

2.

INITIALIZE CONSTANT DIRECTIVES. These directives let you define symbols. It allows you to assign a symbolic name to an expression. You can also directly define words & bytes. PROGRAM LINKAGE DIRECTIVES.
These directives allow you to link different assembly program modules together into one long program. This feature can greatly simplify program development. These directives allow you to define extended operations. They also allow you to define the end of your program.

3.

4.

MISCELLANEOUS DIRECTIVES.

5.

ASSEMBLER OUTPUT DIRECTIVES.

These directives allow you to change the assembler output in order to make it easier to read, such as page lengths, page titles, program idenLifiers, ect.

L..... C3 4:::::: e:41 -I* I Cli NI

4:::: CD til INI1 -11- E.::::: FR

r..) 1: Fi. ". El: C::: -I- I "1/41 E:::: lEi; *

The location counter

is the pointer that determines where the assembler stores instructions or data in memory. It sequentially follows the steps in the source listing as it converts it into the object listing. There are 6 useful directives for altering the location counter.

Table 5.0 LOCATION COUNTER DIRECTIVES Mnemonic


--.

Directive
. .

Format
---------------------------

AORG RORG DORG BSS BES EVEN


---------.....

Absolute ORiOin Relocatahle ORiGin Dummy ORiGin Block Starting with Symbol Block Ending with Symbol Move to a Word Boundary

word(expression) expression expression word(expression) word(expression)

-------------------------------------------------------

ASSEMBLER DIRECTIVES (ADFCG) PhEiBOILMIEI (73F<IGIP4

67

When the assembler reaches a AORG directive, the location counter is altered to store the object code for subsequent instructions starting at the location specified by a word. For example if X=7, then the source code statement:

LABEL AORG

>D000+X

sets the location counter to >D007, and LABEL is assigned the value >D007. With the Editor/Assembler you normally let the computer make the placement decisions but AORG gives you the option of making these decisions yourself. When using the Line-by-Line Assembler with the Mini Memory Module you will use the AORG directive quite frequently to move through various memory locations. See chapter 10 section 10.1 for further details. (F;:01FR 10) -

IFZIEFIVE: DIRIBINI

You may locate object code relative to the current active storage location in memory. The RORG places a value in the location counter which, if encountered in absolute code, also defines succeeding locations as program re-locatable. The dollar sign ($) symbol refers to the current value of the location counter. The statement:

LABEL RORG $ 40
-

overlays the last 20 words (40 bytes) by backing up the location counter 20 words. LABEL is assigned the value that is placed in the location counter. You may never have occasion to use AORG and RORG in your own programs (provided you are not using the MMM), but you'll encounter them if you ever delve into listings of system programs. For this reason you should know what AORG and RORG do. (13101FZIGi)

DUMM'Y DIF;cIBINI

This direct:lye places a value in the location counter and defines the following address locations as a dummy block or section. (F4E39) Eci_DCZA< CIF'

F3IFIPIII

MIFEMIL WITAA e'VMEICJIL-

The BSS directive allows you to reserve an area of memory for future use. If a Label is used it is assigned the location of the first byte in the block. it does this by advancing the location

68

ASSEMBLER DIRECTIVES

counter by the value specified in the expression. You reserve memory for use to set up reference tables, arrays, ect. The following code reserves a 32 byte area of memory for your 16 Workspace Registers:

MYREG BSS

32

If the AOR5 directive is to be used in your program, it must precede come before you use any BSS directives.

(EKE3)

muEriciwy
EEtNinir4c3 8 .ymEcc3L__
NM

This directive is similar to that of the BSS directive in that it reserves a block of memory by advancing the location counter by the value specified in the expression. The label is assigned the location of the last byte in the block. For example, if the location counter contains ';-2n0 when the assembler processes the statement:

BUFF BES

>30

BUFF is assigned the value >230 and a 48 byte area of memory is reserved. The BES directive can be used to mark the end of a block started with the BSS directive. For example, when the assembler processes the statements:

BUFF1 BSS 10 BUFF2 BES 10


a 32-byte buffer (memory area) is set beginning at location BUFF1 and ending at location BUFF2.

icE.T.vrEiNto

lorA

wcwzr>

..ocluNinemR-sy

All words in memory begin at an even address. EVEN is a directive that can force the location counter to point to an even address. If the location counter is already at an even address then the directive is ignored, but if the counter is at an odd address, EVEN causes the assembler to jump to the next even address. For example, if the location counter points to address >3001, an EVEN directive makes it point to >3002. The only time you wou)d need to use the EVEN directive would be to ensure that a statement consisting of only a label is at an in word boundary after a TEXT or BYTE directive.

TEXT 'HELLO' EVEN DATA >88AF

ASSEMBLER DIRECTIVES

69

You do not need to use an EVEN directive instruction or a DATA directive because the automatically advances the location counter when it processes machine instructions or a

after a machine assembler to an even address DATA directive.

You can avoid much of the hassle of having to use the EVEN directive by simply not specifying a statement consisting of only a label after a TEXT or BYTE directive.

173 I Ft: FE. IC 11- I "1/41 IE 9 -

-11- IHI inh 11"

IrAI -T- I.AL.I2: E.- IC a INJI 9 -11- dcb rA -11- 9

These directives allow you to define the values of constants and place the values in bytes or words of memory. Table 5.1 outlines the directives that initialize constants along with their mnemonics and formats:

TABLE 5.1 DIRECTIVES THAT INITIALIZE CONSTANTS


Mnemonic EQU DATA BYTE TEXT

Directive
Define assembly-time constant (EQUate) Initialize BYTE Initialize WORD Initialize TEXT

Format
expression exp,exp...exp exp,exp...exp 'string'

IC IE. D. 1.11 3

E:: Ca Li ir4 -T- IE.

I:3 Faib.

f 1. ini ea.

f= 4=11

ir-s ,. -I: .at. ini -t: ...

This directive assigns a value to some symbol. The label field contains the symbol that you assign. Once you assign the symbol you may use it anywhere you would normally use the expression. The EQU directive can be used to define a symbol for a 16-bit constant, or another symbolic name. Some examples of the EQU are:

JOYX UP

EQU >8376 * Constant EOU JOYX * Another symbolic name.

You can also specify an index reference through some juggling of the EQU directive like so:

MYREG R1HB R1LB

EQU EQU EQU

>8300 * My own workspace area begins here. MYREG+2 * Value in high byte of R1 addr. >8302. MYREG+3 * Value in low byte of R1 addr. >8303.

Here we see the individual bytes of a Workspace Register reference through the use of a symbolic equate directive.

70

ASSEMBLER DIRECTIVES IN1 "T CAI_ Z IE: Ec"1/4fer*TEE )

This directive can place one or more values in successive bytes of memory. When you specify a label it is assigned the location which the first byte is places at. Each expression is evaluated individually as a signed two's compliment 8-bit number. The following statements show the allowable maximum and minimum values for byte-size variables, in decimal:

* Maximum byte constant, unsigned. BUMAX BYTE 255 * Maximum byte constant, signed. BSMAX BYTE 127 BSMIN BYTE -128 * Minimum byte constant, signed.
You can also allow the assembler to calculate the value of a constant as in the following example:

HERE BYTE >F+4,

1, 34+>12,>10/8,'A'
-

which initialize five bytes of memory starting with the byte at location HERE. The contents of five successive bytes are >13, >FF, >F0, >02, and >41. The EVEN directive is often used after the BYTE directive when a DATA or TEXT directive is next in the source code. This is to assure that the next directive begins at an even word boundary.

11 4:11)

I AIL_ I Z. EE

011R. 13

This directive only differs from the BYTE directive in that it can place one or more successive values in 16-bit word locations. Each word is evaluated as a signed two's compliment 16-bit number and, if necessary, places a value of >00 in any bytes not filled. The followed statements outline the maximum and minimum values for word-size variables, in decimal:

WUMAX DATA 65535 * Maximum word constant, unsigned. WSMAX DATA 32767 * Maximum word constant, signed. WSMIN DATA -32768 * Maximum word constant, signed.
Again, it is possible to let the assembler calculate some of the values of the constant as in the following example:

HERE DATA

1+>F3,3121+ C,'AB'

which initialize three words of memory beginning at location HERE. The conLents of the three successive words are >00F4, >F01, 4142. The BYTE and DATA directives can be used to set up in memory. To do this simply list the table elements them with a comma. The following sequences of source two 20-element tables, one comprised of bytes and Lhe a data table and separate code set up other

ASSEMBLER DIRECTIVES

71

comprised of words:

SOUND1 EQU BTABLE BYTE BYTE BYTE SOUND2 EQU WTABLE DATA DATA DATA

>34 0,0,23,32,43,23,-12,45 36,-120,>3A,'AB',-'DX' 64,>A,45,0,3,7*5,SOUND1

(BYTE TABLE)

>35 >3025,>FFAB,-4356,0,23,-34 >4567,->35,'VC','G'-4,>5523 (WORD TABLE) >2332,>23,0,5*>34,36,1,34,SOUND2

The text directive allows you to define a character string as an expression. The string characters are stored in successive bytes of memory as their ASCII hexadecimal egivalents. The string may be up to 52 characters in length. You may precede the string with a urinary minus (-) sign in which case the last character of the string is negated. When a label is used its location is the first byte in the string. The string must be enclosed in single quotes as shown here with two possible error messages outlined:

NICE TEXT THAT NUMBER IS TOO LARGE. TEXT 'PLEASE RE-ENTER IT.' RUDE TEXT 'TRY IT AGAIN, STUPID'
The bytes are filled sequentially by the assembler when processing a TEXT directive. So if 4_he assembler is on an even address when it starts to execute the following directive,

MESG TEXT 'HELLO'


the result is >4845, >4C4C, and >4F-- with (--) being determined by the next source statement. For this reason the EVEN direcLive usually follows a TEXT statement to insure that the next instruction starts at an even word boundary.

IF" F:C.31 11.73 IR fr-211 11'1

it_ I PA F.::

ff.:4

1E3 IEEE

ID 1: IR E.: CT:: -1- I

".%)1

ET: 1:7-1

Program linkage directives allow you to Lreate programs as separate modules which you later connect together to form one long program. There are a total of five directives that are available to allow you to link programs, however, only three of them can be used with the loader provided with the assembler. These will be the ones we will discuss in depth in the sections that follow.

72

ASSEMBLER DIRECTIVES

Table 5.2 outlines the directives that allow you to link programs along with their mnemonics and required formats: TABLE 5.2 DIRECTIVES THAT LINK PROGRAMS Mnemonic DEF '
REF

Directive
External DEFinition External REFerence

Format
symbol,symbol symbol,symbol symbol symbol

Copy

Copy

"File Name"

<

la X 7- EE F: IPA IA

:11.)

NI I *T"

The DEF directive allows you to makes one or more symbols available to other programs for reference. The DEF directive can be thought of as supplying "entry" points into the program for other programs. The DEF directive must precede the object code that contains the symbols to be defined. For this reason the DEF directive is usually at the beginning of the source code. The following statement shows an example of the usage of the DEF directive:

LABEL, DEF START,SLOAD


This statement will cause the assembler to include the symbols START and SLOAD in the object code so that these symbols are available to other porgrams. If a label is specified, it is assigned the current value of the location counter.

11=7

E: X 11" E.7 F:

F: IE.: Fr: E.: F: E7.

The REF directive allows you to have access to one or more symbols defined in other programs. The REF gives you the location of where "entry" into another program is to take place. For instance, the statement:

LABEL REF START,SLOAD


causes the assembler to include the symbols START and SLOAD in the object code so that the corresponding address may be obtained from other programs. If a symbol is listed in a REF directive inside your program, then the same symbol must be present in the DEF directive of the program that you are trying to link with

This directive will fetch a file from a diskette during the

ASSEMBLER DIRECTIVES

73

separate source file in the assembly process as if it were a series of source statements in the program. The assembler continues right on through. You can use as many COPY directives in a program as you want but if an END directive is encountered the assembly process ends. This happens no matter if the END directive is in the file called up or part of the original program. The following statement is an example of the COPY directives use: LABEL COPY "DSK1.8AME1" COPY "DSK1.GAME2" COPY "DSK2.GAME3" END This last example will first copy the file GAME1 from disk drive 1 into the computer in order for the assembler to assemble it. It then loads file GAME2 from disk drive one and keeps right on assembling it. Finally, file GAME3 is loaded from disk drive two and it is assembled. The assembler then reaches the END directive and the assembly process stops. The main use of the COPY directive is to allow you to write programs as separate modules which can then be assembled together. You may want to do this for writing convenience or because the source program is too long to fit on one file.

:r

IS, '

ID I. Fir.1E:C::11-

'1/4./1E:E3

The two miscellaneous directives are the Define eXtended Operation directive (XOP) and the END directive. The miscellaneous directives are outlined in Table 5.3 below: TABLE 5.3 MISCELLANEOUS DIRECTIVES Mnemonic Directive Format

XOF Define extended OPeration symbol,term END Program END symbol -, -----------------------------------------------------------------C X DP* EE F.:" I NI FE EL: X -11- t1/44 F.) 1E: t,"- 1E: IR. onh I- (3 INJ

This directive can only be utilized on the TI-99/4A Home Computer. The DXOP directive will assign a symbol to be used in the operator field to specify an extended operation.

!NJ 11:3 )

E: I) IF" Fc. 13 R".

ET. X

If; "T" 3: C.)

The END directive causes the assembly proce s s to stop. The last source statement you put into your program should be an END statement to signify to the assembler that this is her you want the program to end. lf you specify a label it is assigned the current value in the location counter.

74

ASSEMBLER DIRECTIVES

You can specify and entry point into the program by placing a symbol in the operand field of an END directive. If this is done the program will automatically begin running as soon as it is loaded into the computer. For example, the statement:

END START
will cause the program to begin running immediately upon loading starting at address START. If an operand is not specified in the END directive, then you must define the entry point with a DEF directive and type in this entry point in response to the 'PROGRAM NAME' prompt you receive after loading the program using the Editor/Assembler. If you are using the Line-by-Line Assembler with the Mini Memory Module to program in assembly language the END directive will cause you to exit the assembler. See chapter 10 for more detailed information.

..-.._^ niFiriviE.:s.- mencr .r), pkE3BIE:myEt


There are 5 different directives that you can use to affect are assembler output. You may on occasion want to alter the assembler output in .order to make the object and/or source code more readily readable. Table 5.4 outlines the five directives that affect the output of the assembler:

TABLE 5.4 ASSEMBLER OUTPUT DIRECTIVES


Mnemonic UNL LIST PAGE TITL IDT

Directive
DoNot List Source List Source PAGe Eject page TITLE program IDenTifier

Format

'string' 'string'

CIL_I9.-T3 L_IE3 -T

4 SCAJII , BIEDUF

our4L_) nolv4ocr. L_IBm

These directives have no effect on the assembler unless you have specified a listing to an output device with the L option of the Editor/Assembler. If you have specified a list file option then the UNL directive will halt the output to the file device such as list file or printer. The UNL directive in not printed out and any source statements following it are not printed.

ASSEMBLER DIRECTIVES

75

The LIST directive may be used after a UNL directive to resume printing to an output device such as a list file or printer. The list statement is not printed, but the location counter is incremented and the listing begins with the next source statement. To summarize the UNL and LIST directives are used to stop and start output by the assembler to a list file device such as a disk drive or printer.

( FIPkeiE:: >

F" int IS

IE: E..._: a FE lc; -r :

This directive causes the assembler to start printing the source listing (provided the L option has been selected) on a new page. If a label is specified it is assigned the current value of the location counter.

The TITL directive will print a heading (provided the L option has been selected) on each subsequent page of the source listing. For example, the statement:

TITL 'PROGRAM FOR PRINTING AMORTIZATION SCHEDULE'


prints the heading: "PROGRAM FOR PRINTING AMORTIZATION SCHEDULE" on the top of each page of the program listing. The title may be up to 50 characters on length after which the message "OUT OF RANGE" is printed and the title is truncated to the first 50 characters.

( I :DT- >

F"F4'..' Di 1:3111R:. rql 1.1

1: :11DEEP1/411 -1- r F.,.. I IE::::F-; s:'


:

The IDT directive assigns a name to the program. It is printed in the source listing but serves no other purpose during the assembly process. The name is limited to 8 characters in length after which a "TRUNCATION" error is displayed. If a label in specified it is assigned the value of the current location counter.

76

ASSEMBLER DIRECTIVES

CHAPTER 5 STUDY EXERCISES


1. If R1 contains >123A and R2 contains >456c, list the contents of R1 after each of the following statements is executed:

(a) (b) (c) (d) (e)

AND R2,R1 OR R3,R1 XOR R2,R1 MOVB R2,R1 SLA R1,2

2. What does this sequence do?

START MOV INC DEC JED

40,R3 R6 R3 OUT

3. Write some statements (two lines should suffice) that will store the contents of R3 into a word location called SAVE. 4. What does this instruction do?

MPY >23FF

UTILITY PROGRAMS
In your computer there exists two distinct areas of random access memory (RAM). The first is termed CPU RAM (Central Processing Unit RAM) and is readily manipulated by you. The second is VDP RAM (Video Display Processor RAM) and is more difficult to manipulate because it is memory mapped. When you are putting something on the screen, describing sprites, or writing to the sound table you are actually writing to the VDP RAM. Normally it would be difficult to read and write to the VDP RAM areas because in order to read data you would first have to write a value to a specific address, wait while the data is obtained and then read the data from another address. To write data to VDP RAM the opposite process occurs, namely you place the data in a specific address, write a value to another address to signify that the date is to be written, and then wait while the data is written. This requires an in-depth knowledge of the addresses to use, as well as how to use them. Fortunately, you have ready access to certain utility programs that allow you to write and read easily to and from the VDP RAM. The following is a listing of utility programs available to you. All utility programs needed by your program must be referenced in a REF statement at the beginning of the source code unless you are using the Mini Memory Module with the line-by-line assembler in which case you should refer to chapter 10.

-77-

78

UTILITY PROGRAMS

Table 6.0 outlines the utility programs that are available to you along with a description as to what they do:

TABLE 6.1 UTILITY PROGRAMS Symbol VSBW. VMBW VSBR VMBR VWTR KSCAN GPLLINK DSRLNK XMLLNK Name
VDP Single Byte Write VDP Multiple Byte Write VDP Single Byte Read VDP Multiple Byte Read Write to VDP Register Keyboard SCAN Graphics Programming Language Link. Device Service Routine Link Extended Memory Language Link

Description
Copies a single byte from CPU RAM into VDP RAM. Copies Multiple bytes from CPU RAM into VDP RAM. Copies a single byte from VDP RAM into CPU RAM. Copies multiple bytes from VDP RAM into CPU RAM. Copies a single byte from CPU RAM into a VDP register. Scans the keyboard and joystick for input and returns it. Links your program to Graphic subroutines that you can use. Links your program to peripheral devices. Links your assembly program to ROM and RAM routines.

vipp.

Ervir

This utility allows you to place a single byte in VDP RAM. You place the VDP RAM address you want to write to in RO. You place a copy of the byte you want to write in the most significant byte of Rl. You then call the utility. For example, to place >05 at VDP RAM address >0040, you would use the following source code:

REF VSBW LI RO I >0400 LI R1,>0500 \ BLWP @VSBW

UTILITY PROGRAMS

79

civr-ma44)

NoPIDIF-

mulL_ -riF

Eiv -ria

WFCITE

This utility program allows you to copy any number of bytes from an area of CPU RAM into an area of VDP RAM. The Block Starting with Symbol (BSS) instruction is usually used to reserve the CPU RAM to hold bytes prior to transfer. To use the VMBW utility, place the VDP RAM address you wish to start writing to in RO. Place the starting address of the information in CPU RAM that you wish to copy in Rl. R2 is then loaded with the number of bytes to copy. The utility program is then called. For example, the following source code:

REF VMBW . BUFFER BSS 32 . LI LI LI BLWP R00.0300 R1,BUFFER R2,32 @VMBW

copies the 32 bytes located in BUFFER into VDP RAM starting at VDP address >0300.

(wBEtiFc) %/DR. 8'1.4

E4V -Tla

Fdapkup

This utility allows you to copy a single byte from an address in VDP RAM into CPU RAM. You do this by placing the VDP address you want a copy of in RO. Then when the utility is called, the value at that address is placed in the most significant byte of Rl. For example, if VDP address >0300 contains the value >FF, then the following statements:

REF VSBR . LI R0,>0300 BLWP @VSBR


places a value of >FF in the most-significant byte of Rl.

cwriEcFR) wrw, mult_irIvq_la Eryria

IRlischn

This utility allows you to copy any number of successive bytes from VDP RAM into CPU RAM. Load RO with the starting address in VDP RAM that you want to start copying from. Load R1 with the CPU address that you want to copy into. You load R2 with the number of bytes to be copied. You then call the VMBR utility.

BO

UTILITY PROGRAMS

For example, if you want to copy 40 bytes from VDP RAM beginning at address >0780 into CPU RAM beginning at address BUFFER, you would use the following source code: REF VMBW BUFFER ;SS >28 . LI LI LI BLWP RO,>0780 R1,@BUFFER R2,>28 @VMBW

(vtArriR) wiFicure..

-Irca vnip sizzioie -r- IE:Fc

This utility allows you to change the contents of the VDP Workspace Registers. You place the value you want the VDP register to be in the least-significant byte of RO. The most significant byte of RO is loaded with the VDP register you want to change. For example, the code: REF VWTR

. RO,>02CE LI BLWP @VWTR places a value of >CE in VDP register 2. NOTE: When changing VDP register 1, place a copy of what you are changing it to at CPU RAM address >83D4. You have to do this because the value at this address is loaded into VDP register R1 when a key is pressed after the screen has "blacked-out" which it does if no key is pressed for a long period of time.

(KirAIA) KlavnipAIRD

(4&./

This utility allows you to check the keyboard and joysticks for input. It also returns the ASCII value of the key that was pressed or the position of a specified joystick. On the next page is Table 6.2 which presents the CPU RAM addresses used by the KSCAN routine.

UTILITY PROGRAMS

81

TABLE 6.2 ADDRESSES USED BY KSCAN UTILITY Address Description >8374


Placing a value here selects the keyboard device to be checked. The following values are allowed: >00 -- Causes entire keyboard to be checked. >01 -- Causes the left side of the keyboard and input from joystick #1 to be checked. >02 -- Causes the right side of the keyboard and input from joystick #2 to be checked. >8375 This byte holds the ASCII value of the last key pressed. If no key was pressed, then this address contains a value of >FF. Holds (V) position of joystick input. Holds (X) position of joystick input. Status byte. If a key is pressed then bit 2 is set.

>8376
>8377 >837C

If your program contains a keyboard scanning loop and your program needs to enable interrupts (to move sprites, create sound, ect.) the key scanning loop is an excellent place to do so. The following is an example of how to structure the key scanning loop so that interrupts may be enabled:

REF . . LOOP LIMI 2 LIMI 1 BLWP @KSCAN


. .

* Reference needed utility program. * Enable interrupts * Disable interrupts * Call utility program to scan keyboard.

A keyboard status byte is located at CPU address >837C. It gives certain status information based on keyboard input. It can be used in combination with a compare ones corresponding (COG) instruction to determine if a key has been pressed. Bit 2 of the status byte is set if a pressed key is detected during execution of the KSCAN utility. The following source listing on the next page can be used to detect a pressed key.

82

UTILITY PROGRAMS

REF

KSCAN

* Reference needed utility.

SET DATA EQU

>2000 >837C

* Binary 0010 * * * * * *

0000

0000

0000.

GETKEY BLWP MOV COC JNE

@KSCAN @STATUS,R3 @SET,R3 GETKEY

Call up utility program. Move status word into R3. Check and see if bit 2 is set. If no key pressed loop again.

An alternative method of checking to see if a key has been pressed is to check address >8375 to see if it contains the value >FF (no key pressed). The following source code performs this check:

REF

KSCAN

KEY HEXFF

EQU BYTE

>8375

>FF

GETKEY

BLWP

CB JEQ

@KSCAN OHEXFF,OKEY * See if a key was pressed. GETKEY * If no key pressed, check again.

( OR'L_L_INK: ) (3PcicbF"1-1 I C3
e U G

C) t3

r-1 Ni I 184 io

L. I IN tc::

The following GPL routines can be used by your program to perform some useful tasks such as loading character sets, producing tones, allocating string space ect. All the GPL routines are accessed through GPLLNK. The GPL routines covered in the following sections return to your program after they have finished executing. In order for you to use the GPLLNK utility you must include the statement REF GPLLNK in your program source code. You must also set the status byte located at address >837C equal to >00 before branching to GPLLNK. The address of the desired GPL routine is put in a DATA statement immediately following the BLWP @GPLLNK instruction. The source code on the following page illustrates these points.

UTILITY PROGRAMS

83

REF GPLLNK CLR MOVB BLWP DATA R1 R1,@>837C @GPLLNK >XXXX

* Reference GPLLNK routine. * * * * R1=0 Set Status Register byte=0 Call utility. Designate routine desired.

Table 6.3 lists all the subroutines available with the GPLLNK utility.

TABLE 6.3 GPLLNK UTILITY ROUTINES Data >0016 >0018 >0020 >0034 >0036 >0038 >003B >003D >004A Description
Loads the standard character set into VDP RAM. Loads small capitals character set into VDP RAM. Executes the "power up" routine. Generates the "accept tone". Generates the "bad response tone". Executes the "get string space" routine. Bit reversal routine. Cassette device service routine. Loads lower case character set into VDP RAM.

The following are complete descriptions of each GPLLNK routine that is available.

DATA >0016 LOAD STANDARD CHARACTER SET


This GPL utility loads the standard set into a designated area of VDP RAM. Before calling this routine, put in CPU RAM address >034A the beginning address in VDP RAM where characters are to be loaded. The following is an example of how to load the standard character set into VDP RAM starting at VDP address >0400:

REF LI MOV

GPLLNK R1,>0400 R1,@>834A

Reference needed utility. Beginning address to load characters. Place beginning address at >834A. R1=0 Move 0 into >837C. Call up utility. Designate subroutine desired.

R1 CLR MOVB R1,@>8376 BLWP @GPLLNK DATA >0016

84

UTILITY PROGRAMS

DATA >0018 LOAD SMALL CAPITALS CHARACTER SET


This GPL routine loads the small capitals character set into a designed area of VDP RAM. Before calling this routine, place the VDP address you want the characters to start loading at CPU RAM address >834A. Use the same source listing as in the previous example except the DATA directive to read DATA >0018.

DATA >0020 EXECUTE POWER-UP ROUTINE It returns you to the This GPL routine initializes the system. master title screen, clears the VDP circuits and places the default values in the VDP registers, character set, status block, and Color Table. Available VDP RAM size is stored at >8370. DATA >0034 GENERATE ACCEPT TONE
This routine causes a tone to be generated. It is the same tone that is generated in BASIC in association with a correct input.

DATA >0036 GENERATE BAD RESPONSE TONE


This routine causes a tone to be generated. It is the same tone that is generated in BASIC in response to an incorrect input (error message).

DATA >0038 GET STRING SPACE ROUTINE


This routine sets aside memory space in VDP RAM. CPU address >830C and >830D are loaded with the number of bytes to be reserved. After calling this routine, CPU address >831C points to the beginning of the allocated string space and address >831A points to the first free address in VDP RAM (byte following string). This routine destroys bytes at addresses >8356 through >8359. Addresses starting at 834A onward may also be destroyed in some cases.

DATA >003B BIT REVERSAL ROUTINE


This routine provides a mirror image of a byte. It is most commonly used to from a mirror image of a character or sprite during execution of game programs. Prior to calling this routine, CPU RAM address >834A is loaded with the address of the data in VDP RAM that you want to reverse. Address >834C contains the number of bytes to be reserved. During execution of this routine, in each byte, bits 0 and 7 are exchanged, bits 1 and 6 are exchanged, bits 2 and 5 are exchanged, and bits 3 and 4 are exchanged. CPU RAM addresses >0830 through >0840 are destroyed.

UTILITY PROGRAMS

85

DATA >003D CASSETTE DSR ROUTINE This routine allows you to access a cassette recorder. In order for this routine to work a number of condition must be met: 1. The Peripheral Access Block (PAB) and data buffer must be set up in VDP RAM prior to calling the routine. The screen start address must be >00 for prompts issued by the cassette DSR (Device Service Routine).

2.

3. Address >834A is the beginning of the device name (ie. "CS1"). 4. Address >8356 points to the first character following the name in PAB. Address >8354 and >8355 are the length of the device name (ie. >0003 for "CS1"). The word at address >83D0 should be set to
>0000.

5.

6. 7.

Address >836D must be set to >08 to indicate a DSR call. The status byte at CPU address >837C must be set to >00.

8.

DATA >004A LOAD LOWER CASE CHARACTER SET This routine is only available on the TI-99/4A. This routine allows you to load the lower-case character set into a designated area of VDP RAM. Before calling this routine, load CPU RAM address >834A with the starting address in VDP RAM that you want to begin loading the characters. ( ID B IRIL... Ni F.< )
Er N.," I IC 8 la Ft V I IC E.: Fc rol

urr 1 r4 la

L.. I IN.1 IF<

This utility allows you to link your assembly language programs with peripheral devices such as printers, disk drives, cassette recorders, ect. It also allows you to link to a subprogram in ROM. Before calling this utility a number of conditions must be set up: 1. A Peripheral Access Block (PAB) must be set up in VDP RAM to describe the characteristics of the device and file to be accessed. The word at CPU RAM address >8356 must be loaded with the value that represents the device or subprogram name length.

2.

86

UTILITY PROGRAMS 3. A DATA directive after the BLWP @DSRLNK is >8 for
linkage to a Device Service Routine and >10 for linkage to a ROM routine.

If after the DSRLNK utility is called and no error has occurred, bit (EQ) of the Status Register is reset. If however, and Input/Output error has occurred, the equal bit is set and the error code is stored in the most-significant bit of RO of the calling programs workspace. Appendix F outlines the Input/Output error codes. NOTE: You can not use this routine to access a cassette because the cassette Device Service Routine is located in GPL GROM and not normal DSR ROM. In order to access a cassette you must use the statement:

BLWP @GPPLNK DATA >003D fS .. 1 (IF* Pli Et ) IF*EFeli I F'a I-I la IR A IL__ Pil IC B B

PABs are used by Device Service Routines to access peripheral devices. The structure and format of a PAB is the same for every peripheral. You must place the necessary information describing the peripheral device into the PAB before attempting to open the file. The PAB is made up of 10 more bytes which provide information to the DSR Utilities regarding the characteristics of the peripheral device and file attributes that you want to access. Table 6.4 describes the bytes that make up the PAB as well as a description of the information each contains:

TABLE 6.4 PAB STRUCTURE Byte* Bits Contains


0 All I/0 code

Description
I/0 code describing current file condition. See following sections for complete description of all allowable I/0 codes.

-Status Byte-

This byte contains all the information the computer needs to describe the file. It includes information regarding file type, data type, and operation mode. The contents of each bit is outlined below:

UTILITY PROGRAMS TABLE 6.4 PAB STRUCTURE (continued) Byte# Bits


0-2

87

Contains
Error Code

Description
When an error is detected during an operation the error code is returned here. '00' indicates that no error has been detected. The error codes are further outlined in Table 6.6

Record Style

Place a value of '0' for "Fixed length records" and a value of 'I' for "Variable length records".

Data Format

Place a value of '0' for "DISPLAY" and '1' for "INTERNAL". "UPDATE"='00', "OUTPUT"='01' "INPUT"='10', "APPEND"-'11' Load '0' for "Sequential Files" and '1' for "Relative Files".

5-6

Operation Mode File Style

'") 4-

*tr

.....

All Data Buffer This is the address in VDP RAM that you want to put data read from a Address record or where you place data that you want to write to a record. All Record Length The length of each record for "fixed length records" or the value of the maximum length of a "variable length record". This byte contains the number of characters that you want to WRITE onto a record or it contains the number of characters that is to be READ from a record. This byte is only used with "relative It gives the current record files". number that the next I/O operation is

All

Character Count

6-7

ALL

RECORD #

88

UTILITY PROGRAMS

TABLE 6.4 PAB STRUCTURE (continued) Byte* Bits Contains Description


to be performed. But 0 is discarded so that this number can range from a value of 0 through 32767.

8 All

Screen Offset

This byte contains the offset of the screen characters with respect to their normal ASCII values. This is only used with a cassette interface, which requires prompts to be placed on the screen. This byte contains the length of the File Descriptor begins at byte 10.

9 All

Name Length

10 All

Device/File Contains the device name and if necessary, Descriptor the file name. The length of this description is given in byte 9.

For%Js ImFqirr'olurrFq_rr

caiDiB

The following are complete descriptions of each Input/Output code that can be used in Byte 0 of the PAB:

DIFNEM

>00

Before you can do anything with a file or device you must open it. The only exceptions to this are the SAVE and LOAD operations. You cannot alter byte 1 (STATUS BYTE) when an OPEN operation has been performed, the file remains open until a CLOSE operation takes place. If byte 4 of PAB is set to >0000 (Record Length), the record length that is specified by the attached peripheral is returned in byte 4. If the value for the record length is given by you is greater than 0, then it is used only after being checked against the peripheral in question.

ICILADBE

>01

This operation will close a previously opened file. If the file was originally opened in APPEND or OUTPUT mode, an END OF FILE (EOF) record is written to the device or file before closing occurs. After a file is closed you can alter byte 2 (STATUS BYTE) to

UTILITY PROGRAMS

89

change to a new mode of operation before going through the next OPEN operation.

Ft E AD

>C:1

This operation will READ a selected record from a designated peripheral device. The obtained information is stored in VDP RAM beginning at the address specified in bytes 2 & 3 (Data Buffer Address) of the PAB. The size of the buffer is number of bytes stored is given in byte 5 (Character Count) of PAB. When a READ operation takes place, if the length of the inputted record exceeds the buffer size, the remaining bytes are discarded.

11,4 Ft I ir E

>07,5

This operation will write to a record from the buffer specified in PAB bytes 2 & 3. The number of bytes that will be written is given in byte 5 of the PAB.

Ft E '11. C3FtEl. IR la 1.4 I r.4 Et

> c) A-

This operation will reposition the file pointer to the beginning of the file for sequential files. If the file is a relative file, the pointer is set to the record specified in bytes 6 & 7 of PAB. The RESTORE/REWIND operation can only be carried out if the file was opened in UPDATE or INPUT mode. You can simulate a RESTORE operation when you are using relative files by entering the record at which the file is to be positioned in bytes 6 & 7 (Record #) of the PAB. This will then be the next record accessed in the next operation.

L...1010;13

>on

This operation code will allow you to load the memory image of a file from a peripheral into an area of VDP RAM. You are allowed to use LOAD without a previous OPEN operation. The following information must be placed in the PAB before instituting a LOAD operation: 1. 2. Place >05 in byte 0 of PAB. Place the starting address in VDP RAM that you want the file to be copied into in bytes 2 & 3 (Data Buffer Address) of the PAB. Place the maximum number of bytes to be loaded in bytes 6 & 7 (Record #) of the PAB. Place the name length in byte 9 of the PAB. Place the file descriptor information in bytes 10 on.

3. 4. 5.

90

UTILITY PROGRAMS

Keep in mind that the LOAD operation will require as much memory space in VDP RAM as the file occupied on a diskette or other medium.

This operation code will allow you to write a copy of a file in VDP RAM to a peripheral. You are allowed to use SAVE without a previous OPEN operation. The following information must be placed in the PAB before instituting a SAVE operation.

1. Place >06 in byte 0 of PAB. 2. Place the starting address in VDP RAM from which the file is to be copied in bytes 2 & 3 (Data Buffer Address) of the PAB. Place the number of bytes to be saved in bytes 6 & 7 (Record #) of the PAB. Place the name length in byte 9 of the PAB. Place the file descriptor information starting in byte 10 of PAB.

3. 4. 5.

This operation code will delete the file specified from the peripheral. A CLOSE operation will then be performed.

13 a L_ E 'T. E: IR a

lc oi Fc o

> ci a

This operation code will remove a specified record from a relative record file. The number of records that you want to delete is placed in bytes 6 & 7 (Record #) of the PAB. If this operation code is specified with files opened as sequential, an error occurs.

When the operation code is specified certain status information is returned regarding the peripheral device and file. The status information returned is placed in byte 8 (Screen Offset) of the PAB. Bits 0 through 5 have meaning whether the file is opened or closed, bits 6 & 7 only have meaning when the file is open; otherwise they are reset.

UTILITY PROGRAMS

91

Table 6.5 outlines bits of byte 8 (Screen Offset) and the information regarding status that each returns:

TABLE 6.5 PERIPHERAL STATUS BITS Bit


0

Status Information
If this bit is set (=1), the file does not exist. If this bit is reset (=0), the file does exist. With devices such as printers this bit would never be set because any file can conceivably exist. The file is write-protected if this bit is set. If resei, this file is not protected and can be written to. Reserved, Always reset. If this bit is set it indicates that the Data Format is INTERNAL. If this bit is reset it indicates that the Data Format is DISPLAY or that the file is a program file. If this bit is set it indicates that the file is a program file. If this bit is reset it indicates that the file is a data file. If this bit is set it indicates that the record length is VARIABLE. If this bit is reset it indicates that the record length is FIXED. If this bit is set, the file is at the actual physical end of the peripheral and no more data can be written. If this bit is set, the file is at the end of its previously entered data. You can write more data to the file but if you attempt to read past this point an error will be generated.,

2 3

5 ,.)

___________ ..... ______________________________________________


Now that we have discussed the basic structure of the PAB it is time we go through an example of creating one for your on program so you can better understand how it is accomplished. Suppose we wanted to OPEN a FIXED 80 file "DSK, FILE1", DISPLAY, INPUT, SEQUENTIAL. To start, byte 0 of the PAB would specify an OPEN operation like so:

0000 0000

(OPEN operation code)

Byte 1 would indicate FIXED, DISPLAY, INPUT & SEQUENTIAL like


SO:

0000 0100

92

UTILITY PROGRAMS

Bytes 2 & 3 would indicate the address in VDP RAM where we will place the data that we will later input to the file. In this case we will put it starting at address >1000 like so:

0001 00000

0000

0000

Byte 4 would indicate our record length, which is 80 or >50:

0101 0000

Byte 5 is our character count which will be:

0000

0000

Bytes 6 & 7 are only used with relative files so we will reset them both to 0 like so:

0000 0000 0000

0000

Byte 8 is our screen offset for a cassette inteface which we are not using, so we reset it to o like so:

000 0 0000

The remaining bytes, 10 and on, contain the Device and File Description. Since these are given as ASCII values we will use a TEXT directive to enter it

TEXT

'DSK1.FILE1'

Thus, our PAB would look something like this:

PAB EQU >0004,>1000,>5000,>0000,>000A TEXT 'DSK1.FILE!'


When accessing files some errors are bound to occur. Errors are returned in bits 0 through 2 of the first byte of the PAB. Table 6.6 on the next page indicates all the possible error codes and their respective meanings.

UTILITY PROGRAMS TABLE 6.6 FILE ACCESS ERROR CODES Error code Bits Meaning
0 1 .. 2 000 001 010

93

...) 3

011

4 5

100 101

6 7

110 111

Bad device name. Device is write protected. Incorrect file type, incorrect record length, incorrect I/0 mode, no records in a relative file. Illegal operation; a operation that is not supported on the peripheral or a conflict with the OPEN attribute. Out of Buffer space on the device. You have attempted to read past the end of the file. The file is closed when this error occurs. Device error, bad medium and other hardware problems. File error such as data/program file mismatch, non-existent file opened in INPUT mode ect.

NOTE: An error code of 0 indicates that no error has occurred. unless bit 2 of the status byte at address >837C is set. If bit two is set in the Status Register it indicates a bad device name. Your program should check bits 0 through 1 of byte 1 of the PAB after every I/O operation to see if an error has occurred. You should also clear these bits before every I/O operation. There are some default values that the DSR will use if no values are specified. The following chart outlines these defaults. DEFAULT CONDITIONS 1. 2. 3. 4. 5. SEQUENTIAL UPDATE DISPLAY FIXED if relative records, VARIABLE if sequential Record length depends on the peripheral

You also need to construct a PAB in order to comunicate with RS232 interfaces. The following source code illustrates how you may output information to a printer or other peripheral attached via a RS232 interface:

000 001
002 * 003 MYREG

DEF START REF VSBW,VMBW,KSCAN,DSRLNK BSS


>20

004 *

94

UTILITY PROGRAMS

005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053

PAB STATUS PNTR PDATA

EQU EQU EQU BYTE BYTE DATA BYTE BYTE DATA BYTE BYTE TEXT

>F80 >837C >8356 0 >10 >0002 80 34 0 0 12 'RS232.BA=300'

* * * * * * * * *

OP-CODE Flag status VDP buffer Record length # of characters to write

Name length Device name

* ERMSG ERROR# * START * LOOP

TEXT 'ERROR DETECTE D= ' TEXT '0123456789ABC DEF' LWPI MYREG MOV R11,R10 BLWP @KSCAN MOVB @STATUS,R0 JEQ LOOP LI LI LI BLWP LI LI LI BLWP BL LI BLWP BL LI BLWP BL JMP LI MOV BLWP DATA JEO RT RO,>0002 R1,MESS R2,34 @VMBW RO,PAB R1,>0300 R2,>29 @VMBW @STEP4 R1,>0300 @VSBW @STEP4 R1,>0100 @VSBW @STEP4 LOOP R3,PAB+9 R3,@PNTR @DSRLNK 8 ERROR

* Save return address. * * Key scanning loop * * * Put message on screen *

* STEP1

* STEP2

* * Write PAB data to * VDP RAM * * Open file * * * Write to file * * * Close file * * Set * PAB ponter * * * *

* STEPS

* STEP4

UTILITY PROGRAMS

95

054 055 056 057 058 059 060 061 062 063 064 065 066 067 068

ERROR

CLR MOVB SWPB MOVB LI BLWP LI LI LI BLWP B TEXT END

R4 RO,R4 R4 @ERROR*(R4),R1 R0,79 @VSBW R0,62 R1,ERMSG R2,16 @VMBW *R10

* Error handling routine * * * Get error number * * Print * error * number * and * message * on screen

* MESS *

'THIS SENTENCE WILL BE PRINTED OUT!' START

96

UTILITY PROGRAMS

CHAPTER 6 STUDY EXERCISES

1. Write a short program that will place the value 34 at VDP RAM address >1000.
j..) .4... al

If CPU RAM address >8375 contains >FF after calling the KSCAN utility, what does that indicate?

3. Write a short program that will select the keyboard device that checks input from the left side of the keyboard and joystick #1.

7 GRAPHICS

Your TI home computer is a versatile machine in that it can construct colorful graphics in a virtual infinite number of different shapes. There are four basic screen modes you can use to aid you in constructing graphics, they are as follows:

1.

GRAPHICS MODE

2. MULTICOLOR MODE ,.. BIT-MAP MODE


4. TEXT MODE
Before we discuss each individual screen mode and how each can be used, we must first discuss the VDP (Video Display Processor) registers and how they affect what appears on the screen.

-97-

98

GRAPHICS MADE EASY

7.0 vpIP FreeiBm:RB

There are a total of 8 VDP registers labeled 0 through 7. Each register contains a single byte. You can change the contents of a VDP register by using the VWTR utility. The VDP registers contain information that determines how the computer displays graphics on the screen. The following is an example of using the VWTR utility to put a value of >01 in VDP register 7:

REF

VWTR

* Reference needed utility program. * VDP R7/value to load=>01 * Call utility program

. RO, >0701 LI BLWP @VWTR

The following is a brief description of each VDP register. The default values (values loaded in when the computer is turned on) are also listed:

%/nip IFcez

c)

The default for VDP Register 0 is >00 for BASIC, xBASIC, and Editor Assembler. The following table outlines what each of the bits in VDP Register 0 controls.

TABLE 7.0 VDP REGISTER 0 BITS Bits Description

0 - 5 These bits are reserved. All these bits must be reset (=000000). 6 If this bit is set, the screen is put in

BIT-MAP MODE.

7 External video enable/disable. Setting this bit enables video input and resetting this bit disables video input.

The default configuration of this register is: 0000 0000

vnif.,

FIS;MIR

The default for VDP Register 1 is >E0 for BASIC, xBASIC, and Editor Assembler. A copy of VDP Register 1 is located at CPU RAM address >83D4. If no key has been pressed for a long time the computer automatically "blanks" the screen. When subsequently a key is

GRAPHICS MADE EASY

99

pressed, the computer reloads VDP register 1 with a copy of what is in address >83D4. Therefore if you want to change VDP register 1, make sure you put a copy of its new value at address >83D4. Table 7.1 outlines what the bits in VDP Register TABLE 7.1 VDP REGISTER 1 BITS Bit 0 Description Selects 4K or 16K RAM operation. A value of 0 selects 4K RAM operation, and a value of 1 selects 16K RAM operation. Blank enable/disable. Setting this bit (=1) causes the screen to go blank. Resetting this bit (=0) causes the screen to display normally. When the screen is blanked, only the border color remains on it. Interrupt enable/disable. Setting this bit (=1) enables VDP interrupt and a resetting this bit (=0) disables VDP interrupts. If this bit is set, the display is in TEXT MODE. If this bit is set, the display is in MULTICOLOR MODE. Reserved, must be O.
Sprite size selection. Resetting this bit (=0) selects for standard sized sprites. Setting this bit (=1) selects double-sized sprites. Sprite magnification selection. Setting this bit (=1) selects magnified sprites, and resetting this bit selects unmagnified sprites. 1 controls.

3 4 = ,i 6

The default configuration for this register is

e 1110

0000

VDP registers 2 through 6 define the beginnings of the Screen Image Table, Color Table, Pattern Descriptor Table, Sprite Attribute Table, and Sprite Descriptor Table. We will discuss each of these tables in great depth in subsequent chapters. But for now it is a good idea not to alter these registers from their default values.

100

GRAPHICS MADE EASY

iisi u F... Fr 9 I B -"T" la

:..... -,

The default for this register is >00 in BASIC, XBASIC and Editor Assembler. This register defines where the Screen Image Table begins The beginning of the Screen Image Table is found by multiplying the value in this register by >400.

The default value for this register is >0C in BASIC and >20 in xBASIC.

>0E

in Editor/Assembler,

This register defines the beginning of the Color Table. The beginning address is found by multiplying the value in this register by >40.

'V ID IP Pc e I B li" IR:


The default value for this register is >01 in the Editor/Assembler default and >00 in BASIC and xBASIC. This register defines the beginning of the Pattern Descriptor Table. The beginning address is found by multiplying the contents of this register times >800.

ika ID F. Fr 1E: G I 1- PC

1.. 31

The default value for this register is >06 in the Editor/Assembler, BASIC and xBASIC. This register defines the beginning of the Sprite Attribute Table. The beginning address is found by multiplying the contents of this register times >80.

ivinF.

Fze I B -raF

e)

The default value for this register is >00 in the Editor/Assembler BASIC and xBASIC. This register defines the beginning of the Sprite Description Table. The beginning address is found by multiplying the contents of this register times >800.

The default value for this register is and >17 in BASIC and xBASIC.

>F5

in the Editor/Assembler

GRAPHICS MADE EASY

101

Table 7.2 lists the bits in VDP Register 7 and what each controls:

TABLE 7.2 VDP REGISTER 7 BITS Bits 0 Description TEXT MODE. 4 - 7


Holds the code for the upper and lower screen border color in all modes.

- 3 Holds the color code for the foreground color in

B u pi rsi icl. Ft 'V'

The following table summarizes the most important bits in the various VDP registers. These are the bits that you should become familiar with, as a working knowledge of them is necessary in order to program properly. TABLE 7.3 SUMMARY OF IMPORTANT VDP REGISTER BITS VDP Register RO R1 R1
R1 R1

Bit 6* 3* 4*
6 7

Controls
If set, set, If set, If set, If set,

If

display display display sprites sprites

is in BIT-MAP MODE. is in TEXT MODE. is in MULTICOLOR MODE. are double-sized. are magnified.

*Resetting these 3 bits puts the display in GRAPHICS MODE.

7' - 1 BIR Pk FAINII

ri C31).

GRAPHICS MODE is the mode you probably will be programming in most of the time. It allows you to use the standard ASCII characters and define patterns of your own to display on the screen. You can also define the foreground and background colors for any characters. The ASCII character patterns are available to you. You can use sprites and set them in motion in graphics mode. Graphics consist of characters. Each character is made up by a

8 x 8 dot pattern. The character is defined by turning some dots


"on" and leaving others "off" in the pattern. In order to display a graphic pattern on the screen you have to first describe the shape of the character, then you describe its foreground and background colors, and finally you describe where

102

GRAPHICS MADE EASY

on the screen you want the character to be displayed. There are three separate tables that contain the information needed to produce graphics on the screen. The three tables and the information they contain are as follows:

1. 2.

PATTERN DESCRIPTOR TABLE Holds character pattern identifier a) COLOR TABLE a) Holds color code for foreground and background color of character SCREEN IMAGE TABLE a) Refers to the screen location of the pattern.

3.

To sum up, graphics are created by setting up information about their shape, color and screen location in the tables. It is recommended that your three graphics tables start at the following VDP RAM addresses (These are the VDP Register default values):

TABLE 7.4 LOCATION OF GRAPHIC TABLES Table


PATTERN DESCRIPTOR TABLE COLOR TABLE SCREEN IMAGE TABLE

VDP RAM Table Location


>0800

>o3eo
>0000

The Pattern Descriptor Table can hold up to 256 different patterns or characters. Each character is defined by a "pattern identifier" as outlined in your User's Reference Guide. Each pattern takes up 8 bytes in the Pattern Descriptor Table. Thus character 0 takes up addresses >0800 through >0807, character 1 takes up addresses >0808 through >080F, and character 256 occupies addresses >OFFS through >OFFF. In GRAPHICS MODE the standard ASCII character patterns are automatically loaded into the Pattern Descriptor Table by the system. So character 32 (space character) occupies bytes >0900 through >0907, and ASCII character 33 (exclamation point) occupies addresses >0908 through >090F and so on with the other ASCII characters. To find the Table address for any character simply multiply its character number times 8 and add it to >0800. For example to find the table address that starts defining ASCII character 65 (Capital letter 'A'):

E (65) * (8)

+ 2048 = 2568 = >0A08

GRAPHICS MADE EASY

103

If you want to add additional character patterns of your own but do not want to alter any of the ASCII character patterns already present you can place your own character patterns beginning with character number 128 and extending through 256. Of course, you can alter any pattern in the Pattern Descriptor Table, if you wish.

icolLADIFc

iripluit__

The Color Table codes for the foreground and background color of each character. Each color code takes up one byte in the Color Table. Each byte codes for the foreground and background color of eight successive characters. The four most-significant bits code for the foreground color and the four least significant bits code for the background color. The Color Table begins at VDP RAM addresses >0380. The following are the values for the 16 colors available on the TI Home Computer. Note that the values are somewhat different in assembly language then they are in BASIC:

TABLE 7.5 COLOR CODES COLOR


Transparent Black Medium green Light green Dark blue Light blue Dark red Cyan

CODE >0 :>1 >3 >3 >4 >5 :::.6 >7

BITS SET
0000 0001 0010 0011
0100

COLOR
Light yellow Light red Dark yellow Light yellow Dark green Magneta Gray White

CODE
>8 >9 >A >B >C >D >E >F

BITS SET
1000

1001 1010

0101 0110 0111

1011 1100 1101 1110 1111

The byte at address >0380 specifies the colors for characters 0 through 7, the byte at address >0381 specifies the colors for characters El through 15, and the byte at address >039F specifies the color of characters 248 through 255. For example, if we place a value of >F1 at VDP address >0384, characters 32 through 39 are displayed as white on black.

ICIIRIEIN4 IMIAB

TiPirE

In the BASIC language the screen is divided into 24 rows of 32 columns. A screen location is designated by a row and column number. For example the statement:

CALL HCHAR(4,5,65,1)
will place the capital letter 'A' in the 4th column row 5.

104

GRAPHICS MADE EASY

The computer has no concept of a "screen"; it just views the screen as a series of memory locations. There are no rows and no columns, only 768 possible memory locations numbered 000 through 767. These memory locations begin at VDP address >0000 and extend through address >02FF. These addresses make up the Screen Image
Table. Figure 7.6 shows how the consecutive memory locations designate the consecutive screen locations:

FIGURE 7.6 SCREEN IMAGE TABLE/SCREEN POSITION


000 001 002

032 064 .
O N

033 965 .
0

034 066 .
a

003 004 . . . . a 035 . . II . . .


I/ St a

. . .
g

IV
a

. 029 030 031 . 062 063 095 0

V II * *

O a

a a

a 736

" a a
P a
//I N * "

767

If you place the ASCII value of a character in the Screen Image Table, the character will appear in the designated place on the screen. For example, if you place the value 65 in VDP RAM address >23 then the character 'A' will appear in screen position 035. To convert a row and column location into a Screen Image Table address simply use the -Following -Formula: C C + (R * 32) 3 =P where C is the column number, R is the row number, and P is the
resulting Screen Image Table address. Now that we know how graphics are put together we can construct a small assembly language program to illustrate how it all goes together. Consider the BASIC program:

10 20 30

CALL COLOR(1,16,2) CALL HCHAR(4,10,65,1) GOTO 30

This short program prints character 65, which is the "A" character, on the screen at row 4 column 10. The character is printed white on a black background. To convert this to an assembly language program we have to load the needed information into the proper tables as demonstrated on the next page.

GRAPHICS MADE EASY 001 002 003 * 004 MYREG 005 * 006 START 007 * 008 009 010 * 011 012 013 014 015 * 016 HERE 017 DEF REF BSS LWPI LI LI BLWP LI LI BLWP JMP END START VSBW >20 MYREG R0,>0384 R1,>1F00 @VSBW R0,138 R1,>4100 @VSBW HERE START * Define program entry point. * Reference needed utilities.

105

* Reserve memory for my registers. * Pointer to beginning of my workspace. * Color Table address. * Byte to write (white on black). * * Screen Image Table address. * Load character 'A' ASCII 65. * Character is displayed in screen position 138. * This holds display on screen. * Program runs when loaded.

Now suppose we want to define a character of our own. In BASIC we would add a CALL CHAR statement to our previous program. We will now define a ball pattern as character 128 and color it red. We will then display it on the screen:

10 20 30 40

CALL CHAR(128,"3C7EFFFFFFFF7E3C") CALL COLOR(13,9,1) CALL HCHAR(4,10,128,1) GOTO 40

To translate we simply add some additional code to load the new pattern into the Pattern Descriptor Table, and change the color values in the Color Table:

001 002 003 * 004 MYREG 005 BALL * 006 007 START 009 010 011 012 * 013 014 015 016 017 * 018 019 020 021 HERE 022

DEF REF BSS DATA LWPI LI LI BLWP LI LI LI BLWP LI LI BLWP JMP END

START VSBW,VMBW

* Define program entry point. * Reference needed utilities.

>20 >3C7E,>FFFF,>FFFF,>7E3C MYREG RO,>0390 R1,>8000 @VSBW RO,>0C00 R1,BALL R2,8 @VMBW R0,138 R1,>8000 @VSBW HERE START

* Pattern

* Pointer to beginning. * Load * Color Table (red) * * Load ball * pattern into * Pattern Descriptor Table * * * * * * Screen position Character (ball) to write. Place ball on screen. Hold it on screen. Program runs when loaded

106

GRAPHICS MADE EASY

7_.-7. mull_irIlcolL_DF;: imoin

MULTICOLOR MODE

divides the screen into a series of "boxes". Each box is a 4 x 4 pixels in size. You can define the color of each individual box. There are 64 boxes in a row and there are a total of 48 rows. You are not allowed to define characters or use ASCII characters when in MULTICOLOR MODE. You are allowed to use sprites in MULTICOLOR mode. To place the screen VDP register 1.
in MULTICOLOR MODE you must set bit 4 in

You must place the following values when using MULTICOLOR MODE: TABLE 7.7

in the Screen Image Table

VALUES TO LOAD IN SCREEN IMAGE TABLE VALUES TO LOAD


>00 >00 >00 >00 >20 >20 >20 >20 >40 >40 >40 >40 TO TO TO TO TO TO TO TO TO TO TO TO >1F >1F >1F >1F >2F >2F >2F >2F >3F >3F >3F >3F

VDP ADDRESSES
>0000 >0020 >0040 >0060 >0080 >00A0 >0000 >00F0 >0100 >0120 >0140 >0160 TO TO TO TO TO TO TO TO TO TO TO TO >001F >003F >005F >007F >009F >00BF >00DF >00FF >011F >013F >015F >017F

VDP ADDRESSES
>oleo TO >019F
>01A0 >01C0 >01E0 >0200 >0220 >0240 >0260 TO TO TO TO TO TO TO >02e0 TO >02A0 TO >02C0 TO >02E0 TO >01BF >01DF >01FF >021F >023F >025F >027F >029F >02BF >02DF >02FF

VALUES TO LOAD
>60 >60 >60 >60 >BO >BO TO TO TO TO TO TO TO TO TO TO TO TO >7F >7F >7F >7F >9F >9F >9F >9F >BF >BF >BF >BF

>eo
>80 >A0 >AO >AO >AO

Once you have loaded the Screen Image Table with the above values you can start describing the colors of the boxes on the screen. This is done by placing values in the Pattern Descriptor Table. The Pattern Descriptor Table thus describes colors in MULTICOLOR MODE instead of patterns as it did in GRAPHICS MODE.

The Pattern Descriptor Table should begin at address >0800 in VDP RAM. The first byte in the Pattern Descriptor Table describes the color of the first two adjacent boxes on the first row. The color codes are given on page 103. The left four bits of the byte describe the color of the first box and the right four bits describe the next box on the same row.
The next byte in the table defines the colors of the first two boxes in the second row. The third byte describes the first two boxes in the third row. This continues until the first two boxes

GRAPHICS MADE EASY

107

in all 48 rows have been defined. Thus, the first eight bytes in the Pattern Descriptor Table describe the color of the first two columns of boxes. The second group of eight bytes in the table define the colors of the third and fourth columns of boxes. This continues until the last eight bytes in the Pattern Descriptor Table are reached OODF8 to >ODFF) which in their turn define the colors of the last two columns of boxes.
-

7__.. s

mx -117- mania
rows. You are not pixels in size. of 768. Thus the often used in

In TEXT MODE the screen is 40 columns by 24 allowed to use sprites. Each character is 6 x 8 There are 960 possible screen positions instead Screen Image Table is longer. TEXT MODE is most word processing programs.

To place the screen in TEXT MODE you must set bit 3 in VDP register 1. Two colors are available in TEXT MODE, the pixels that are turned off are the color defined in bits 4 through 7 of VDP register 7. The bits that are turned on are the color defined in bits 0 through 3 of VDP register 7. The tables used in TEXT MODE are set up the same way as the Screen Image Table and Pattern Descriptor Tables are in GRAPHICS MODE except that the Screen Image Table is longer, and in the Pattern Descriptor Table the last two bits of each entry are ignored because each character is only 6 x 8 pixels instead of 8 x 8 pixels as they are in GRAPHICS MODE.
-

7_44. EcIir micliv- mcon

BIT-MAP MODE is available only on the TI-99/4A Home computer due to its use of an advanced microprocessor chip. BIT-MAP MODE allows you to define independently each of the 768 screen positions. You can also independently set the color of each pixel in a character. You can use sprites in BIT-MAP MODE but you cannot move them using automatic motion. In BIT-MAP MODE the Pattern Identifier Codes are stored in the Pattern Descriptor Table. The color codes that describe the colors of these patterns are stored in the Color Table. The Screen Image Table contains the number referencing a given pattern from the Pattern Descriptor Table. The reference numbers range from >00 to >FF each referencing a successive pattern in the Pattern Descriptor Table. In BIT-MAP MODE you should start the Screen Image Table at VDP RAM address >1800. You do this by setting VDP Register 2 equal to >06. Add the following code to your program to accomplish this: LI BLWP RO,>0206 @VWTR * (SEE PAGE 80 FOR A REVIEW * OF THIS UTILITY)

108

GRAPHICS MADE EASY

The Pattern Descriptor Table begins at VDP RAM address >0000 and is >1800 bytes long. In order to start the table at address >0000 you must load VDP Register 2 with >00 as in the last example. Each pattern identifier code (pattern) takes up 8 bytes in the Pattern Descriptor Table, thus there are 768 possible patterns. See your User's Reference Guide, subprogram CHAR, for further discussion of pattern identifier codes. The Color Table should begin at VDP RAM address >2000. You can do this by loading a value of >04 into VDP Register 3. The Color Table is >1800 bytes long. Each color code is 8 bytes long. The color codes are described on page 103. The first four bits of each byte code for the color of the pixels that are 'on' in one row of 8 pixels, and the last four bits of each byte code for the color of the pixels that are 'off' in the same row of 8 pixels. For example, the pattern identifier for our ball, "3C7EFFE7E7FF7E3C," which starts at address >0000 of the Pattern Descriptor Table would have >00 as its reference code. You can display the ball anywhere on the screen by entering its reference code in the appropriate place of the Screen Image Table. Other patterns in the table are referenced in the same way. For example, the second group of 8 bytes in the Pattern Descriptor Table (second pattern) are referred to in reference code >01 and so on for all other patterns. The 8 bytes in the Color Table beginning at address >2000 hold the color codes for the ball, the next 8 bytes code for the colors of the next pattern and so on. Now lets look at an example to illustrate these last points. Say we want the ball to be red with a black background. We also want the ball to have a white square in its center. Our ball pattern would be constructed as follows:

HEX CODE
1 1 lx1x1x1x1 1 1
lx1x1x1x1x1x1 1 lx1x1x1x1x1x1x1x1 lx1x1x1 ', lx1x1x1 lx1x1x1 1 lx1x1x1 lx1x1x1x1x1x1x1x1 1 lx1x1x1x1x1x1 : 1 1 lx1x1x1x1 1
>3C

>7E >FF >E7 >E7 >FF >7E


>3C

The following code would load this pattern into the Pattern Descriptor Table beginning at VDP address >0000. Don't forget to change the value of VDP Register 4 to >00 first. .

PATTAB EOU >0000 PAT DATA >3C7E,>FFFF,>FFFF,>3C7E . LI RO,PATTAB LI R1,PAT LI R2,8 BLWP @VMBW

GRAPHICS MADE EASY Now that the pattern is loaded we need to define its colors. First lets draw a map outlinning the colors we want. Black=8, Red=R, and White=W: COLOR CODE

109

IBIBIRIRIRIRIBIB1 IBIRIRIRIRIRIRIBI IRIRIRIRIRIRIRIR1 IRIRIRIWIWIRIRIRI IRIRIRIWIWIRIRIR1 IBIRIRIRIRIRIRIR1 IBIRIRIRIRIRIRIBI IBIBIRIRIRIRIBIBI

>81 >81 >81 >8F >8F >81 >81 >81

*Each row of 8 pixels is coded for *with one byte. The first 4 bits *code for the pixels that are 'ON' *in the row, in this case the code *i s red (8). The second group of *bits code for the color of pixels *that are 'OFF' in the row, in *this case black (1) or white (F).

We can use the following code to load these values into the Color Table beginning at address >2000. Remember to load VDP
Register 3 with >04 prior to reaching this segment:

COLTAB EQU >2000 COLORS DATA >8181,>818F,>8F81,>8181 LI R0,COLTAB LI R1,COLORS LI R2,8 BLWP @VMBW

When programming there will be instances when you will want to change which pixels are 'on' and which pixels are 'off' in a character. To do this it will be necessary to calculate the byte and bit position that needs to be changed in the Pattern Descriptor Table. You may also on occasion wish to change the foreground and background colors of a group of eight pixels. To do this it will be necessary to calculate the byte in the Color Table that should be changed.

If you know the X-position and Y-position of a pixel, you can use the following source code to calculate the bit offset and byte that refers to the pixel in the Pattern Descriptor Table. This source listing also provides the byte to change in the Color Table. See page 115 for a description of how how to determine pixel X and Y coordinates.

110

GRAPHICS MADE EASY

In this example RO contains the X--position and R1 contains the Y--position of the pixel: .

MOV R1,R6 SLA R6,5 SOC R1,R6 ANDI R6,65287 MOV RO,R7 ANDI R7,7 RO,R6 A R7,R6 S

* R6 is the byte offset * R7 is the bit offset

R6 is the address in the Pattern Descriptor Table that you must change. R7 is the bit that must be altered. The address of the Color Table byte that you will need to change is found by adding >2000 to R6. The following source code segment can be used to alter the VDP Register values so that the Pattern Descriptor Table, Screen Image Table and the Color Table all begin at the proper addresses required for BIT-MAP MODE: . LI

BLWP LI BLWP LI BLWP LI BLWP


. .

RO,2 * Put screen @VWTR * in BIT-MAP MODE. R0,>0206 * Screen Image Table @VWTR * begins at address >1800 R0,>0403 * Pattern Descriptor Table @VWTR * begins at address >0000 RO,>03FF * Color Table @VWTR * begins at address >2000

This next source code segment can be used to initialize the Screen Image Table. The values >00 through >FF are loaded three times in succession:

. LI CLR LI LOOP BLWP INC AI JNE CLR DEC JNE

R0,>1800 R1 R2,3 @VSBW RO R1,>100 LOOP R1 R2 LOOP

* * * * * When FF+1 is reached, (>00) * no jump is made * * Repeat loading >00 to >FF * three times

GRAPHICS MADE EASY

111

This final segment can be used to initialize the Color Table. Here we will color all pixels that are "on" black and all pixels that are "off" white. We do this by loading successive values of >F1 into the Color Table: . . LI RO,>2000 R1,>F100 LI LOOP BLWP @VSBW INC RO RO,>3801 CI JNE LOOP
. .

The following subprograms illustrate how BIT-MAP MODE can be used. Subprogram INITBM will initialize all tables and place the screen in BIT-MAP MODE. Subprogram TURNON will 'turn-on' a single pixel whose X and Y coordinates have been placed into R3 and R4 respectively. If you are using the Editor/Assembler, you need not type in these subroutines directly into your program. This is because they are all DEF'd. All you need to do is include the subprogram names in a REF statement in your program and follow these steps: 1. Type in the subroutine coding for INITBM and TURNON and save it to disk. Assemble it into an object file named BITMAP. Write your own program which places the X and Y location of the pixel you want to turn-on in R3 and R4 respectively. Include in your program a REF INITBM,TURNON statement. Assemble your program into a file named DEMO (or whatever). Select the LOAD & RUN option and when prompted for the file name type DSK1.DEMO and press ENTER. When prompted for the next file name type DSK1.BITMAP and press ENTER. Press ENTER again. When prompted for a program name, type START and press enter. Program should now execute.

2.

3.

4. 5.

6. 7.

If you are using the Line-by-Line assembler you will have to type in the source code as part of every program that uses BIT-MAP MODE.

112

GRAPHICS MADE EASY

This program will draw a rectangle when given the two points of one of its diagonals. 001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 DEF REF * HIGHX HIGHY LOWX LOWY * START * EQU EQU EQU EQU BLWP LI LI BLWP DEC CI JNE LI INC CI JNE LIMI JMP END START INITBM,TURNON 65 50 50 150 @INIT R3,HIGHX R4,HIGHY @TURNON R3 R3,LOWX PLOT R3,HIGHX R4 R4,LOWY PLOT 2 $ * Diagonal * end * points * * Initialize & enter BIT-MAP MODE

PLOT

The following are the INITBM and TURNON routines: 001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 DEF REF * MYREG INITBM BSS DATA LI BLWP LI BLWP LI BLWP LI BLWP LI CLR LI BLWP INC AI JNE INITBM,TURNON VWTR,VSBW >20 MYREG,$+2 R0,2 @VWTR RO,>0206 @VWTR RO,>0403 @VWTR RO,>03FF @VWTR RO,>1800 R1 R2,3 @VSBW RO R10100 LOOP

* Enter BIT-MAP MODE * Screen Image Table = >1800 * Pattern Descrp. Table = >0000 * Color Table = >2000

LOOP

GRAPHICS MADE EASY

113

022 023 024 025 026 027 028 029 030 031 032 033 034 035 036
037

CLR DEC JNE * LI LI BLWP INC CI JNE LI CLR BLWP DEC JNE RTWP DATA MOV MOV MOV ANDI SZC SLA A MOV ANDI S A SWPB MOVB SWPB MOVB NOP MOVB SOCB ORI SWPB MOVB SWPB MOVB NOP MOVB RTWP DATA END

R1 R2 LOOP RO,>2000 R1,>F100 @VSBW RO RO,>3801 LOOP1


R0,>1800

LOOP1

* R1 @VSBW RO LOOP2

LOOP2

038 039 * 049 TURNON 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 GET 077

MYREG,$+2 @6(R13),R3 @8(R13),R4 R4,R5 R5,7 R5,R4 R4,R5 R5,R4 R3,R0 RO,>FFF8 RO,R3 R4,R0 RO RO,@>8CO2 RO RO,@>8CO2 @>8808,R1 @GET(R3),R1 RO,>4000 RO RO,@>8CO2 RO RO,@>8CO2 R1,@>8C00 >8040,>2010,>0804,>0001

114

GRAPHICS MADE EASY

CHAPTER 7 STUDY EXERCISES

1.

Write a few lines of source code that could be used to put the screen in MULTICOLOR MODE. Write a few lines of source code that could be used to display sprites as double-sized and magnified. What will the following source code statements do?

2.

3.

REF

VWTR

RO,>0701 LI BLWP @VWTR


4. Write a complete short program that will display a medium green colored ball-shaped sprite in the center of the screen. How does the computer view the screen? How do you make a program start running immediately upon loading it with the LOAD AND RUN option of the Editor/ Assembler?

5. 6.

8 THOSE SPIRITED SPRITES


Sprites are the mainstay of the game programmer. They can be any shape and color and can occupy screen positions independent of any characters already present. Once set into motion, a sprite can move independently of direct program control. You can magnify or make sprites double-sized. From these characteristics you can see that sprites are a very powerful asset to the programmer intent on designing fast-executing arcade games. You are allowed to define up to screen at any given time. You can MULTICOLOR MODES. You can also use cannot use their automatic motion at all in TEXT MODE. 32 separate sprites on the use sprites in GRAPHICS and sprites in BIT MAP MODE but you feature. You cannot use sprites

-115-

116

THOSE SPIRITED SPRITES

In your computer there are three different tables that collectively contain all the information needed to define sprites. You simply load the desired information into the tables and change it as needed to redefine the characteristics of your sprites. The three tables and the information they contain are as follows:

1. SPRITE ATTRIBUTE TABLE a) b) Sprite position Sprite color

2. SPRITE DESCRIPTOR TABLE a) b) Sprite pattern identifier Specify magnified or double-sized sprites

3. SPRITE MOTION TABLE a) Define X and Y velocities of sprite


To sum up, sprites are created by setting up information in the three tables that define their position, pattern, color, direction of motion, speed, and their size. It is recommended that your three sprite tables begin at the following memory locations (default values):

TABLE 8.0 DEFAULT LOCATIONS OF SPRITE TABLES Table


SPRITE ATTRIBUTE TABLE SPRITE DESCRIPTOR TABLE SPRITE MOTION TABLE

Table Begins at This VDP Address


>0300 >0400 >0780

As mentioned before you can have up to 32 separates sprites completely defined and operating at one time. These sprites are numbered from 0 (first sprite) to 31 (last sprite). Before we discuss the three sprite tables in greater detail we must first understand how the computer defines the screen for sprites. For sprites the computer divides the screen into a series of rows and columns. The columns are labeled starting on the left from 0 to 256 (>00 to >BE). The rows are numbered somewhat differently, starting from the top left, the first row is numbered 256 (>100), followed by the numbers 0 through 255 (>00 to >FF). Each screen location defined by a row and column in this manner is referred to as a pixel. A pixel is the smallest area of the screen that can be turned on or off. Most of the time you

THOSE SPIRITED SPRITES

117

will probably enter the sprite screen position as hexadecimal values, so table 8.1 outlines the rows and columns of all pixel locations in HEX code:

TABLE 8.1 ROW AND COLUMN PIXEL LOCATIONS PIXEL COLUMN . . >00 >01 >02 .
>100 1 >00 1 . . p1 . . .
. .
.

. >FC >FD >FE >FFI I


.

p2 I
II

. .

IP II IX 1E IL 1R 10 IW

>01

.
.

.
.

p3
.

>02 1
.

II

>BB >BD

I 1

. . .

. . p4 . .

>BE I

Looking at Table 8.2 it can be seen that pixel p1 is in row >100 and column 02, p2 is in row >100 column >FF, p3 is in row >01 column 02, and p4 is in row >BE column >01. There are some formulas available for converting a graphic row and column location into pixel locations and vice-versa. These formulas are as follows:

TABLE 8.2 GRAPHIC-TO PIXEL INTERCONVERSIONS


GRAPHIC ROW TO PIXEL ROW GRAPHIC COLUMN TO PIXEL COLUMN PIXEL ROW TO GRAPHIC ROW PIXEL COLUMN TO GRAPHIC COLUMN GR*8-7=PR GC*8-7=PC INTE(PR+7)/83=GR INTE(PC-1-7)/83=GC

GR=graphic row, GC=graphic column, PR=pixel row, PC=pixel column

118

THOSE SPIRITED SPRITES

8- 0 B P- FicI M

dc%T TIRI BUTE

TintEcLE

You should begin the Sprite Attribute Table at VDP address >0300. The Sprite Attribute Table holds the information regarding the present screen position of all sprites as well as their colors. The entries in the Sprite Attribute Table change constantly as the position of moving sprites changes. There are 32 possible sprites numbered 0 through 31. Each sprite takes up four bytes in the Sprite Attribute Table. The first byte is the row or "Y" position of the sprite. The second byte is the column or "X" position of the sprite. The (Y) position starts with >FF then continues with >00, >01, >02 and so on until >BE. The (X) position extends from >00 through >FF. The third byte references the pattern of the sprite as to where it is located in the Sprite Descriptor Table. It can contain any value from >00 to >FF. The fourth byte is the early clock attribute and also codes for the color of the sprite. When your computer moves sprites it updates the entries in the Sprite Attribute Table. The more sprites it has to update the longer it takes to execute the program. To shorten the time and increase program efficiency you can place a value of >DO as the Ylocation of the lowest numbered non-moving sprite in the Sprite Attribute Table. This indicates that all subsequent sprites are undefined. For example, if you have 10 sprites in motion you should place a value of >DO at address >0328. If you have no sprites defined, you should place a value of >DO at address >0300. To sum up, it is recommended that you always let the final unused sprite be undefined by specifying a Y-location of >DO. The third byte references a pattern in the Sprite Descriptor Table. The pattern reference number can range from >00 to >FF. The value of this byte corresponds to a character defined in the Sprite Descriptor Table. For example, if the third byte contained a value of >80 it would represent the character defined by address >0400 through >0407 in the Sprite Descriptor Table. The fourth byte controls the early clock of the sprite and its color. The four most significant bits (bits 1-4) control the early clock. If the last bit (bit 4) is reset to zero the early clock is off and the location of the sprite is said to be its upper left-hand corner. This means that the sprite will fade in and out on the right hand side of the screen. If the fourth bit is set to one the early clock is on and the sprites location is shifted 32 pixels to the left. The sprite can then fade in and out on the left side of the screen. The color of the sprite is determined by the contents of the four least significant bits of the fourth byte in the Sprite Attribute Table. The values are given on the next page.

THOSE SPIRITED SPRITES

119

TABLE 8.3 COLOR CODES COLOR Transparent Black Medium green Light green Dark blue Light blue Dark red Cyan CODE BITS SET
s.1 IT Ul 42, At..,1II"'0

COLOR Medium red Light red Dark yellow Light yellow Dark green Magenta Gray White

CODE
8 9 A B C D E F

BITS SET 1000 1001 1010 1011 1100 1101 1110 1111

0000 0001 00 10
0011

010 0 0101
0110 0111

You should take note that the color codes differ slightly in assembly language from their counterparts in BASIC.

The following diagram illustrates how an entry into the Sprite Attribute Table might be constructed. Two sprites are specified. Sprite 0

Sprite 1

SALIST DATA >33560.8001,>A8280.810F,>D0 -- third sprite / / / / undefined Y X / color pattern


E3... 1

'RIR I11- EE

n la is

IFt I Fm -TC:11Fc

-TAtEsi_la

The Sprite Descriptor Table describes the patterns of sprites in the same way that the Pattern Descriptor Table describes characters. You will usually begin the Sprite Descriptor Table at address >0400. You can start it at a lower address, but these are usually reserved for the Screen Image Table, Color Table, and Sprite Attribute List. Addresses >0400 through >0407 are defined as sprite pattern >80, sprite pattern >81 occupies addresses >0480 through >040F and so on through sprite pattern >EF which occupies addresses >0778 through >077F.

You can make sprites magnified double-sized or both by writing a value to the two least significant bits of VDP register 1. Table 8.4 which begins on the next page, explains the different sizes and magnifications possible as well as the correct values to write to VDP Register 1.

/20

THOSE SPIRITED SPRITES

TABLE 8.4 MAGNIFIED & DOUBLE-SIZED SPRITES BITS Description


00 Standard size sprites: Each sprite is 8 x 8 pixels which is the same size as a standard character. HEX (>00) Magnified sprites: sprites is 16 x 16 pixels in size, equal to four standard characters on the screen. Note that the pattern displayed is exactly the same as that for standard size sprites except the sprite is 4x as big. HEX (>01) Double-sized: Each sprite is 16 x 16 pixels on the screen. Each sprite is defined by four consecutive patterns from the Sprite Descriptor Table. For example, if the last two bits (bits 14 & 15) are 01, then if character >80 is referenced the sprite will be formed by characters >80, >81, >82, and >83. The first character, character >80, makes up the upper left hand portion of the sprite, the second character, character >81, makes up the lower left hand portion of the sprite, the third character, character >82, makes up the upper right portion of the sprite, and finally the last character, character >83, makes up the lower right portion of the sprite. HEX (>02) Double-sized magnified sprites: Each sprite is 32 x 32 pixels in size. This is equal to the space occupied by 16 standard size characters on the screen. Sprites are defined in the same way that double-sized sprites are except that each of the four characters is in turn four standard characters in size. HEX (>03)

01

10

11

8-:.22

SF>IFCITIa MOITIDINJ

-T- 04

The Sprite Motion Table specifies the X and Y velocity of each sprite. The Sprite Motion Table begins at address >0780. Before a sprite can be put into motion, several conditions must be met. The first thing that must occur is that your program must allow interrupts. You can enable interrupts with the LIMI 2 instruction however, before your program accesses VDP RAM you will have to disable the interrupts with a LIMI 0 instruction in order that the interrupt handling routine does not alter the VDP write address. You must also indicate in your program how many sprites will be in motion. This is done by placing a value at address >837A in CPU memory. For example if sprites 2, 5, and 7 are in motion, the number 8 be put in address >837A in order to allow motion of sprites 0, 1, 2, 3, 4, 5, 6, and 7.

THOSE SPIRITED SPRITES

121

A description of the motion of each sprite must be placed in the Sprite Motion Table. Each sprite takes up four bytes in the table. The first byte specifies the (Y) velocity of the sprite, the second byte specifies the (X) velocity of the sprite. The third and fourth bytes are used by the interrupt routine so all you have to do is remember to leave space for them in the table. The following are allowed as values for (X) and (Y) velocities, also shown are direction of travel:

TABLE 8.5 ALLOWED VALUES FOR X AND Y SPRITE VELOCITIES Decimal


0 to 127

Hex

Motion

Description
Positive velocities. Down or right motion. Negative velocities. Up or left motion.

>00 to >7F Down (Y) Right (X)

-1 to -128 >FF to >80 Up (Y) Left (X)

A value of 1 (>01) will cause the sprite to move one pixel every 16 VDP interrupts. This is approximately once every 16/60ths of a second. To summarize, in order to put sprites into motion you must:

1. 2. 3.

Enable

interrupts to occur with the LIMI 2 instruction.

The number of sprites in motion must be placed in CPU RAM address >837A. Place descriptions of motion in the Sprite Motion Table which begins at VDP address >0780.

We will now create some programs to illustrate the points covered in this chapter. The first program will place a standard sized sprite in the center of the screen, but we will not put it in motion just yet: ****************************************************** 001 002 * * 003 * Program to place a red ball-shaped sprite * 004 * in the center of the screen. * 005 * * 006 ******************************************************

007 008
009 * 010 SATAB

DEF REF EQU

START VMBW
>0300 *SPRITE ATTRIBUTE TABLE.

122

THOSE SPIRITED SPRITES

011 012 013 014 015 016 017 019 020 021 022 023 024 025 026 027 028 029 030

SDTAB * BALL SPAT * MYREG START

EQU

>0400

* SPRITE DESCRIPTOR TABLE. * PATTERN CODE. * SPRITE ATTRIBUTES. * UNDEFINED SPRITE.

DATA >3C7E,>FFFF,>FFFF,>7E3C DATA >70D0,>8008 DATA >D000 BSS LWPI LI LI LI BLWP LI LI LI BLWP JMP END >20 MYREG RO,SDTAB R1,BALL R2,8 @VMBW RO,SATAB R1,SPAT R2,8 @VMBW LOOP START

* LOAD BALL PATTERN INTO

* SPRITE DESCRIPTOR TABLE. *

LOOP

* HOLD DISPLAY ON SCREEN.

Most programmers think of sprites when referring to moving graphics. Sometimes other methods of imparting motion to characters on the screen are better suited for certain situations. The following program will place six red ball-shaped characters on the screen and scroll the screen upwards moving the characters with it. If you run this program you will notice that the motion of the characters is somewhat jerky, this is because sprites are not used: 001 002 003 004 005 006 007

* * Place 6 ball-shaped characters on the screen & scroll * * the screen upwards. This is an example of how to * * put graphics into motion without using sprites. * * ***********************************************************

*********************************************************** *
*

008 009 010 011 012 013 014 015


016 017 018

DEF REF * BALL COLOR * COLTAB PATTAB


* MYREG *

GRAPH VSBW,VMBW,VMBR

DATA >3C7E,>FFFF,>FFFF,>7E3C DATA >8100 EQU EQU


BSS

>0384
>0908 >20

* *

COLOR TABLE PATTERN DESCRIPTOR TABLE

019 020 021 022

GRAPH

LWPI LI MOV BLWP

MYREG RO,COLTAB @COLOR,R1 @VSBW

* * * *

LOAD FOREGROUND & BACKGROUND COLORS OF BALL CHARACTER INTO COLOR TABLE

THOSE SPIRITED SPRITES

123

023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064

* LI LI LI BLWP * LI LI LI BLWP AI DEC JGT BSS BSS CLR LI LI BLWP LI LI LI BLWP * LOOP1 CLR BLWP AI CI JHE BLWP AI JMP RO @VMBW R0,>40 R0,>300 OUT @VMBR RO,>FFE0 LOOP1 R0,325 R1,>2100 R2,6 @VSBW R0,33 R2 LOOP >20 >20 RO R1,LINE1 R2,>20 @VMBW RO,>20 R1,LINEX R2,>20 @VMBR * * * * PLACE 6 BALL SHAPED CHARACTERS ON THE SCREEN ONE AT A TIME IN DIFFERENT SCREEN POSITIONS ARE ALL SIX ON SCREEN YET? RESERVE MEMORY TO HOLD SCROLLED LINES OF SCREEN SAVE TOP SCREEN ROW (BEGINNING WITH POSITION >000) IN LINE1 RO,PATTAB R1,BALL R2,8 @VMBW * * * * LOAD THE BALL PATTERN INTO THE PATTERN DESCRIPTOR TABLE

LOOP

* * * * * * * *

* LINE1 LINEX * SCROLL

* * *

SAVE SECOND SCREEN ROW IN LINEX

* * * * * * * * * * * * *

EACH SCREEN ROW IS SUCCESSIVELY READ INTO LINEX AND THEN PRINTED IN THE ROW POSITION JUST ABOVE IN ORDER TO SCROLL THE SCREEN "UP" WHEN THE LAST ROW IS REACHED THE PROGRAM JUMPS TO "OUT" PRINT FIRST LINE IN LAST ROW

* OUT

LI RO,>2E0 LI R1,LINE1 BLWP @VMBW JMP END SCROLL GRAPH

JUMP BACK TO SCROLL AND REPEAT

The source code Jisting on the next page places our red ball on the screen as a sprite instead of as a graphic. It also places the sprite in motion from left to right across the screen. By pressing any key you can change the magnification of the sprite. The sprite is moved by successively changing its X-location on

124

THOSE SPIRITED SPRITES

the screen.

Automatic motion is not used.

00 1
002 003 005 006 007 008 009 010 011 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054

**** ****** ******* ******* ****** ******* ******* ****** ******* **** * *
* CALL SPRITE * * * THIS PROGRAM PLACES A RED BALL-SHAPED SPRITE IN * MOTION ACROSS THE SCREEN BY SUCCESSIVELY ALTERING ITS * * X--LOCATION. PRESSING ANY KEY ALTERS THE MAGNIFICATION * * * ************************************************************* DEF MOTION REF VSBW,VMBW,VSBR,VWTR,KSCAN KBOARD EQU >8375 SKEY EQU >8374 SATAB EQU >0300 SDTAB EQU >0400 * BALL DATA >3C7E,>FFFF,>FFFF,>7E3C SDATA DATA >7080,>8008 DATA >D000 * STATUS EQU >837C SET DATA >2000 MYREG BSS >20 * SPRITE LWPI MYREG * CLR @KEYBOARD * KEYBOARD DEVICE=0; SCAN ALL KEYS LI RO,SDTAB * LOAD LI R1,BALL * SPRITE LI R2,8 * DESCRIPTOR BLWP @VMBW * TABLE * LI RO,SATAB * LOAD LI R1,SDATA * SPRITE LI R2,6 * ATTRIBUTE BLWP @VMBW TABLE * * LOOP LI RO,SATAB+1 * READ BLWP @VSBR * GET X POSITION OF SPRITE AND SRL R1,8 * SUBTRACT 1 FROM X (X-1) DEC R1 * JNE MOVE * IF X=0 THEN LI R1,>00FF * LET X=>FF * MOVE SLA R1,8 * WRITE NEW X POSITION BLWP @VSBW * CLR R8 * THIS IS A SHORT DELAY TO * SLOW DOWN THE SPEED OF THE DELAY INC R8 CI R8,800 * SPRITE (FOR I=1 TO 800) JNE DELAY * *

THOSE SPIRITED SPRITES

125

056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084

OUT

BLWP @KSCAN MOV @STATUS,R3 COC @SET,R3 JNE LOOP

* * * *

CHECK TO SEE IF A KEY HAS BEEN PRESSED

* * R6 IS USED AS A COUNTER TO KEEP CHECK INC R6 * TRACK OF WHICH MAGNIFICATION R6,4 CI * LEVEL (1 TO 4) WE ARE ON. JLT GO * CLR R6 * * SELECT R6,1 GO CI * NEXT JEQ MAG * CI R6,2 MAGNIFICATION * JEQ DSIZE LEVEL * R6,3 CI * JEQ DSIZEM * SMALL LI RO,>01E0 * LOAD RO WITH THE PROPER VALUE JMP WRITE * TO LOAD INTO VDP REGISTER 1 IN MAG LI RO I >01E1 * ORDER TO CHANGE THE JMP WRITE * MAGNIFICATION DSIZE LI RO,>01E2 * JMP WRITE * DSIZEM LI RO,>01E3 * * ************************************************************* * * ACTUALLY LINES 066 THROUGH 079 TAKE UP A GREAT DEAL * OF MEMORY. CAN YOU SUM UP THESE LINES OF CODE INTO * * A SIMPLE TWO LINE STATEMENT THAT WOULD WORK AS WELL? *

085 *************************************************************
086 * 087 WRITE BLWP @VWTR 088 @LOOP B 089 END MOTION

* CHANGE THE VDP REGISTER

This next source code listing again places our red ball on the screen as a sprite. The ball is magnified and is moved using automatic sprite motion. The LIMI 2 instruction is present to allow interrupts to occur. Keep in mind that automatic sprite motion cannot occur without interrupts. 001 ************************************************************ 003 * CALL SPRITE * 004 * THIS PROGRAM PLACES A MAGNIFIED SPRITE ON THE SCREEN AND * 005 * PUTS IT IN MOTION USING AUTOMATIC SPRITE MOTION * 006 ************************************************************ 007 DEF START 009 REF VMBW,VWTR 010 * 011 NUMB EQU >837A 012 SATAB EQU >0300

126

THOSE SPIRITED SPRITES

013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044

SDTAB SMTAB BALL SDATA SPEED * MYREG START

EQU EQU DATA DATA DATA DATA DATA BSS LWPI LI LI LI BLWP LI LI LI BLWP

>0400 >0780 >3C7E,>FFFF,>FFFF,>7E3C >70D0 >8008 >D000 >0505,>0000 >20 MYREG RO,SDTAB R1,BALL R2,8 @VMBW RO,SATAB R1,SDATA R2,8 @VMBW RO,SMTAB R1,SPEED R2,4 @VMBW

* * * * * * * * * * * * * * * * * *

LOAD SPRITE DESCRIPTOR TABLE LOAD SPRITE ATTRIBUTE TABLE LOAD SPRITE MOTION TABLE INDICATE NUMBER OF SPRITES IN MOTION (1) IN ADDRESS >837A ENABLE INTERRUPTS ENDLESS LOOP TO HOLD DISPLAY ON THE SCREEN

* LI LI LI BLWP * LI R1,1 SLA R1,8 MOVE R1,@NUMB * LIMI 2 JMP $ END START

9 LET THERE BE SOUND


Both versions of BASIC; BASIC and Extended BASIC- provide a statement that lets you generate sound through the internal console speaker. This statement, CALL SOUND, requires that you specify the duration, frequency and volume of a desired sound: The frequency can range from 110 Hertz (cycles/sec) to 44,733 Hertz. If you want "noise" instead of a tone to be produced you can specify a negative frequency value of from -1 to -8 depending on the exact noise desired. The duration of a tone or noise can vary from 1 to 4250 milliseconds (.001 to 4.25 seconds). The volume can range from 0 (loudest) to 30 (quietest). The TI Home Computer is capable of generating up to three tones and one noise simultaneously. Sound is generated using the TMS9919 sound generator controller chip. In order to produce sound in your assembly language programs a number of conditions must be met. First, you must load the Sound Table with a description of the tone or noise you wish to produce. Secondly, you must set the least significant bit of the byte at CPU address >83FD. This indicates that the Sound Table is in VDP RAM to the computer. Thirdly you must enable interrupts with the LIMI 2 instruction so that sound processing can occur.

-127-

128

LET THERE BE SOUND

The following steps summarize what must be done in order for your program to produce sound: 1. Load the Sound Table which begins at VDP address >83CC with sound data. Set the least significant bit of the byte located at CPU address )83FD to indicate to the computer that the Sound Table is in VDP RAM. Enable interrupts by using the LIMI 2 instruction.

2.

3.

Once all the above conditions are met, you can start the sound generator by placing a value of 01 at CPU address >83CE. This address is used by the interrupt routine as a count-down timer during sound generation. NOTE: You will have to disable interrupts if you are going to read or write to VDP RAM because the interrupt routine may alter the read/write address. If your program has a key scanning loop this may be a good place to enable/disable your interrupts. See page 81 for an example.
(?_(14 THE

BoluNin

-Irdcs Eci__

In order to produce sound you must construct a Sound Table that describes the characteristics of the sound you wish to produce. The TI Home Computer has the ability to produce up to three separate tones simultaneously. It can also produce a number of different "noise" sounds. Up to three tones and one noise can be produced simultaneously. The computer has three tone generators labeled 1, 2, and 3. Noise is produced by a separate noise generator. In order to produce a tone you must enter the following information into the Sound Table: 1. 2. 3. 4. Specify Specify Specify Specify which TONE GENERATOR is to produce the tone. the FREQUENCY of the tone. the VOLUME of the tone. the DURATION of the tone.

To produce noise you must enter this information into the Sound Table: 1. 2. 3. 4. Specify Specify Specify Specify WHITE or PERIODIC noise. SHIFT RATE (type of noise). VOLUME of noise. the DURATION of the noise.

LET THERE BE SOUND

129

All the bytes that describe the characteristics of a tone or noise except one are referred to as specification bytes. The exception is the DURATION byte which is not considered a specification byte. It takes a total of three specification bytes to hold the generator number, volume and frequency of a tone. Table 9.0 outlines the contents of each of the three bytes. It should be noted now that the frequency is not entered as such (that would be to easy). Instead it is entered as a "frequency code" which we will have more on later.

TABLE 9.0 SPECIFICATION BYTES FOR TONES Byte Bit# Holds The following Information:
/ 0

ONE
\

1-2
3 4-7 0-1 2-7 / 0 1-2 \ 3

This bit is always set (=1). Specifies the Sound Generator. This bit is reset (=0). Contains the 4 least significant frequency code bits. These bits are always reset (=00). Contains the 6 most significant frequency code bits. This bit is always set (=1). Indicates Sound Generator used. This bit is set (=1).

TWO \ THREE

4-7

Volume level.

All the noise information requires only two specification bytes. They are structured as outlined in Table 9.1: TABLE 9.1 SPECIFICATION BYTES FOR NOISE Byte Bit#
0 / 1-2

Holds The Following Information:


This bit is always set (=1). Specify noise generator (both set =11). This bit is reset (=0). This bit is reset (=0). Specify WHITE (1) or PERIODIC (0) noise. Indicate TYPE of noise. This bit is always set (=1). Indicates Sound Generator used. This bit is set (=1). Volume Level.

ONE \

3
4 5 6-7 0 1-2 3 4-7

TWO
\

130

LET THERE BE SOUND

Bits 1 and 2 in all bytes refer to one of the three tone generators or the noise generator. A bit configuration of 00 selects tone generator #1. A bit configuration of 01 selects tone generator #2. A bit configuration of 10 selects tone generator #3. Finally, a bit configuration of 11 selects the noise generator. Table 9.2 illustrates several examples of the structure of tone and noise bytes. An X in a bit position is for frequency or volume information that we will cover later.

TABLE 9.2 EXAMPLES OF TONE AND NOISE SPECIFICATION BYTES Bit configuration
1000 XXXX 00XX XXXX 1001 XXXX

Byte #
1 --) .,_ 3 .... 1 2 .,_ 3 1 2 3 1 2 3

Description
Toe Lenerator # 1

HEX >8>->9>A> >B>C>->D>E>->F-

1010 XXXX 00XX XXXX 1011 XXXX 1100 XXXX 00XX XXXX 1101 XXXX 1110 XXXX OOXX XXXX 1111 XXXX

Tone Generator # 2

Tone Generator # 3

Noise generator

IF- FRIaQUEMICV %wPB.

P- Ftactli

(7.1711rE

You may think that plugging in the desired frequency into the Sound Table is all there is to it. However, it is not that easy. First of all the frequency must be converted into a frequency code which is then loaded into the table. The frequency code is defined as half the period of the specified frequency. To save you a lot of time trying to figure out what this means you can use the following formula: 111860.8 = Frequency Code Frequency Suppose we want to find the frequency code for "middle C" which has a frequency of 523.25 . We simply plug this value into our formula as follows:

111860.8 = 213.8 523.25

LET THERE BE SOUND

131

We easily find that the proper frequency code equals 213.8, a value that rounds up to 214 OOD6). The most significant 6 bits (bits 0-5) of the frequency code are placed in bits 2 through 7 of our second specification byte. The four least significant bits of the frequency code are placed in bits 4 through 7 of our first specification byte. If this sounds a bit confusing don't worry, actually its quite simple. For example, suppose we wanted to define the first two specification bytes of a tone with a frequency of 392 HZ. Further, we want to produce this tone on generator #1. We find from our formula the frequency code which equals 285 or >11D.

1000 XXXX

00XX XXXX

= >8---

Here we have selected generator #1. Now we will take our frequency code >11D and place its 4 least significant bits (>D) in bit positions 4 through 7 of our first specification byte: 1000 1101 00XX XXXX = >8D--

Finally, we take the most significant 6 bits of our frequency code (>11) and place them into bit positions 2 through 7 of our second specification byte: 1000 1101 0001 0001 = >8D11

We now have created the first two specification bytes required to produce a tone of 392 HZ on tone generator # 1. The following are some additional examples: 1000 0110 0000 1101 0000 1011 C>860D]

1010 1110 1101 1001 "...#01L_Lilm IE: IF"

0011 1111

C>AEOB] C>C93F3

Gen #1 freq = 523.25 Gen 412 freq = 587.33 Gen #3 freq = 110.00

I IF- I 'CIA -T. I CLIIINJ Et 'Y'.-1- 1

The third specification byte required for tones holds the volume of the tone. It also holds the value of the generator number you are referring to as did the first specification byte. The volume is held in bit positions 4 through 7 of the third specification byte for tones. Its value can range from 0 (loudest) to 30 (no sound). When determining the volume level these four bits may be thought of as having a binary zero following them. In this way a volume level of 0001 may be considered as 00010. The following are some examples of the third specification byte:

1001 1111 1011 0000 1111 0011 1101 1110

[>9F] E>B03 [>F3] E>DE3

TURNS OFF GENERATOR #1 VOLUME LEVEL = GENERATOR #2, VOLUME LEVEL = 0 NOISE GENERATOR, VOLUME LEVEL = 6 GENERATOR #3, VOLUME LEVEL = 28

30

132

LET THERE BE SOUND

INDIBla BF-1IF - IICPC1rICHNI EilNirT

To produce a noise requires only two specification bytes to be loaded into the Sound Table. Referring to Table 9.3 gives the bit values to be loaded into the first specification byte for the desired noise. The second specification byte holds the volume level and is constructed the same way the third specification byte for a tone is constructed except that you specify the noise generator instead of a tone generator.

TABLE 9.3 ALLOWABLE NOISE BIT CONFIGURATIONS Bit 5


0 0 0

Bits 6 & 7
00 01 10

Description
"Periodic Noise" Type 1 "Periodic Noise" Type 2 "Periodic Noise" Type 3 "Periodic Noise" varies with the frequency data in tone generator #3 "White Noise" Type 1 "White Noise" Type 2 "White Noise" Type 3 "White Noise" varies with the frequency data in tone generator #3

0 1
1 1

11
00 01 10 11

Suppose we wanted to construct the two required noise specification bytes for a Type 3 Periodic Noise with a volume level of 6. From Tables 9.1 and 9.3 we put together the first byte like so:

1111 0010

E>F23

The second specification byte containing the volume information would look like this:

1111 0011
EI.L

C>F3]

Icim DIF- lroliNua oliFe: rsIolIB

The DURATION byte is not considered a specification byte. It informs the tone or noise generator how long the tone or noise will last. It is measured in sixtieths (1/60) of a second. Possible values range from 0 (>00) no sound, which stops the generator, to 256 (>FF) which is approximately 4.25 seconds.

LADAinilmoi

imila

(DiultNin

-iric

One last thing to note before we begin constructing a Sound Table is that when you are setting up a byte table you must indicate the number of specification bytes that you are going to feed to the

LET THERE BE SOUND

133

sound generator. For example, if you wanted to specify a tone with a frequency of 110 HZ, a volume of 2 and a duration of 0.5 seconds on generator #1, the specification and duration bytes needed are: >03,>89 1 >3F,>91,30 The first byte (>03) indicates that there are 3 specification bytes to load into the sound generator. The second and third bytes (>893F) tells us that on generator #1 (>8---) a tone of 110 HZ (>-93F) is desired. The fourth byte (>91) sets the volume level of generator #1 at 2. The last byte (30) specifies a duration of 30/60ths of a second for the tone. The following are some additional examples of values to load into the Sound Table:

-3 specification bytes to load 1 -Tone Generator #1 tone -Frequency = 392.00 FC = >11D -Volume level = 2 -Duration = 20/60ths second 2. >3,>A6,>0D,>85,244 -3 specification bytes to load 1 -Tone Generator #2 tone -Frequency = 523.25 FC = >0D6 - Volume level = 10 (0101 0) - Duration = 244/60ths second

-9 specification bytes to load 3 -Tone Generators #1, #2, & #3 tones -Frequencies = 329.63, 523.25 and 739.99 - Volume levels G1=2, G2=10, G3=20 -Duration = 10/60ths second 4. >2,>E5 1 >FE,119 -2 specification bytes to load -Noise Generator (>E0) -White Noise, Type 2 (>05) -Volume level = 28 -Duration = 119/60ths second >1,>9F,0 -This data will terminate the sound in Generator #1.

1 noise

5.

134 6.

LET THERE BE SOUND >0B,>8E,>OF,>AD,>17,>CC,>1F,>E3,>90,>B6,>D3,>F6,249 -11 specification bytes to load -Tone Generators #1, #2, #3 and noise generator -Frequency = 440.00, 293.66, 220.00 -Periodic Noise of the type that varies with the frequency data loaded into tone generator #3. -Volume levels G1=0, G2=12, G3=6, NG=12 -Duration = 249/60ths seconds.

The following source code can be used to access the sound controller and start sound processing. * Begin Sound Table at VDP Address >1000 SOUNDT EQU >1000 ONE BYTE >01 . START LI R10,SOUNDT * * Put VDP address that Sound Table . MOV R10,@>83CC * begins at in CPU address `-83CC SOCB @ONE,@83FD * Sound Table is in VDP RAM. MOVES @ONE,@>83CE * Start sound processing. LIMI 2

The following program plays "HOME ON THE RANGE" on your computer. Note how all three tone generators are used together to produce multiply notes.

001 *********************************************************** * 002 * * 003 * Program plays "HOME ON THE RANGE" on your computer. * 004 * 005 ***********************************************************
006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 DEF REF * MYREG SOUNDT ONE * START BSS EQU BYTE EVEN LWPI LI LI LI BLWP START VMBW >20 >1000 >01 MYREG RO,SOUNDT R1,SDATA R2,274 @VMBW

* * * * * *

* LOOP1

LIMI 0 R10,SOUNDT LI MOV R10,@>83CC

LET THERE BE SOUND 023 024 027 029 LOOP2 030 031 032 * 033 SDATA 034 035 036 037 038 039 040 041 042 043 * 044 045 046 047 048 049 050 051 052 053 054 055 * 056 057 058 059 060 061 062 063 064 065 066 * 067 068 069 070 071 072 073 074 075 076 077 078 SOCB @ONE,@83FD MOVB @ONE,@>83CE LIMI 2 MOVB @>83CE,@>83CE JEQ LOOP1 JMP LOOP2 BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE END

135

* When CPU address >83CE = 0 * sound processing is * finished & program repeats

>03,>8D0.110.91,40 >04 1 >AD I >110.9F,>B1,40 >03,>A6,>ODOS1 1 40 >06,>8E0.0B,AD,>11,>95,>B5,40 >090.8A0. 0A,>A6,OD,CD,>11,>95,B5 1 >D5,60 >05,>86,>OD,>91,>BF,>DF,20 >030.8200E 9 ).91,40 >030.8E,OF0.91,40 >03,>800.0A,>91,40 >04 1 >A0,>0A,>9F,>B1 1 40 >09,>80,>0A 1 >A6,>ODO.CD,>100.950.B50.D5,60 >050.80,>0A,>91,BF,DF,20 >03,>80,>0A,>91,20 >03,>817 0.08,>91,40 >09,>8A,>0A,>A60.0DO.CD,>110.95,B5 I D5,40 >05,>860.0D0,9102F,DF,20 >04,>A6 1 >OD0.9F021,40 >05 1 >C6,OD,>9F 1 >BFO.D1,40 >03,>C2,>OE,>D1,40 >03,>C6,>OD,>D1,40 >03,CE,OB,>D1 1 80 >03 1 >CD,>11,D1,40 >04,>8D,>110.91,>DF,40 >03,>86,OD,>91,40 >06,>8E,>OB,>AD,>11,>93,>B3,40 >09,>8A,>0A,>A6,ODOCD,>110.950250.D5,60 >05,>860.0D,>91,BF,DF,20 >03,>82,>OE,>91,40 >03,>8E0.0F I >91,40 >03,>80,>0A,>91,40 >04,>A00.0A0.9F,>B1,40 >06, >80, >OA, >AD, >10, >93, >B3, >60 >04,>80,>0A,>91,BF,20 >04,>A000A,>9F021,40 >09 1 >8A,>0A 1 >A6,>OD I >CD,>11,>950.B5,>D5,50 >05,>8E,>OB,>91,>BF,>DF,>30 >030.86,>0D,>91,40 >090.820.0E,AD I >11,CD,>17 1 >95,B5,D5,40 >05,>86,OD0.91,>BFODF,40 >030.8E 9 M:30'91,40 >03 1 >86,ODO.91,100 >01,>FF,0

136

LET THERE BE SOUND

The following table gives you a quick reference guide for frequency specification bytes (specification bytes #1 & #2). Simply look up the desired note or frequency and follow it over to the DATA column to get the first two specification bytes. The DATA in Table 9.4 always refers to tone generator #1. If you want to produce the tone on generator #2 change the first nybble of the DATA to >A. To produce the tone on generator #3 change the first nybble of the DATA to >C. For example, to produce a tone with a frequency of 5587.65 on generator #2 the DATA would be >A401.

TABLE 9.4 TONE DATA REFERENCE TABLE NOTE


F E D# D C# C B A# A G# G F# F E D# D C# C B A# A G# G F#

OCTAVE
6 6 6 6 6 6 5 5 5 5 5 5 5 5 5 5 5 5 4 4 4 4

FREQUENCY
5587.65 5274.04 4978.03 4698.64 4434.92 4186.01 3951.07 3729.31 3520.00 3322.44 3135.96 2959.96 2793.83 2637.02 2489.02 2349.32 2217.46 2093.00 1975.53 1864.66 1760.00 1661.22 1567.98 1479.98 1396.91 1318.51 1244.51 1174.66 1108.73 1046.50 987.77 972-33 880.00 830.61 783.99

FREQUENCY CODE
>014 >015 >016 >018 >019 >01B >01C >01E >020 >022 >024 >026 >028 >02A >02D >030 >032 = >03C >040 >043 >047 >04C >050 >055 >05A >05F >065 >06B >071 >078 >07F >087 >08F

DATA
>8401 >8501 >8601 >8801 >8901 >BB01 >8C01 >8E01 >8002 >8202 >8802 >8602 >8802 >8A02 >8D02 >8003 >8203 >8503 >8903 >8CO3 >8004 >8304 >8704 >8C04 >8005 >8505 >8A05 >8F05 >8506 >8806 >8107 >8807 >8F07 >8708 >8F08

F
E D# D C# C B A# A G# G

4 4 4
4

4
4 4 4 3 , ..) 3 ..... ,:, 3

LET THERE BE SOUND

137

TABLE 9.4 TONE DATA REFERENCE TABLE NOTE


F# F E D# D C# C B A# A G# G F# F E D# D C# C B A# A G# G F# F E D# D C# C B A# A OCTAVE 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 FREQUENCY 739.99 698.46 659.26 622.25 587.33 554.37 523.25 493.88 466.16 440.00 415.30 392.00 369.99 349.23 329.63 311.13 293.66 277.18 261.63 246.94 233.08 220.00 207.65 196.00 185.00 174.61 164.81 155.56 146.83 138.59 130.81 123.47 116.54 110.00

(Continued)
DATA >8709 >800A >840A >840B >BEOB >BAOC >860D >820E >800F >8EOF >8D10 >8D11 >8E12 >8014 >8315 >8816 :::.8D17 >8419 >8C1A >851C >801E >8C1F

FREQUENCY CODE >097 >0A0 >OAA >0B4 >OBE >OCA >0D6 >0E2 >OF >OFE >10D >11D >12E >140 >153 >168 >17D >194 >1AC >105 >1E0 >1FC >21B >23B >25D >281 >2A7 :::.2CF >2FA >327 >357 >38A >3C0 >3F9

Anal
>8B23 >8D25 >8128 >872A >8F2C >8A2F >8732 >8735 >8A38 >803C >893F

NOTE: If you need to find a note that is a half-step higher than a given note, you can use the following formula:

(Old Frequency) * 1.059463094 = New Frequency


For example, to find the frequency of a note a half-step higher then Middle 'C':

(523.25) * 1.059463094 = 554.37

10

THE LINE-BY-LINE ASSEMBLER


Although the disc based Editor/Assembler is the most commonly associated package for programming in assembly language, you can also program using the cassette based Line-by-Line assembler in conjunction with the Mini Memory Module. This chapter will attempt to explain the differences in each, as well as how programs written for the Editor/Assembler may be modified for the Line-by-Line assembler. The first major difference encountered is the fact that the Line-by-Line assembler assembles each line of code as soon as it is entered. This is opposed to the disc based Editor/Assembler which assembles the entire source listing at one time after it has been written. The Line-by-Line assembler provides a 9-page text buffer which allows you to scan previously entered lines of code. You can scroll through the pages of the text buffer by using the up and down arrow keys. One advantage of learning assembly language on the Line-by-Line assembler is that you get to see what values are placed into memory as soon as a line of source code is entered. This gives you much greater insight into the workings of the computer and how the instructions affect it.

-139-

140

THE LINE-BY-LINE ASSEMBLER

ic."_c"

-T- IHI

ecia_wc

oppla e -renimlaml-

As with the Editor/Assembler each source code statement is made up of four fields. These fields are named and arranged as follows: LABEL OPCODE OPERAND COMMENT If you do not specify a LABEL then you must leave a space before typing in the OPCODE. If you use a LABEL the first character must be alphabetic. The second may be any alphanumeric character. The LABEL field when using the Line-by-Line assembler is limited to 2 characters in length. This is our first major difference over the Editor/Assembler which can have LABELS up to 6 characters in length. The OPCODE, OPERAND and COMMENT fields are all constructed as outlined in section 3.3 of Chapter 3.

10-1

irNBlarlEgt.

EllI

T- I",,,

There are 7 assembler directives that are recognized by the Line-by-Line assembler. They are:

AORG BSS DATA END EQU TEXT SYM

Absolute ORigiN Block of memory Starting with Symbol Word definition (initialization) END program Let a LABEL represent a constant String constant definition (initialization) Call up SYMbol table

The Directives BSS, DATA, EQU and TEXT are used exactly as outlined in Chapter 5 entitled 'ASSEMBLER DIRECTIVES'. The functions of the remaining directives are outlined in the following sections.

CIACJORG) PrEcOOL_JUM DIRIIBIINI


You will not need to use this directive much when programming with the Editor/Assembler. However, you will find it indispensable if you attempt to program using the Line-by-Line assembler. The AORG directive is used to change the value of the Location Counter (which is always an even address). In this way you can jump to any memory location you want in order to alter or review its contents. For example, if you type:

AORG

>7D00

the Location Counter will now be set to location >7D00 and the contents of this location will be displayed. If you were to

THE LINE-BY-LINE ASSEMBLER

141

type in a new source statement and press enter memory location >7D00 would now contain the new value and the Location Counter would advance to address >7D02. There are basically two main uses for the AORG directive. The first is to point to where you begin entering your program. The second use is to correct errors in the code after you have entered them. To illustrate these two points consider that we are entering the following program where #### represents whatever number happens to be held in a paticular address:

Location & Contents

Instruction

Comments

MOMS *CM
7D00 0000 7D20 0201 7D22 7D00

MW

AORG BSS LWPI LI


LI

>7D00 32 MW R1,30 R2,64 R3,96 0S1

* Go to this address to load program. * Reserve my workspace area. * Put pointer to workspace. * Load a value into R1. * Load a value into R2. * Load a value into R3. * Branch & Link with subprogram S1.

Mw

'! -5

tAt,-)
41

7D24 7D26 7D28 7D2A 7D2C

0201 001E 0202 0040 0203

4s o
Rt

LI BL

7D2E 0060 7D30 06A0 7D32R0000

7D34

Lets say we have reached this point on entering our program and found that we have made a mistake; instead of loading a value of 30 into R1 we wanted instead to load a value of 32. To get back to address :>7D24 and change the value we use the AORG directive as illustrated below:

7D34 7D24 7D26 7D28 7D34

0000 0201 0020 0202 *C.

AORG LI AORG

>7D24 R1,32 >7D34

* Return to address of mistake. * Insert corrected code. * Go back to where we left off. * Continue entering program.
B Ise MEI 01 L.. "1". Pt El L.. IE

ID I 3F " IAN

When programming with the Line-by-Line assembler you will specify symbols for operands that have not yet been defined. For example, you may write the instruction JMP S1 where S1 is a destination further along in the program (a point you have not reached to type in yet). The Line-by-Line assembler must keep track of these references somewhere until they are defined by you. These references are kept in a SYMBOL TABLE until you resolve them.

142

THE LINE-BY-LINE ASSEMBLER

By typing in SYM you can call up the Symbol Table to review references which are unresolved. There are 3 categories within the Symbol Table. These categories and their contents are outlined in Table 10.0. TABLE 10.0 CATEGORIES OF THE SYMBOL TABLE Category RESOLVED REFERENCES Contents These are any symbols that have already been defined. These are any symbols that are undefined and are not referenced by a jump instruction. These are any symbols referenced by a jump instruction.

UNRESOLVED REFERENCES (WORD)

UNRESOLVED REFERENCES (JUMP)

To see how the SYM directive works lets consider the following example: Location & Contents

Instruction AORG BSS LWPI LI EQU BL JMP SYM >7D00 32 MW R1,A1 >0400 @S1 S7

Comments * Starting address of program. * Reserves workspace area. * Load pointer to workspace area. * Load R1 with undefined data. * Define Al. * Branch & Link to undefined point. * Jump to undefined destination. * Now call up Symbol Table.

7D00 0000 MW 7D20 0201 7D22 7D00 7D24 0201 R0000 7D28 0202 AI 7D26 *0400 7D28 06A0 7DRCR 1OFF 7D2E ####

RESOLVED REFERENCES MW-7D00 A1-0400 UNRESOLVED REFERENCES (WORD) S1-7D2A UNRESOLVED REFERENCES (JUMP) 97-7D2C 7D2E **WI * Ready for next instruction.

If a category has no symbols associated with it, that category is not printed on the screen. If all three categories are empty, the SYM directive is erased and the assembler waits for you to

THE LINE-BY-LINE ASSEMBLER

143

enter the next instruction. A maximum of 32 unresolved references can be displayed by the Symbol Table.

camp) amp P.Frole2bm & am ANBaamwc


The END directive signifies to the computer that this is the point that your program will end. If you press ENTER after using the END directive you will exit from the assembler. If you press any other key, the END directive is erased and you can keep on entering source code.

After you enter the END directive the statement: #### UNRESOLVED REFERENCES

will be displayed on the screen where #### is the number of references that you have not yet resolved. You must go back and figure out which ones they are (by using the SYM directive) and resolve them before attempting to exit from the assembler.

10-12 laniirime
The assembler retains some of the source code in a nine-page buffer which you can review by using the up and down keys to scroll the screen. When the buffer is filled the assembler scrolls back onto the screen to indicate that the buffer is full. Any additional instruction that are entered will overwrite previously written lines in the buffer. Because of this it is a good idea for you to keep a written copy of your source code so that you can refer to it when programming.

Once you start typing a line you cannot "back-up" with the arrow keys to correct a typing error. If you have not pressed "ENTER" you can delete the whole line by pressing "ERASE" and then retyping the entire line correctly. If you have already pressed ENTER then you have to return to that address by way of the AORG directive to change it. If you do not use the label field you can move right to the OPCODE field by simply pressing the SPACE BAR once. You can then move to subsequent fields by pressing the SPACE BAR again.

144

THE LINE-BY-LINE ASSEMBLER

1 C), ... 7.7.=

I a Ft: Fc C II FC

IHI IA NI ID L_. I NI ID

When entering source statements, the Line-by-Line assembler will display an ERROR message under one of three conditions: 1. If you attempt to redefine a previously defined label. For example:

AORB >7D00 7D00 0200 MW BSS 32 7D20 02E0 LWPI MW 7D22 7D00 7D24 0200 MW *ERROR*
2. If you attempt to enter an undefined opcode or directive. For example:

7D00 0200 MW BSS 32 7D20 02E0 LWPP *ERROR*


3. If you attempt to exceed the reach (256 bytes) of a jump instruction. For example:

7D00 ####

JO] JI

. 7E02 #### JI CLR R1 7D00 *R-ERROR*


NOTE: If you even suspect that a jump instruction to an as yet undefined label might possibly be out of range (that is more than 256 bytes away) you would be better off using a B (branch) instruction. If you did not you couldn't go back later because a Branch requires 4 bytes The of memory while a jump instruction requires only 2. following illustrates these points:

THIS WAY 7D00 7D02 7D04 7D06

NOT THIS WAY 7D00 #### JEQ JI . . .

#### JNE$+6 0460 B @JI 7E02 COB1 MOV R1,R6

7E02 #### JI CLR R1


1 0 - -41-T. El

7E02 #### JI CLR R1

IR: la IF' la IR la N11 IC la ./ .13 la F-- I INII I -1- I C3 INI "T ink 1E4 It_ la

Once you have finished entering your program you must also enter the program name and location of its starting point in the REF/DEF table so that mini memory module can find it.

THE LINE-BY-LINE ASSEMBLER

145

The following is a short program that will print a message on the screen. We will then demonstrate how to use assembler directives to enter its name and starting point in the REF/DEF table: AORG >7D00 7D00 #### WS BSS 32 7D20 #### MW EQU >6028 * EQUATE VMBW UTILITY. 7D20 484F Al TEXT 'HOW ARE YOU?' * MESSAGE TO DISPLAY. 7D22 5720 7D24 4152 7D26 4520 7D28 594F 7D2A 5535 7D2C 02E0 ST LWPI WS * POINTER TO WORKSPACE AREA. 7D2E 6028 7D30 0200 LI R0,138 * SCREEN TABLE LOCATION. 7D32 008A 7D34 0201 LI R1,A1 * BEGINNING OF MESSAGE. 7D36 7D20 7D38 0202 LI R2,12 * # OF BYTES TO WRITE. 7D3A 000C 7D3C 0420 BLWP @MW * BRANCH TO VMBW UTILITY. 7D3E 6028 7D4OR1OFF JMP $ * HOLD DISPLAY ON SCREEN. 7D40*1OFF 7D42 END Assuming that you have just entered the preceding program exactly as written and have not exited from the assembler, the screen will appear as follows: 7D42 #### END 0000 UNDEFINED REFERENCES Do not press ENTER at this point (if you do you will exit from the assembler). Instead you should enter the following code to place the program name and starting location in the REF/DEF table so that you may run the program: 7D42 #### AORG >701C >7D42 is the first address that is not used in your program. That is, it is the First Free Address in the Module (FFAM). #### represents whatever value happens to be contained in address >7D42. Address >701C holds the FFAM. 701C #### #### represents the address of the old FFAM. We need to put the new FFAM (>7D42) here.

146

THE LINE-BY-LINE ASSEMBLER

701C

7D42

DATA

>7D42

Remember, FFAM is the First Free Address that follows your program, in this case >7D42. Address >701E holds the Last Free Address in the Module (LFAM). Subtract this value from the FFAM; if the difference is 7 bytes or more, you have enough room to insert your program name.

701E

7FE8

701E

7FE0

DATA

>7FE0

Subtract 8 bytes from the old LFAM and place the result at address >701E like we have done here by using the DATA directive. Location counter advances to here displaying any data located at this address. We now need to jump to the REF/DEF table and enter our program name.

7020

####

7020

#### AORG

>7FE0

Jump to new entry point in REF/DEF table. >7FE0 #### Data at this address is displayed. Enter the program name as PRINT1. The program name must be exactly 6 characters long. The characters making up the name are stored in six bytes beginning at location >7FEO. Location counter advances to this next location, where we will define the 2-character entry point into our program.

7FE0 7FE2 7FE4

5052 TEXT 494E 5431

'PRINT1'

7FE6

####

7FE6

7D2E

DATA

ST

Entry point at where we want program to start running. Enter the END directive and press ENTER to leave the assembler.

7FE8

####

END

We can now run this last program by selecting the RUN option from the MINI MEMORY selection list and typing in PRINT1 for the PROGRAM NAME? prompt and pressing ENTER.

THE LINE-BY-LINE ASSEMBLER

147

To summarize, in order to run your assembly program you must: 1. 2. Place new FFAM at address >701C. Compare new FFAM with LFAM to see if there is a difference of 7 bytes or more. If there is then you can proceed. Subtract 8 bytes from old LFAM and place the resulting value at address <701E with a DATA directive, Jump to new LFAM and by using a TEXT directive enter your program name which must be exactly 6 characters in length. Define the entry label into your program with a DATA directive at address LFAM+6.

3.

4.

5.

If you have a disk memory system, you can use the LOAD AND RUN option of the MINI MEMORY module to execute assembly programs that were written using the Editor/Assembler system. When the minimemory comes across a BLWP @VMBW instruction while it is loading from a disk system, it will look up the address it needs in order to use the required utility. It will do this with all subsequent utilities it encounters. Thus, even though you can not create a program with the lineby-line assembler using the instruction BLWP @VMBW you can RUN programs that contain these symbols with the mini-memory module when the LOAD AND RUN option is used. All predefined symbols in the Editor/Assembler will load correctly into the Mini-Memory Module because they are all predefined in an internal table used by the loader.

1 0 .. 'ffi

Pt 'V I INI e IF* Fc C3 B IR 4:=11 FIB

You can save your assembly language program on cassette tape in the following manner: 1. 2. 3. Select EASY BUG option from the selection menu. Use the S command. You can enter the actual starting and ending address of your program, but it is recommended that you enter a starting address of >7000 and an ending address of >7FFF in order to include the REF/DEF table and pointers. If you do not do this you will have to re-enter the program name in the REF/DEF table every time you load the program.

148

THE LINE-BY-LINE ASSEMBLER

i (7.) -

e.

ul -r

1 L.

x ir "Yr IF"Fc Dia IR ens Pi'l

All the utility programs discussed in chapter 6 are available when using the Line-by-Line assembler. However the Line-by-Line assembler does not recognize the predefined symbols that the Editor/Assembler package does. With the Line-by-line assembler you simply cannot reference the needed utilities, you have to branch directly to the address the utility is located at. The following routine is an example of how utility programs are accessed when programming with the Line-by-Line assembler.

Location & Contents

Instruction AORG >7D00 BSS 32 LWPI MW EQU >6018 CLR R1 MOVB R1,@>837C BLWP @GP DATA >0034 END

Comments

7D00 7D20 7D22 7D24 7D24 7D26 7D28 7D2A 7D2C 7D2E 7D30

*Mt* 02E0 7D00 41#404) 04C1 D801 837C 042A 6018 0034 ####

MW

* *
* GPLLNK begins @>6018 * Set status byte=0 * * * BL with GPLLNK * Accept tone routine * Exit assembler

GP

This short program uses an equate directive to create a symbol (GP) for the GPLLNK utility which begins at address >6018. Of course, the program could have just as easily referenced the address directly. The following table lists the available ROM utilities and their respective addresses.

Address >6018 >601C >6020 >6024 >6028 >602C >6030 >6034 >6038 >603C >6040 >6044 >6048 >604C >6050 >6FOE >6FFF

TABLE 10.1 ROM UTILITY LOCATIONS E/A Symbol Utility


GPLLNK XMLLNK KSCAN VSBW VMBW VSBR VMBR VWTR DSRLNK LOADER NUMASG NUMREF STRASG STRREF ERR Link to GROM routine Link to ROM routine Keyboard scan routine VDP single byte write VDP multiple byte write VDP single byte read VDP multiple byte read Write to VDP Register Device service routine link Link to tagged object loader Numeric assignment routine Get numeric parameter String assignment routine Get string parameter Error reporting routine Beginning of REF/DEF Table End of REF/DEF Table

11

CONVERTING BASIC TO ASSEMBLY LANGUAGE


Using a high level language such as BASIC or xBASIC to create a program is relatively easy. The sprite capabilities and the clear straight-forward instruction set give you a great deal of control during program construction. In fact, in most applications BASIC is ideally suited over most other languages for programming. However, when fast-executing arcade style games or other similarly designed programs are needed, BASIC can be intolerable slow. To overcome this speed barrier, we must deal on a level much closer to the level the computer actually communicates on. That is why we write this type of program in assembly language. Assembly language executes at many times the speed of BASIC. Unfortunately, assembly language for many people is much more difficult to work with. One way to circumvent this difficulty is to first write the program in BASIC or xBASIC and then translate that working program into the much faster assembly language. This chapter covers some of the more common BASIC and xBASIC commands, arranged alphabetically. Each command is followed by the source code which duplicates its function. Often, because assembly language is so much freer then BASIC, there will be several ways to accomplish the same task. Of these choices one might be faster, one may take up less memory, and one might be easier to program and understand. When presented with these alternatives, I have selected the example routines which are easiest to program and understand.

-149-

150

CONVERTING BASIC TO ASSEMBLY LANGUAGE

Pk L_ L__ cLE fnt Fc

The CALL CLEAR BASIC routine clears the screen by placing a space character in all screen positions. To understand how assembly language accomplishes this we must first understand how the compute creates a 'screen'. The computer has no concept of a screen; it views the screen as one continuous series of memory locations. There are no rows and columns, only 768 possible character locations numbered beginning at the upper left of the screen at 000 and continuing to the bottom right hand corner 767. These memory locations are in VDP RAM beginning at address >0000. Figure 11.0 illustrates this below:

FIGURE 11.0 1 1 1 1 000 001 002 003 004 005 . . 032 033 034 035 064 065 066 . . . 096 . . 1 . 1 . 1s . si .

NUMBERED SCREEN LOCATIONS . . . . . . . . . 029 030 031 1 062 063 1 . . . 095 1 . . . . ,. . s

1 1 s 1
i

. . .
.

. . . .
.

1 736 .

767 1

To convert a BASIC row and column position into a assembly language graphic screen position we use the following algebraic expression:

C C + (R*32) 3 = SP

Where 'C' is the column number, 'R' is the row number and 'SP' is the resulting screen position. For example, to find the screen position of (5,7) we simply plug in the values:

E 5 + (7*32) 3 = 229

CONVERTING BASIC TO ASSEMBLY LANGUAGE

151

Clearing an entire screen is accomplished by placing a space character (32 or >20) in all successive screen locations as demonstrated in the following routine:

001

*********************************************************** * 002 * * CALL CLEAR 003 *

* * This module will place a space character in all * * screen positions. * * *********************************************************** DEF BEGIN 008 REF VSBW 009 * Reserve memory for my workspace. 010 MYREG BSS 32 011 * * Set pointer to workspace area. 012 BEGIN LWPI MYREG R0,0 * First screen position to print to. 013 LI R1,>2000 * Load space character. 014 LI R2,767 * Load our count register. LI 015 * Place character on screen. BLWP @VSBW 016 LOOP * Increment screen position by 1. 017 INC RO * Decrement our count register. DEC R2 018 * See if whole screen filled. JGT LOOP 019 020 * * End program. END BEGIN 021 004 005 006 007
Lines 008-012 reserve memory for the Workspace Registers, set the workspace pointer at the beginning of this work area and reference all needed utility programs. Line 013 is the beginning of the working part of the program. It loads RO with the first screen position to receive a blank character (position 000). Line 014 loads character 32 (the blank space character) into the left byte of R1 as this is the byte that VSBW will utilize. Line 015 sets up R2 as a count register that will reach 0 when all screen positions are filled. Line 016 places the character on the screen and is the beginning of our loop. The first time this program runs through the 'LOOP' a blank space character will be written to VDP RAM address 0000. Lines 017 and 018 will increase RO by one and decrease the count register by one. The program will then jump back and write a space character in the next screen location. This will continue until the count register has been decremented to zero. When this happens the program will end. The loop in this program will execute a total of 768 times; filling VDP RAM memory locations 000 through 767 with the value for the space character.

slchL__L__ BFc Ilat..4

The source code used to color the screen in BASIC is the 'CALL SCREEN' statement. It is quite similar to the source code

152

CONVERTING BASIC TO ASSEMBLY LANGUAGE

we used to mimic the CALL CLEAR routine. The difference is that the foreground and background color of the space character has to be redefined before we fill the screen with it. For example, if we make the foreground and background color of the space character black, then fill the screen with it, it will leave the screen appear black. The foreground and background color of a character is altered by changing the values of addresses in the Color Table. The Color Table begins at VDP RAM address >0380 and extends to address >039F. Each byte in the Color Table codes for the foreground and background of a group of eight characters. For example, VDP address >0380 holds the byte that codes for the foreground and background colors of character codes 0 through 7. Address >0381 holds the byte that codes for characters 8 through 15. Address >0382 holds the byte that codes for characters 16 through 23. This continues on until address >039F is reached which holds the byte that codes for the final character codes 248 through 255. Table 11.1 lists the Color Table addresses and character codes each byte holds the color of.

TABLE 11.1 COLOR TABLE ADDRESSES Table Address


>0380 >0381 >0382 >0383 >0390 >0391 >0392 >0393

Char. Codes
0-7 8-15 16-23 24-31 128-135 136-143 144-151 152-159

Table Address
>0384 >0385 >0386 >0387 >0394 >0395 >0396 >0397

Char. Codes
32-39 40-47 48-55 56-63 160-167 168-175 176-183 184-191

Table Address
>0388 >0389 >0390 >0391 >0398 >0399 >0400 >0401

Char. Codes
64-71 72-79 80-87 88-95 192-199 200-207 208-215 216-223

Table Address
>038C >038D >038E >038F >039C >039D >039E >039F

Char. Codes
96-103 104-111 112-119 120-127 224-231 23 , -219 240-247 248-255

The space character is character 32 (HEX >20). Looking at the Color Table outlined in Table 11.1 we see that address >0384 holds the byte that contains the color code for character 32. As we already know there are eight bits in a byte. In the case of a color byte the left most four bits (4 most significant bits) code for the foreground color, while the right four bits (4 least significant bits) code for the background color. From this information we know that if we place a value of >Fl at address >0386 it will set characters 48 through 55 white on black. The following source code can be used to load a value into a color table address. In this case characters 32 through 39 are set black on black.

CONVERTING BASIC TO ASSEMBLY LANGUAGE

153

001 003 004 005 006 008 009 010 011 012 016 017 018 019 020 021 022 023 024 025 026 027

********************************************************** * * CALL SCREEN(2) * * PROGRAM MODULE TO LOAD VALUE (BYTE) INTO THE COLOR * * TABLE, THEREBY SETTING THE FOREGROUND AND BACKGROUND * * COLOR OF A DESIGNATED CHARACTER SET. ********************************************************** REF VSBW MYREG BSS 32 COLTAB EQU >0384 COLOR DATA >1100 BEGIN LWPI MYREG LI RO,COLTAB MOV @COLOROR1 BLWP @VSBW * LI R0,0 R1,>2000 LI LI R2,767 LOOP BLWP @VSBW INC RO DEC R2 JGT LOOP

Line 010 sets up the Workspace Register area. Line 011 sets COLTAB equal to 0384, the address in the table we want to write to. Line 012 defines the byte we will use, in this case >11, or black on black. Line 016 starts the program proper. Here we load the address of the Color Table into RO. Line 018 moves the byte we are going to write (>11) into the most significant byte of R1. Line 019 calls the utility program that executes the write. At this point address >0384 now contains the byte >11. Characters 32-39 are now set to black on black. Lines 021 through 027 are just the CLEAR SCREEN program that prints the space character in all screen positions, but now that character is set to black on black. The screen is now totally black except for the upper and lower border which can be changed by writing a value to VDP Register 7.

I) 1

e IF" L.. ink "Ne enCir

To display a message somewhere on the screen in xBASIC you use the simple command:

100 DISPLAY AT(4,5):"HIGH"


which will put "HIGH" on the screen with the first letter beginning in column 4 row 5 of the screen. As already mentioned, the computer regards the screen as a series of memory locations

154

CONVERTING BASIC TO ASSEMBLY LANGUAGE

numbered 000 to 767. To convert a row and column location into its memory location equivalent use the algebraic expression: C C + (R*32) 3 = P where C is the column, R is the row, and P is the assembly language memory location. Thus location (4,5) becomes: C4+(5*32)]=164 Now that we know the location on the screen where we want to put the message, we need to know how to store the message in the program until we print it out. This is done through the use of a "TEXT" directive. The following source code outlines the procedure to print something on the screen: 001 003 004 005 007 008 009 010 011 012 013 014 015 016 017 ************************************************** * DISPLAY AT(6,3):"HOW ARE YOU?" * * * PROGRAM MODULE TO PRINT A STATEMENT IN A * * DESIGNATED SCREEN POSITION. ************************************************** REF VMBW MYREG BSS >20 ADDR1 TEXT 'HOW ARE YOU?' * Message to print. * BEGIN LWPI MYREG * E6+(3*32)3 Screen location. R0,102 LI R1,ADDR1 * Load message. LI * # of characters to write. LI R2,12 BLWP @VMBW * Hold display on screen. JMP $

'CALL CAAAIR This BASIC statement redefines a specified character using a 16 character HEXadecimal coded string. For example character 33 C>213 is the ASCII value for the exclamation point (!). If we enter the statement: 100 CALL CHAR(33,"FFFFFFFFFFFFFFFF") then character 33 is redefined as solid square (all areas shaded). If we wanted to redefine a character into a ball shape, we could use the procedure on the following page which outlines a grid to help us create our pattern.

CONVERTING BASIC TO ASSEMBLY LANGUAGE

155

HEX CODE 1 1 IXIXIXIX1 1 1 IX:XIXIXIXIX1 I


IXIXIXIXIXIXIXIX1 IXIXIXIXIXIX:XIX1 :XIXIXIX:XIXIX;X: IXIXIXIXIXIXIXIX1 1XIXIX:XIXIX: 1 1 IXIX:XIX1 1

>3C >7E >FF >FF >FF >FF >7E >3C

From the figure above it can be seen that the pattern identifier for the 'BALL' is "3C7EFFFFFFFF7E3C". We now construct the following statement: 100 CALL CHAR (128,"3C7EFFFFFFFF7E3C") Which defines character 128 as our "ball". We can then place the ball anywhere on the screen with a CALL HCHAR statement. The complete code is thus: 100 CALL CHAR(128,"3C7EFFFFFFFF7E3C") 110 CALL HCHAR(4,10,128,1) To understand how assembly language accomplishes the same task we must know where the computer stores patterns. It holds them in a Pattern Descriptor Table. This table begins at address >0800 and extends through to address >OFFF in VDP RAM. Each pattern requires eight bytes to define one character. The pattern of character 0 occupies addresses >0800 through >0807, character 1 occupies addresses >0808 through >080F, character 3 occupies addresses >0810 through >0817 and this continues until the last character, character 256, is reached which occupies addresses >0FF8 through >OFFF. To quickly find which address begins the code for which character, you can use the following formula: E 2048 + ( C*8 ) 3 = A Where 'C' is the decimal value of the character and 'A' is the decimal value of the desired address. Using this formula we can find that the address that begins the description of character 128 E>803 is : E 2048 + ( 128 * 8 ) 3 = 3072 which is VDP address >OCOO.

156

CONVERTING BASIC TO ASSEMBLY LANGUAGE

Now that we know the pattern identifier for a ball and the address of where that pattern belongs for character 128, we can write a translation of the following BASIC code: 001 002 003 004 005
006

********************************************************** * * * 100 CALL CHAR(128,"3C7EFFFFFFFF7E3C") * * * 110 CALL HCHAR(4,10,128,1) * * **********************************************************

007 008 009 010 011 012 013 014 015 016 017 018 019 020 021

REF VMBW,VSBW MYREG BSS 32 * PATTAB EQU >0000 * E20484-(C*8((3=0000 PAT DATA >3C7E,>FFFF,>FFFF,>3C7E * "BALL" pattern * START LWPI MYREG * Loads the pattern for the balll LI RO,PATTAB * into the Pattern Descriptor * Table. LI R1,PAT * . LI R2,8 BLWP @VMBW * . * LI R0,138 * Places the "ball" (character 128) * on the screen in position (4,10) LI R1,>8000 BLWP @VSBW * ' JMP $ * Hold display on screen.

By adding a few additional lines of code we can repeat the pattern any number of times in the horizontal direction. The following additional lines of source code when placed in the program above will simulate the BASIC statement:

CALL HCHAR(4,10,128,8)
Replace lines 018 through 025 with the following code:
.

018 LI R0,138 019 R108000 LI * R2,8 020 LI 021 LOOP BLWP @VSBW * * RO 022 INC * DEC R2 023 * 024 JGT LOOP 025 *

Count register: loop 8 times. Put character on screen. Next position to place character. Decrease count register. Check if all 8 characters are on screen, if not loop again.

To translate the VCHAR statement requires only a slight modification of the code for the HCHAR statement as illustrated on the next page (note only line 022 was altered):

CONVERTING BASIC TO ASSEMBLY LANGUAGE

157

018 019 020 021 022 023 024 025

LOOP DEC *

LI LI LI BLWP AI R2 JOT

R0,138 R10.8000 R2,8 @VSBW * Increment to screen position R0,32 * below last one written to. LOOP

You will notice that line 022 adds 32 to the current screen position that you are writing to. In this way the next screen location specified is the one directly under the previous one. This source code, when added to the program lines previously mentioned, is a direct translation of the BASIC statement: CALL VCHAR(4,10,128,8) In fact, by altering the amount that yoU increase *or decrease RO in your program you can make the patterns print up, down, diagonally or virtually any way by altering this one line of source code.

This BASIC command sets the keyboard to be tested and returns two variables based on input from the keyboard. The first variable tells you whether or not a key has been pressed, while the second variable returned gives you the value of the key pressed. There is a utility program in assembly language that you can use to return keyboard input. This utility is referred to as KSCAN. In order to use the KSCAN utility, you have to first determine where you want the input to come from. You can input from the whole keyboard, right side of the keyboard, left side of the keyboard or input from the joysticks. Address >8374 contains the byte that determines which keyboard device you want to select. The following values select for desired keyboard devices:

>00 Checks the entire keyboard. >01 Checks left side of keyboard and joystick #1. >02 Checks right side of keyboard and joystick 0@2
From the above table we see that if a value of >01 is placed at address >8374 the KSCAN routine will check for input from the left side of the keyboard as well as input from joystick #1. When a key is pressed its ASCII value is placed at address >8375. If no key was pressed this address will contain >FF. Lets

158

CONVERTING BASIC TO ASSEMBLY LANGUAGE

consider a program where input from the keyboard is used to perform some task. The following BASIC program will print a message on the screen based on which arrow key has been pressed. 100 110 120 140 160 180 190 200 CALL KEY (1,KEY,STATUS) IF STATUS=0 THEN 100 IF KEY=5 THEN A$="UP KEY PRESSED" IF KEY=3 THEN A$="RIGHT KEY PRESSED" IF KEY=0 THEN A$="DOWN KEY PRESSED" IF KEY=2 THEN A$="LEFT KEY PRESSED" DISPLAY AT (4,10):A$ GOTO 100

This program will display the "UP KEY PRESSED" message if the up 'E' key is pressed. If the 'D' key is pressed the "RIGHT KEY PRESSED' message appears. This continues on for the other two keys (X & S). The assembly language translation of this program illustrating the CALL KEY function is as follows: 001 002 003 004 005 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 *********************************************************** * CALL KEY (1,KEY,STATUS) * * This module will input from the arrow keys (E,D,X,S) * * and display a message indicating the pressed key. * *********************************************************** DEF * Reference needed utilities. BEGIN * Address to select keyboard REF KSCAN,VMBW * Holds ASCII # of pressed key KBOARD EQU >8374 >8375 KEY EQU * * * ASCII values KEYUP BYTE 5 of E, D, X and S * KEYRT BYTE 3 * keys KEYDN BYTE 0 * KEYLT BYTE 2 * No key pressed value HEXFF BYTE >FF * ONE BYTE 1 * TEXT 'UP KEY PRESSED ' UP RIGHT TEXT 'RIGHT KEY PRESSED' 'DOWN KEY PRESSED ' DOWN TEXT TEXT 'LEFT KEY PRESSED ' LEFT EVEN * MYREG BSS >20 * BEGIN LWPI MYREG MOVB @ONE,@KEYBOARD * Check left side of keyboard. * Check for keyboard input. BLWP @KSCAN LOOP @HEXFF,@KEY * Was a key pressed? CB * JEQ LOOP * Compare to see which CB @KEYUP,@KEY * arrow key was pressed. JEQ PUP

CONVERTING BASIC TO ASSEMBLY LANGUAGE

159

035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054

CB JEQ CB JEQ CB JEQ B PUP LI B PRIGHT LI B PDOWN LI B PLEFT LI B * PRINT LI LI BLWP B

@KEYRT,OKEY PRIGHT @KEYDN,@KEY PDOWN @KEYLT,@KEY PLEFT @LOOP R1,UP @PRINT R1,RIGHT @PRINT R1,DOWN @PRINT R1,LEFT @PRINT R0,138 R2,17 @VMBW @LOOP

* * * * * * * * * * * * * * *

If key not found, LOOP again. Load correct message into Ri

* Print message on * * screen * Repeat program * End program.

Pt L_. L_.

Jr DV

If you place a value of >01 at address >8374 the KSCAN routine will check for input from joystick #1 (as well as from the left side of the keyboard). If you place a value of >02 at address >8374 the KSCAN utility will check for input from joystick #2 (as well as from the right side of the keyboard). Input from joysticks is placed into CPU addresses >8376 (Y-position) and >8377 (X-position). Table 11.2 lists the possible values that may be returned.

TABLE 11.2 JOYSTICK INPUT Y POSITION


Joystick Y Position CENTER UP DOWN Value Returned
>00

Address >8376 >8376 >8376

>04 >FC

160

CONVERTING BASIC INTO ASSEMBLY LANGUAGE

TABLE 11.3 JOYSTICK INPUT X POSITION


Joystick X Position CENTER RIGHT LEFT Value Returned :>00 >04 >FC Address >8377 >8377 )3377

Lets assume that a value of >01 is at address >8374. Lets also assume that joystick #1 is in the DOWN-RIGHT position. When the KSCAN routine is called a value of -4 (:>FC) is placed at address >8376 and a value of 4 (>04) is placed at address >8377. The following xBASIC program will print out a message on the screen reporting on the current position of joystick #1. It is very similar to the CALL KEY program that was presented earlier.

100 110 120 130 140 150 160 170 180 190 200 210

CALL JOYST(1,JOYX,JOYY) IF JOYY=0 AND JOYX=0 THEN A$="CENTER" IF JOYY=4 AND JOYX=0 THEN A$="UP" IF JOYY=4 AND JOYX=4 THEN A$="UP-RIGHT" IF JOYY=0 AND JOYX=4 THEN A$="RIGHT" IF JOYY=-4 AND JOYX=4 THEN A$="DOWN-RIGHT" IF JOYY=-4 AND JOYX=0 THEN A$="DOWN" IF JOYY=-4 AND JOYX=-4 THEN A$="DOWN-LEFT" IF JOYY=0 AND JOYX=-4 THEN A$="LEFT" IF JOYY=4 AND JOYX=-4 THEN A$="UP-LEFT" DISPLAY AT(4,10):A$ GOTO 100

The above program will display a message on the screen reporting on the current position of joystick #1. The source code that follows is a direct translation of the previous xBASIC program. You may wish to study it in great detail as most game programs utilize a joystick input of one type or another.

001 003 004 005 007 008

*********************************************************** * CALL JOYST(1,JOYx,JOYY) * * This module will input from joystick #1 and display its * * * current position on the screen. ***********************************************************

009
010 *

DEF REF

START KSCAN,VMBW

CONVERTING BASIC TO ASSEMBLY LANGUAGE

161

011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061

KBOARD JOYY * JOYUP JOYUR JOYRT JOYDR JOYDN JOYDL JOYLT JOYUL JOYCT HEXFF ONE * UP UPRT RT DNRT DN DNLT LT UPLT CENTER EVEN * MYREG * BEGIN * START

EQU EQU BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE TEXT TEXT TEXT TEXT TEXT TEXT TEXT TEXT TEXT BSS LWPI MOVB BLWP C JEQ C JEQ C JEQ C JEQ C JEQ C JEQ C JEQ C JEQ LI B

>8374 >8376 4,0 4,4 0,4 -4,4 -4,0 -4,-4 0,-4 4,-4 0,0 :OFF 1

* Address of keyboard device select. * Joystick input "Y" value. * * * * * * * * * * * * * * .* * * * * JOYSTICK POSITION MESSAGES

'UP 'UP-RT 'RIGHT 'DOWN-RIGHT 'DOWN 'DOWN-LEFT 'LEFT 'UP-LEFT 'CENTER 32

* Reserve space for Workspace Registers. MYREG * Load pointer. @ONE,@KBOARD * Select keyboard device. @KSCAN @JOYY,@JOYUP P1 @JOYY,@JOYUR P2 @JOYY,@JOYRT P3 @JOYY,@JOYDR P4 @JOYY,@JOYDN P5 @JOYY,@JOYDL P6 @JOYY,@JOYLT P7 @JOYY,@JOYUL P8 R1,CENTER @PRINT * Scan joystick..

* Compare to see what * the X and Y position * of the joystick is. * * * * * * * * * *

162

CONVERTING BASIC TO ASSEMBLY LANGUAGE

062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082

P1
P2 P3 P4 P5 P6 P7 P8 * PRINT

LI
B LI B LI B LI B LI

R1,UP
@PRINT R1,UPRT @PRINT R1,RT @PRINT R1,DNRT @PRINT R1,DN

*
* * * * * * * * Load appropriate message

B
LI B LI B LI LI LI BLWP B END

@PRINT
R1,DNLT @PRINT R1,LT @PRINT R1,UPLT R0,138 R2,10 @VMBW @START BEGIN

*
* * * * * * Display message on * screen. * * Return and check again.

ID I MI
BASIC is a powerful language when it comes to automatic string manipulation, array handling and specific error messages letting you know exactly where you went wrong. The price you pay for these luxuries is that the BASIC program will run very slowly when compared with assembly language. Because array management is not directly handled by the computer when using assembly language, you will have to set memory aside for that purpose. The best way to do this is through the use of the BSS and BES directives, either of these directives will set aside any amount of memory. Handling these 'chunks' is not too difficult, but it may help to use a pen and paper to keep track of your own arrays as you set them up in memory.

IF- C.) Ft INI IE X "T .


The FOR-NEXT statement in BASIC can be used to create a delay loop or a counting loop. For example, if you want to put something on the screen for someone to read you might incorporate a "delay loop" to hold the message on the screen for a period of time. In game programming with assembly language these delays become much more important because the program executes so quickly that an object on the screen could move so quickly that it would de visible only as a blur. The source code on the next page outlines a simple delay loop.

CONVERTING BASIC TO ASSEMBLY LANGUAGE

163

001 ******************************************************* * FOR DELAY=1 TO 1000 :: NEXT DELAY 003 * 005 ******************************************************* 006 . 007 . * For 1 R1,1 LI 008 * To 1000 R2,1000 LI 009 010 DELAY DEC R2 R1,R2 C 011 * Next Delay JNE DELAY 012 . 013 Of course this delay loop will execute much more quickly then its BASIC counterpart. In fact, unless you were looking for it you would probably not even notice this small of a delay! The maximum value we can one in the previous example we can create two registers the next example, the first then R2 clicks in to repeat "loops". 001 003 005 006 007 008 009 010 011 012 013 014 015 use in a single delay loop like the is 32767. To loop with larger numbers working together to keep count. In register counts down from 32767 and the count for a total delay of 98301

******************************************************* * FOR DELAY-1 TO 98301 :: NEXT DELAY * ******************************************************* . LI R2,3 LOOP1 LI R1,32767 * Load a count register. * Load maximum delay. LOOP2 DEC R1 JNE LOOP2 DEC R2 JEQ OUT JMP LOOP1 . OUT

Here we use R2 as our "second count" register and we use R1 as our "primary count" register. Line 009 is the beginning of our loop, R1 is loaded with the maximum signed value it can hold. The next line (010) decrements R1 by one and line 011 tests to see if R1 is zero yet. If not, the program jumps to LOOP2 and decrements R1 again. This continues until R1 is equal to zero, then R2 is decremented. If R2 has been decremented to zero program control jumps to OUT, otherwise the program jumps to LOOP1 and R1 is reloaded and the delay continues.

164

CONVERTING BASIC TO ASSEMBLY LANGUAGE

F- C3Fc-- NI E

X lr 9 -T

PI

For this instruction you just increment your counter register the amount of the step as demonstrated in the following source code: 001 003 005 006 007 008 009 010 011 012 ******************************************************* * FOR DELAY=0 TO 75 STEP 3 :: NEXT DELAY * ******************************************************* R1,0 LI DELAY INCT R1 R1 INC R1,75 CI JNE DELAY

Notice that lines 009 and 010 of the last example increment our count register (R1) a total of three for each pass of the DELAY loop. Take note that this source code could also be written:
0 0 M

008 LI R1,0 009 DELAY Al R1,3 010 CI R1,75 011 JNE DELAY Either version would work equally as well. For very large numbers we can again use two counter registers to keep track of things. Following our first example above we could translate the xBASIC statement FOR 1=10000 TO 0 STEP -1 into the source code: 001 ******************************************************** * 003 * FOR 1=10000 TO 0 STEP -2 :: NEXT I 005 ******************************************************** 006 . 007 . R2,10 008 LI 009 LOOP 1 LI R1,1000 010 LOOP2 DECT R1 JNE LOOP2 011 012 DEC R2 013 JNE LOOP1 Here we see R1 decremented by two after each loop. If you were using the value of "I" for some other procedure in the program you could get it simply by multiplying R1 and R2 together at any point during execution of these loops.

CONVERTING BASIC TO ASSEMBLY LANGUAGE

165

Conditional jumps and compare instructions constitute the primary computing structure in assembly language. It is fairly straight forward and can be easily demonstrated with a translation of the following:

001 003 005 . 008 009 . 200 201 202 203 204 205

********************************************************* * IF DAMAGE=100 THEN SHIP=10 * ********************************************************* DAMAGE SHIP . SUB1 DATA DATA . MOV CI JNE LI MOV RT >0000 >0000 @DAMAGE,R1 R1,100 OUT1 R1,10 R1,@SHIP * * If DAMAGE=100 * Then... . * * ..SHIP=10

OUT1

To add an ELSE to the statement you simply add three additional lines of source code as follows: 001 003 005 . 006 009 . 200 201 202 203 204 205 206 207 206 ******************************************************* * * IF DAMAGE=100 THEN SHIP=10 ELSE SHIP=5 ******************************************************* DAMAGE SHIP DATA DATA . MOV CI JNE LI MOV JMP LI MOV RT >0000 >0000 @DAMAGE,R1 R1,>64 ELSE1 R1,>A R1,@SHIP OUT1 R1,>5 R1,@SHIP

ELSE1 OUT1

DIN GC) B Ul Et In BASIC, you are limited with the GOSUB instruction to test very specific values before proceeding. For example:
100 ON Y GOSUB 200,230,240

In this example Y must be 1 or 2 or 3. Only one branch test is

166

CONVERTING BASIC TO ASSEMBLY LANGUAGE

performed with control returning to the statement just after the GOSUB after that one branch is finished. Also, if Y was not equal to any of the branches (ie: not=1, 2, or 3) an error message would be returned by the computer. Assembly language permits you much greater freedom in programming in that it permits multiply branch testing. In this situation, one, two or all the branches might be executed. Or alternatively, none of the branches may be branched to under certain conditions. The source code on the following page could be found in a game program where some value, perhaps inputed from the keyboard, determines which subprogram is branched to 001 003 004 006 007 008 009 010 011 012 013 014 015 016 017 018 ********************************************************* * * ON VALUE GOSUB 100,200,300 * Program module to perform a multiple branch test * ********************************************************* . . MOV @VALUE,R0 R0,100 CI * See if VALUE=100 JNE NEXT1 * If not, then jump to NEXT1 MISS BL * Branch & Link w/ MISS routine NEXT1 CI R0,200 * See if VALUE=200 NEXT2 JNE * If not, then jump to NEXT2 BL HIT * Branch & Link w/ HIT routine NEXT2 R0,300 CI * See if VALUE=300 JNE OUT * If not, jump to OUT BL KILLED * Branch & Link with KILLED

You will be BLing out of the program and RTing back to within the multiple branch test above to continue until all the branches have been tested. You will have to be careful that your subprograms MISS, HIT and KILLED do not change the value in RO or an accidental triggering of another branch may occur.
C3 INI B C) 11- C)

This is another version of the GOSUB structure we have just covered. The difference is that after one branch meets with a successful test, control jumps back to the point following all the branch tests. 001 002 003 004 005 007 010 011 ********************************************************** * ON GOTO * * This program module allows you to test branches one at * * a time. Program control transfers to a point following * * all branch tests after completion of a subroutine. * ********************************************************** . .

CONVERTING BASIC TO ASSEMBLY LANGUAGE

167

012 MOV @VALUE,R0 013 CI R0,100 014 JNE NEXT1 015 JMP SUBR1 * 016 NEXT1 CI R0,200 017 JNE NEXT2 018 JMP SUBR2 * 019 NEXT2 CI R0,300 020 JNE OUT * 021 JMP SUBR3 * 022 OUT Call subroutines "JMP" to location OUT when finished] Instead of RT, each subroutine in the last example will JMP back to location OUT, which lets the program continue without running through any more tests of the branches. In this way no branch is accidentally triggered if the subroutine were to change the contents of RO. REIM You can make notes directly inside program by preceding them with an asterisk (*). An entire line in a source program may be reserved in this way for comments or notes about your program. Comments also can be made after the operand field in most instructions by spacing once and typing in an asterisk (*) followed by your note or comment. The asterisk serves as a signal to the assembler to ignore the information you have typed. Your remarks remain part of the source code only and are omitted during the assembly process. FZIE -FL.IFP4 There are two return instructions in assembly language. They operate very similar to the way RETURN does in BASIC. THE RTWP takes you back from a subprogram to just after the BL (GOSUB) instruction that sent you to a subroutine. When a BL or BLWP instruction is reached, the address which immediately follows the BL or BLWP instruction itself is placed in R11. That address then stays in RII until a RT or RTWP is encountered. When this occurs, the address is taken from RII and placed into the Program Counter. This transfers program control back to the instruction just after the BL or BLWP line. FZ Ul IN If you are not going from BASIC to an assembly program, but are only running an assembly program by itself, there are basically two ways to run the program using the Editor/Assembler. The first way is to define an entry point with the DEF statement at the

168

CONVERTING BASIC TO ASSEMBLY LANGUAGE

beginning of the program. Using this method you load the object code into the computer using the LOAD and RUN option of the Editor/Assembler module. After the program is loaded you press ENTER and the PROGRAM NAME? prompt appears. You then type in the starting point of program. This entry must match a entry in the DEF statement at the beginning of the program. The second way to run a assembly language program is to place the entry point of the program in the operand field of an END directive. When this program is loaded it will start running automatically as soon as the file is loaded. The following illustrates these two methods of starting assembly programs: DEF START 001 . . . . . . 020 START . Using this procedure you must load the file that contains the object code with the LOAD and RUN option of the Editor/Assembler. When the file is loaded hit ENTER and the PROGRAM NAME? prompt appears. You then type in the entry point in your program which also must be found in a DEF statement at the beginning of the program. . 020 START . . . . END START 800 Placing the entry point to your program in the operand field of a END statement causes the program to start running automatically as soon as it is loaded with the LOAD and RUN option of the Editor/Assembler.

12 LINKING WITH BASIC


Many times in programming you will want to add an assembly language module to a BASIC program. This has the effect of allowing you to create your "own" BASIC commands which you can use as needed. You can also add fast-executing modules at specific points to speed up program execution. This chapter will discuss in detail the ways in which you can link your BASIC programs with assembly language programs.

-169-

170

LINKING WITH BASIC

Both the Editor/Assembler module and the Mini Memory module provide you with several additional BASIC commands. These commands are designed to aid you in the task of interfacing your assembly language programs with BASIC. Table 12.0 outlines these commands.

TABLE 12.0 BASIC ASSEMBLY LANGUAGE SUPPORT COMMANDS Command


CALL CALL CALL CALL CALL CALL CALL INIT LOAD LINK PEEK PEEKV POKEV CHARPAT

Description
Initializes CPU memory for AL subroutines Load data or AL program into CPU RAM memory. Link BASIC program with AL program. Look at data in a CPU RAM address. Look at data in a VDP RAM address. Load data into VDP RAM. Return the value of a character pattern.

Each preceding BASIC command is discussed in detail in the sections that follow in this chapter.

This command must be called before any assembly language programs command are loaded through the BASIC program. This command should not be called once the assembly language program is loaded or the program will be rendered inaccessible. The CALL INIT command goes through the following procedures when called: 1. Check to see if memory expansion is connected to the console. Loads utility routines from the Editor/Assembler module into the memory expansion starting at address >2000. Loads the REF/DEF tables into the memory expansion at addresses >3F38 through >3FFF.

2.

3.

If you use the command CALL INIT 'with the mini memory module, all programs and data are erased. CALL INIT also initializes CPU RAM for assembly language subroutines and re-initializes the internal tables of the mini memory module. If memory expansion is attached, access is enabled to both the module and memory expansion. If the memory expansion is not connected or turned off, the memory expansion is not recognized. You do not need to use CALL INIT each time you use the module, since it has its own internal power supply. Remember that all data and programs on the

module are lost when you use the CALL INIT command!

LINKING WITH BASIC


IcAPILA..... LAD/ND
There are two ways in which the CALL LOAD command can be used. The first is to load an assembly language object code file, and the second is to load or "poke" data directly into CPU RAM.

171

LADicippItNilB

plEcalcir.

car>

To load an assembly language program (object code) you would use the following format of the CALL LOAD statement:

CALL LOAD("device.filename") where the device.filename is a string expression such as DSK1.FILE1. This file must be object code. You can load more than one object file at a time by separating the files you want by commas as in the following example: CALL LOAD("DSK1.FILE1","DSK1.FILE2")
which loads the two files FILE1 and FILE2 from disk drive 1. Relocatable object code is loaded at the first available address. With no files loaded and memory expansion attached this address is >A000. When using the mini memory module without the memory expansion unit attached this address is >7118, the lowest available address in the module's RAM. Subsequent programs are loaded in a sequential manner, with the next program loaded in memory immediately following the previous program. Absolute code is loaded at the absolute address specified by the object code. Your program should not use absolute code unless extreme care is taken, as loading data into an area of memory used by the TI BASIC interpreter can cause the computer to "crash".

-1PolKINie- EtplcrIA
To load or "poke" data into an area of CPU RAM you would use the following format of the CAll LOAD command:

CALL LOADtaddress,value)
where the address is a decimal number which can be any value from -32768 through 32767. Values 0 through 32767 represent addresses 0000 through 7FFF, while the values -32768 through -1 represent 8000 through FFFF expressed as two's compliment form. In order to find an address above 32767 you must subtract 65536 from it. You can load any number of bytes beginning at an address by specifying the values to load. For example, the statement:

CALL LOAD(-36864,24,13,90)

172

LINKING WITH BASIC

loads the values >18, >OD and >5A into the respective bytes at locations >7000, >7001 and >7002. You can specify more than one poke list by separating the last byte of one poke list and the starting address of the next poke list with a pair of quotes as in the next example CALL LOAD(-36864,24,13,",53248,19) which loads the same values as the preceding example and also loads the value >13 into address >D000. You could also load an assembly language program byte-by-byte in this manner by poking in the various instructions. However to run a machine language program loaded in this manner you would have to enter the program name and starting point into the REF/DEF table so that the computer could find it. You do not need to worry about these steps if your program was loaded by the Editor/Assembler loader since that is done for you. If you are using the Mini Memory Module you should use the procedure outlined on page 144. If you use xBASIC to run your assembly language program you must first perform the following steps: 1. Read the First Free Address in the Module with the CALL PEEK command. The FFAM can be found at address >2028. Read the Last Free Address in the Module. This address can be found at address >202A. Subtract the FFAM from the LFAM. If they differ by at least 8 bytes, there is room to add your program name and address. Use the CALL LOAD command to change the LFAM to a value 8 bytes less then its old value. Use the CALL LOAD command to load the program name (6 bytes in length) starting at the new LFAM followed by two bytes which give the program starting address.

2.

3.

4.

5.

For example, suppose the LFAM is >8000, your program name is FILE. The program begins at addess >8300. You would then load the following information:

CALL LOAD(28700,127,251) CALL LOAD(32763,70,73,76,69,32,32,131,00) / / NAME PADDED TO 6 CHARACTERS

LINKING WITH BASIC

173

IC ALL L_. I INA 1-c::: The CALL LINK command lets you pass control from a BASIC program to an already loaded assembly language program. It also lets you optionally pass a list of parameters from the BASIC program to the assembly language program. The format for the CALL LINK command is as follows:

CALL LINK("program-name","parameters...")
The program-name is a 1 to 6 character string that defines the entry point into the program. It must appear in the REF/DEF Table of the assembly language program that you are trying to link with. The assembly language program must already be in memory (loaded via the CALL LOAD command). The parameters are optional. They allow you to pass string variables, numeric variables, or expressions between your BASIC and assembly language programs. For example, the statement:

CALL LINK("BEGIN",A,D$)
passes control from a BASIC program to the assembly language program BEGIN, with the numeric variable 'A' and the string variable 'D$' passed to it. The CALL LINK command goes through the following operations when called: 1. Check to see if AL program name is 1 to 6 characters in length.
1.)

I... s

If name is right length, the name is looked up in the REF/DEF Table, beginning at the lowest address. The program name is then pushed onto the value stack. note: An error is generated if there are duplicate names in DEF instructions.

3.

If parameters are to be passed the utility will build an argument list. This list identifies the type of arguments and builds a stack entry for each argument. Program control is transferred to the assembly language program through a direct AL "branch" instruction.

4.

174

LINKING WITH BASIC

note: In order to return to your BASIC program, your AL program must preserve and restore the values in Workspace Registers R11, R13, R14, and R15 before ending. 5. At the end of the assembly language program, control will return to the calling BASIC program unless an error has occurred. If an error has occurred, the program branches to an error routine. note: Address >8310 contains the value stack pointer in use by BASIC interpreter. IRAFcrtnkrITEIR IPIABBING WITH iALL... LIINK

Up to 16 arguments can be passed between a BASIC program and an assembly language program. If the parameter is an expression, it is passed by its value, if it is a variable it is passed by name. Any variable except an expression can have its value changed by the assembly language program. This value, in turn, can be passed back to the BASIC program. You can pass entire arrays by enclosing them in parentheses. Arrays with more than one dimension are indicated by placing commas between the parentheses to indicate the number of dimensions. The following is an example outlining several simple variables (simple variables do not include expressions):

CALL LINK("BEGIN",A,B$,SCORE,F$0,0$(0) A = numeric variable B$ = string variable SCORE = numeric variable F$() = one-dimensional array G$(,) = two-dimensional array
If you need to pass variables to your assembly language program but do not need to change their values, surround the variable with parentheses. Arrays however, can not be passed in this manner. For instance, all but the last two in the last example can be passed without having their value changed on return to the calling BASIC program as outlined below:

CALL LINKOBEGIN",(A),(B$),(SCORE))
Also, constants such as SCORE-3, do not have their values changed by the assembly language program on return to BASIC. Arguments are passed to an assembly language through an identifier list in CPU RAM. It is not necessary for you to have a knowledge of how arguments are passed if you use the utilities described in section 13.1 If you want to delve deeper and

LINKING WITH BASIC

175

construct your own utilities, see pages 278-280 of your Editor/Assembler manual.

Pt L_. L_. IR la la Il<


The CALL PEEK command allows you to read bytes of CPU RAM directly into BASIC variables. The following statement is an example of the format of the CALL PEEK command:

CALL PEEK(address,variable....)
where the address is a decimal number which can be any value from -32768 through 32767. Values 0 through 32767 represent addresses >0000 through >7FFF, while the values -32768 through -1 represent >8000 through >FFFF expressed as two's compliment form. In order to find an address above 32767 you must subtract 65360 from it. You can peek into any number of successive bytes of CPU RAM by simply specifying the variables. The following example illustrates how data can be read from CPU RAM:

CALL PEEK(-36864,A,B,C,D)
This statement lets 'A' represent the value held at address >7000, 'B' the value at address >7001, 'C' the value at address >7002 and 'C' the value at address >7003. You can read from more then one address in a single PEEK statement by separating the last variable of one PEEK list and the Beginning PEEK address of the next list with a pair of quotes. This is illustrated as follows:

CALL PEEK(53248,A,B(3),"" 9 -36864,C)


This statement lets 'A' and the third element in the array designated 'B' represent the values at addresses >D000 (53248) and >D001 (53248) respectively.

The CALL PEEKV command is used to read bytes of data from VDP RAM. It works in exactly the same manner as the CALL PEEK command except that CALL PEEKV will read from VDP RAM. The format of the CALL PEEKV is the following:

CALL PEEKV(address,variable,var...)
The address is a decimal number which can range in value from 0 through 16383. The values 0 through 16383 represent addresses >0000 through >3FFF in VDP RAM. If you try to access a higher

176

LINKING WITH BASIC

address then >3FFF the system will crash requiring you to turn the power off and back on again in order to continue. The following example illustrates the use of the CALL PEEKV command:

CALL PEEKV(768,A,B(2),w' , n 10,C)


This statement will read a value from VDP RAM address >0300 into 'A' and a value from VDP RAM addres >0301 into the second element of the numeric array designated 'B'. A value will also be read from VDP RAM address >000A into 'C'.
Po L_ L_ Pa' CII K la V

The CALL POKEV command allows you to read bytes of VDP RAM directly into BASIC variables. It works in exactly the same manner as the CALL POKE command, except that CALLPOKEV will poke data into VDP RAM instead of CPU RAM. The format of the CALL POKEY command is as follows:

CALL POKEV(address,variable...)
where the address is a decimal number which can be any value from 0 through 16383. Values 0 through 16383 represent addresses >0000 through >3FFF. Keep in mind that VDP RAM only has 16K of memory. If you try to poke a value into an address higher than >3FFF, the system will crash requiring you to turn the console off and back on in order to continue. The following example:

CALL POKEV(300,32,32,32,"",5,SCORE)
places the value 32 (>20) in VDP RAM addresses 300 (>012C), 301 (>012D), and 302 (>012E). It also places the value of SCORE in VDP RAM address 5 (>0005).
IC ink L.. L_ IC HI Ink Fc Fs Pp 1-

The CALL CHARPAT command returns a 16-character pattern identifier that codes for the character specified by the character-code. The format of the CALL CHARPART command is as follows:

CALL CHARPAT(character-code,string-variable) where the character-code is any character number from 32 to 159. The pattern identifier codes for the ASCII character set normally occupy character codes 32 through 95, although you can redefine and can be defined through the use of the CALL CHAR command.

LINKING WITH BASIC

177

1p4=%Ftem-IIR F-ABBINie
Besides the additional BASIC commands provided, the Editor/Assembler and Mini Memory module also provide several assembly language utility programs that greatly simplify passing arguments between AL and BASIC. You can also return errors that occurred during execution of an assembly language module. Table 12.1 outlines these utilities. TABLE 12.1 BASIC INTERFACE UTILITIES UTILITY NUMSAG STRASG NUMREF STRREF ERR DESCRIPTION Number Assignment. String Assignment. Number Reference. String Reference. Error reporting,routine.

If you are using the Editor/Assembler these utility programs can be found on the disk labeled 'A' in the file named BSCSUP. They are in relocatable code and are about 900 bytes long. To use them you must include them in a REF statement at the beginning of your program. In order to load them you must place the statement:

CALL LOAD("DSK1.BSCSUP")
in your BASIC program. If you are using the Mini Memory module, the addresses of these utilities can be found on page 148.

Fcinlinix lioc) INic

Iolm

The values of variables passed from BASIC to assembly language programs are stored in the Floating Point Accumulator which begins at VDP RAM Address >834A. Before we progress to the utility programs proper, we must explain radix 100 notation. In radix 100 notation all numbers range from 1.000000000000 through 99.000000000000 multiplied by 100 raised to a power ranging from -64 to 64. Each number is coded for in an 8 byte "value stack" located in VDP RAM. The first byte in the value stack indicates the exponent of the numerical value. If the exponent is positive, the byte

178

LINKING WITH BASIC

value is 64 more than the exponent. If the exponent is negative, the byte value is gotten by subtracting 64 from the exponent. For example, if the exponent is 3, the byte is 67 or >43. If the exponent is -2, the byte is 62 or >3E. If the exponent is negative, the first two bytes are entered in two's-compliment form. After the exponent byte, the remaining seven bytes in the value stack contain the value of the number. No regard is given to the decimal point when transforming numbers into their hexadecimal equivalents. The second through eighth byte for a radix 100 value of:

3 100 x 23.456
is constructed as follows:

3 45 60 00 00 00 00 100 x 23 >43 >17 >2D >3C >00 >00 >00 >00


The following examples illustrates how several different numbers would be written in radix 100 notation and how the value stack would be structures in each case.

TABLE 13.2 EXAMPLES OF CONVERSION TO RADIX 100 NOTATION Decimal Value Radix 100 Notation o 6
60 1,234,560 12,345,600 0* -6 -6C) -1,234,560

Value Stack

6 x 100
o 60 x 100 1.23456 x 100 3 12.3456 x 100 o 0 x 100 o -6 x 100 o -60 x 100
'7
...)

>40 >06 >00 >00 >00 >00 >00 >00 >40 >3C >00 >00 >00 >00 >00 >00 >43 >01 >17 >2D >3C >00 >00 >00

>43 >0C >22 >38 >00 >00 >00 >00 >00 >00 >BF >XX >XX >XX >XX >XX >XX

>FA >00 >00 >00 >00 >00 >00 >00 >00 >00 >00 >00 >00 >17 >2D >3C >00 >00 >00

>BF >C4 >BC >FF

-1.23456 x

100

*Zero is expressed by >00 in the first two bytes & undefined in the remaining 6 bytes.

LINKING WITH BASIC

179

tNi

u rii IA B e

) tNi

u ri r3 a Ft

ALB I

e h4 hi la h4 ir

This utility allows you to assign a value to a variable passed as an arguement via the CALL LINK command of BASIC. Follow the steps outlined below in order to use this utility. 1. Place a value of 0 in RO if the variable is a simple variable. If the variable is an element in an array, place the element number in RO. Note: With OPTION BASE 0 (BASIC default) the array elements are numbered starting at O. If OPTION BASE 1 is selected the array elements are numbered starting at 1. Element numbers for multiple dimension arrays are found by counting through the first level, then the second level and so on. For example, an array defined as X(6,6 1 6) with an OPTION BASE of 0; element number X(3,2,1) is found: 2 1 0 (3 * 7 ) + (2 * 7 ) + (1 * 7 ) = 162 = element # 2. Place the arguement number as a full word in Rl. The arguement number is at it appears in the arguement list of the CALL LINK statement. Note: The arguement number is the order in which the arguement appears in the parameter list of the CALL LINK statement. For example, in the statement: CALL LINK("BEGIN",X,Y,Z) 'X' is arguement #1, 'Y' is arguement #2, and 'Z' is arguement #3 3. Enter the value you want to assign into the Floating Point Accumulator which begins at address >834A. The number must be in Radix 100 notation. Access the utility by BLWP @NUMASG using the Editor/Assembler or BLWP @6040 if you are using the Mini Memory Module.

4.

For example, the statement CALL LINK("FILE1",X,Y,Z) when encountered in BASIC would pass control to the assembly language program FILE1. If the Floating Point Accumulator beginning at address >834A contains >43 >02 >22 >38 >00 >00 >00 >00, RO contains >00 and R1 contains >02, then BLWP @NUMASG assigns 4.. ,-'4,5, 600 to 'Y'.
1.7

180

LINKING WITH BASIC

The following source code can be used to load a value into the FAC area: . . FAC EQU >834A VALUE BYTE >XX,>XX,>XX v >XX,>XX v >XX,>XX,>XX
.

LI LI LI LOOP MOV DEC JNE


.

R1,FAC R2 1 VALUE R3,4 *R2+,*R1+ R3 LOOP


Po I 10 h4 Ili h4 ir

C B ir FC Pr B CB ) B -11- FC I h4

This utility allows you to assign a string' to a string variable passed via BASIC command CALL LINK. Before using this utility you must: 1. 2. Create the string in CPU RAM with the first byte in the string indicating the length of the string. For simple string variables, place a value of 0 in RO. If you are assigning a string to an array; place the array element number in RO. Place the address of the string in R2. Place the arguement number as a full word in Rl. Access the utility with BLWP @STRASG if using the Editor/Assembler or BLWP @>6048 if you are using the Mini Memory Module.

3. 4. 5.

The example outlined below demonstrates the usage of the STRASG utility. The string "HELLO" is assigned to the string variable A* which is displayed on return to BASIC. 001 002 003 MESS 004 005 START 006 007 008 009 010 DEF START REF STRASG BYTE >05 TEXT 'HELLO' CLR LI LI BLWP @STRASG RT END

LINKING WITH BASIC

181

The following is the BASIC program that is needed. If you are using the Mini Memory module, omit line 20 as the program is already in memory. You would also need to change line 010 of the source code and omit lines 001 and 002.

10 20 30 40

CALL INIT CALL LOAD("DSK1.BSCSUP","DSK1.START") CALL LINWSTART",A$) PRINT A$

EINUMIRF- 3 INIUMEgIR FCEIF- EIRIeMIC


This utility allows you to get the value of a variable passed into your assembly language program through CALL LINK. In order to do this you need to follow the following steps: 1. If it is a simple variable, place 0 in RO. If it is an array element, place the element number in RO. Place the arguement number as

2. 3.

a full word in R1.

Call the utility via BLWP @NUMREF or BLWP @>6044.

The value of the variable will be returned in the Floating Point Accumulator area starting at address >834A. The number will be in Radix 100 notation.

CBMIREIF- 31 B -IFFRIMB FeEP-

P<EMICE

This utility allows you to get a string that was passed via CALL LINK command from BASIC. You must reserve an area of memory to hold the string before calling this utility. The following steps outline how this accomplished: 1. Reserve a buffer area in memory to hold the string. The first byte of the buffer area should hold the length of the string. If the the string length actually exceeds this value, an error is generated. Otherwise the actual length is placed in the first byte. Place 0 in RO if it is a simple string variable. Place the element number if the string is in an array. Load the starting address of the buffer in R2. Call the utility.

2.

3. 4.

182

LINKING WITH BASIC

la IR Fc C) Fc Pc la IF- C3 Fc -r I rq e
This utility allows you to transfer control to the error reporting routine in BASIC. To use this utility all you have to do is load the error code into the most significant byte of RO and call the utility via BLWP @ERR or BLWP @6050. The error codes that can be listed by your program are found in Table 13.3 on the adjacent page.

TABLE 12.3 BASIC ERROR CODES CODE 00


01 02 03 04 05 06 07 08 09 OA OB OC OD OE OF 10 11 12 13

ERROR MESSAGE
error (bad name) I/0 error (write protected) I/0 error (bad attribute) I/O error (illegal operation) I/0 error (buffer full) I/0 error (read past EOF) I/0 error (device error) I/0 error (file error) Memory full (closes file) N/A Bad tag Checksum error Duplicate definition Unresolved references N/A Program not found Incorrect statement Bad name Can't continue Bad value

CODE ERROR MESSAGE


14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 4,...,_ 22 -.7...,.,) 24 25 .,-) 26-FF Number too big String-number mismatch Bad argument Bad subscript Name conflict Can't do that Name conflict For-Next error I/O error File error Input error Data error Line too long Memory full (file not closed) Syntax error Numeric overflow Unrecognized character String truncated Unknown error

I/O

13 HIGH PRECISION MATHEMATICS


'TT

Along with the many utilities discussed in Chapter 6, there are many additional utility programs related to mathematics that literally save you hours (or days) in programming time. The first section of this chapter outlines mathematical GPL routines that can be accessed through GPLLNK. The second section of this chapter discusses ROM console routines that can be accessed through XMLLNK.

-183-

184

HIGH PRECISION MATHEMATICS

All of the following routines involve floating point numbers. If an error occurs during execution of the routine, the error is indicated in byte >8345. Table 13.0 gives all the possible error codes that can be returned.

TABLE 13.0 FLOATING POINT ROUTINE ERROR CODES CODE


>01 >02 >03 >04 >05 >06 >07

ERROR TYPE
Overflow. Syntax error. Integer overflow on conversion. Square root of a negative number. Negative number to non-integer power. Logarithm of a non-positive number. Invalid argument in trigonometric fxn.

Table 13.1 outlines the mathematical routines that can be accessed through GPLLNK.

TABLE 13.1 XML ROUTINE CODES ROUTINE CODE


>0014 >0022 >0024 >0026 >0028 >002A >002C >002E
>0030

DESCRIPTION
Convert number to string. Greatest integer function. Involution routine. Square root routine. Exponent routine. Natural logarithm routine. Cosine routine. Sine routine Tangent routine. Arctangent.

>0032

The sections that follow in this chapter describe the GPL mathematical routines. The address of the Floating Point Accumulator is >834A. The Floating Point Accumulator is abbreviated FAC in the following sections.

Parentheses indicates the BASIC statement which would call the routine from a BASIC program.

HIGH PRECISION MATHEMATICS DATA >0014 [STU CONVERT NUMBER TO STRING

185

This routine allows you to convert a floating point number into a ASCII string. The following are the necessary steps: 1. The eight bytes defining the number are located beginning at FAC. If you set FAC+11 (>8355) equal to zero, it indicates that the output string is to be in BASIC format. Otherwise the output is in FIX mode, which requires data in FAC+12 and FAC+13 (>8356 & >8357). FAC+12 is the number of significant bytes. If 1, it expresses overflow from the calculation range. FAC+13 indicates the number of digits to the right of the decimal point. A negative value disables the FIX mode. 3. After the execution of the STR routine, FAC is modified. FAC+11 (>8355) contains the least significant byte of the address where the string is located. This byte must be added to >8300 to find the actual address of the string; address=(FAC+11)+>8300. FAC+12 (>8356) contains the length of the string (in bytes).

2.

DATA >0022 [INT] GREATEST INTEGER FUNCTION This routine allows you to compute the greatest integer contained in a value. 1. 2. FAC contains the floating point value. After calling this routine, FAC contains the result. For positive numbers, the integer is the truncated value. For negative numbers, the integer is the truncated value plus one. The GPL status byte (>837C) is set according to the result.

3.

DATA >0024 INVOLUTION ROUTINE This routine allows you to raise a number to a specified power. 1. 2. FAC contains the exponent value. Address >836E (STACK) contains the address in VDP RAM that holds the eight byte number.

186

HIGH PRECISION MATHEMATICS

3. 4.

The result is placed in FAC in floating-point format. This is computed as exp*LOGEABS(base)3. After completion of this routine, the data at addresses >8375 and >8376 is destroyed. The word at address >836E is decremented by 8.

DATA >0026 ESQR3 SQUARE ROOT ROUTINE This routine allows you to find the square root of a number. 1. 2. 3. 4. FAC contains the input value. After the routine, FAC contains the square root of the input value. The GPL status byte is affected. Addresses >8375 and >8376 are destroyed by this routine.

DATA >0028 [EXP3 EXPONENT ROUTINE This routine will compute the inverse natural logarithm of a number. 1. 2. 3. 4. FAC contains the input value. After the routine, FAC contains the resulting value. The GPL status byte is affected. Addresses >8375 and >8376 are destroyed by this routine.

DATA >002A CLOG] NATURAL LOGARITHM ROUTINE This routine will compute the natural logarithm of a number. 1. 2. 3. 4. FAC contains the input value. After the routine, FAC contains the resulting value. The GPL status byte is affected. Addresses >8375 and >8376 are destroyed by this routine.

HIGH PRECISION MATHEMATICS DATA >002C MOS] COSINE ROUTINE

187

This routine will compute the cosine of a number that is expressed in radians.

1. 2.

FAC contains the input value. After the routine, FAC contains the cosine of the input value. The GPL status byte is affected. Addresses >8375 and >8376 are destroyed by this routine.

3. 4.

DATA >002E [SIN] SINE ROUTINE


This routine will compute the sine of a number expressed in radians. 1. 2. FAC contains the input value. After the routine, FAC contains the sine of the input value. The GPL status byte is affected. Addresses >8375 and >8376 are destroyed by this routine.

3. 4.

DATA

>0030

(TAW TANGENT ROUTINE

This routine Oill compute the tangent of a number expressed in radians. 1. 2. FAC contains the input value. After the routine, FAC contains the tangent of the input value. The GPL status byte is affected. Addresses >8375 and >8376 are destroyed by this routine.

3. 4.

DATA

>0032

[ARM ARCTANGENT ROUTINE

This routine will compute the arctangent of a number expressed in radians. 1. FAC contains the input value.

188

HIGH PRECISION MATHEMATICS

2.

After the routine, FAC contains the arctangent off the input value.

3.
4.

The GPL status byte is affected.


Addresses >8375 and >8376 are destroyed by this routine.

To review how to call up GPL routines through the use of the GPLLNK utility, refer to page 82 of chapter 6. Remember that you must reset the GPL status byte at address >837C, or a meaningless error message will be returned. Also make sure that any of the CPU RAM areas that are affected by a GPL routine are not being used by your program to store information. The addresses that you need to use these utilities with the mini memory module can be found in table 10.1 on page 148. Routines that are located in ROM can be accessed through the use of the XMLLNK command. There are two ways to access a routine in console ROM. The first is to specify the routine's code in a DATA statement. For example,

BLWP @XMLLNK DATA >0800


branches to the floating-point multiplication routine in the console. The second way to access a routine in console ROM is to specify its addresses in the DATA statement. You should take note that when using this method, the most significant bit of the DATA word must be set to indicate to the system that this is an address instead of a routine code. For example,

BLWP @XMLLNK * 8 D 3 A (note MSB set to indicate DATA >8D3A * 1000 1101 0011 1010 an address)
branches to console ROM address >0D3A which is the floating point compare routine. Unless absolutely unavoidable, you should not use direct memory addresses of console ROM routines as they can vary from one console to another. Table 13.2 outlines the console routine codes that can be used with XMLLNK.

HIGH PRECISION MATHEMATICS TABLE 14.2 XML ROUTINES Routine Code


>0600 >0700 >0800 >0900 >0A00 >0800 >0000 >0D00 >0E00 >0F00 >1000 >1200 >1700 >1800 >1230

189

Description
Floating-Point Addition Floating-Point Subtraction Floating-Point Multiplication Floating-Point Division Floating-Point Compare Operation Floating-Point Stack Addition Floating-Point Stack Subtraction Floating-Point Stack Multiplication Floating-Point Stack Division Floating-Point Stack Comparison Convert String to Number Convert Floating-Point to Integer Push a value onto Value Stack Pop a Value for the Value Stack Convert Integer to Floating-Point

In the routines that follow, FAC starts at address >834A, ARG (which stands for arguments) starts at address >835C. STACK is at address >836E. All overflow errors, except in convert floating point to integer, return >01 at address >8354.

DATA >0600 FLOATING POINT ADDITION


This routine adds two values. 1. 2. 3. FAC contains the first value.. ARG contains the second value. FAC holds the result after calling the routine.

DATA

>0700

FLOATING POINT SUBTRACTION


This routine subtracts two values. 1. 2. FAC contains the value to be subtracted. ARG contains the value from which FAC is subtracted. FAC holds the result of calling the routine. the subtraction after

3.

190

HIGH PRECISION MATHEMATIC

DATA >0800 FLOATING POINT MULTIPLICATION


This routine multiplies two numbers together. 1. 2. 3. FAC holds the value of the multiplier. ARG holds the value of the multiplicand. FAC holds the result after the routine is called.

DATA

>0900

FLOATING POINT DIVISION

This routine divides two values. 1. FAC holds the divisor.

2. 3.

ARG holds the dividend. FAC holds the result of the operation after calling the utility.

DATA

>0A00

FLOATING POINT COMPARE

This routine compares two floating point numbers. 1. FAC holds the first number while ARG holds the second. The GPL status byte (>837C) is affected. The high bit is set if ARG is logically higher than FAC. The greater than bit is set if ARG is arithmetically higher than FAC. The equal bit is set if ARG and FAC are equal.

2.

DATA

>0B00

VALUE STACK ADDITION

This routine will add using a stack in VDP RAM. 1. STACK contains the VDP RAM address where the left-hand term is located. FAC holds the right-hand term. FAC holds the result of the addition after the addition after the routine is called.

2. 3.

HIGH PRECISION MATHEMATICS

191

DATA >0000 VALUE STACK SUBTRACTION


This routine will subtract using a stack in VDP RAM. 1. 2. 3. STACK contains the VDP RAN address of the multiplicand. FAC contains the multiplier. FAC holds the result of the multiplication after calling the routine.

DATA >0D00

VALUE STACK MULTIPLICATION

This routine will multiply using a stack in VDP RAM. 1. 2. 3. Stack contains the VDP RAM address of the multiplicand. FAC contains the multiplier. FAC holds the result of the multiplication after the routine has been called.

DATA >0E00 VALUE STACK DIVISION


This routine will divide using a stack in VDP RAM 1. 2.
-. %a.

STACK contains the VDP RAM address holds the dividend. FAC holds the divisor value. FAC holds the result of the division after the routine has been called.
,

4.

DATA >0F00 VALUE STACK COMPARE

This routine will compare a value in the VDP RAM stack to the value in FAC. 1. 2. STACK holds the VDP RAM address of the value to be compared. FAC holds the other value to be compared.

192

HIGH PRECISION MATHEMATICS

3. The GPL status byte (>837C) is affected. The high bit is set if STACK is logically higher than FAC. The greater than bit is set if STACK is arithmetically higher than FAC. The equal bit is set if STACK and FAC are equal.

DATA >1000 CONVERT STRING TO NUMBER This routine will convert an ASCII string into a floating-point number. 1. FAC+12 (>8356) is the address of the starting in VDP RAM. 2. FAC holds the result of the conversion in floatingpoint format.

DATA >1200 CONVERT FLOATING POINT TO INTEGER This routine will convert a floating-point number into an integer. 1. 2. FAC contains the floating-point number to be converted. FAC will contain integer value as one word. The maximum value of this word is >FFFF. If there is an overflow, FAC+10 (>8354) is set to the overflow error code, >03.

DATA >1700 PUSH VALUE ONTO VALUE STACK This routine will push a value you have loaded in FAC onto the value stack.

DATA >1800 POP VALUE FROM VALUE STACK This routine will pop a value from the value stack and place it in FAC.

HIGH PRECISION MATHEMATICS

193

1.

FAC contains the one-word integer that is to be converted. FAC will contain the floating-point result after the routine is called.

2.

NOTE: This routine is only available with the Editor/Assembler and is not supported in Extended Basic or by the Line-by-Line assembler. It has also been found that the correct code for this routine may be >7200 in some consoles.

I NDEX
A (add words) AB (add bytes) 36 37 ABS (absolute value) 37 Absolute value Absolute code 66,140 Absolute origin 66 Accept tone 84 Add bytes 36 Add immediate 37 Add words 36 Addressing modes Addressing immediate 26 indexed memory 28 program counter relative 29 symbolic memory 28 Workspace Register 26 Workspace Register indirect auto-increment Add immediate 37 ANDI 51 AORG 66,140 Arctangent routine 187 Arguement passing 174 Arithmetic instructions .. 29,35 Assembler directives 65 Assembler output 74 Branch & link Branch & load Workspace pointer Branch instruction BSCSUP BSS BYTE Byte structure 43 43 43 169 67 70 6

B
Bad response tone BASIC linkage BASIC support utilities BES Binary numbering system Bit reversal routine BIT-MAP MODE BIT-MAP MODE example BL Block ending with symbol Block starting with symbol BLWP

43 84 169 169 68 6 84 107 110 43 68 67 43

C 47 CALL CHARPAT 176 CALL INIT 170 CALL LINK 173 CALL LOAD 171 CALL PEEK 175 CALL PEEKV 175 176 CALL POKEV Cassette DSR routine 85 CB 48 CI 49 Clear instruction 54 CLOSE PAB opcode 89 CLR 54 COC 49 103,119 Color codes Color table BIT-MAP MODE 107 101 GRAPHICS MODE Comment field 23 48 Compare bytes 49 Compare immediate 46 Compare instructions Compare ones corresponding instruction 49 47 Compare words Compare zeros corresponding 49 instruction Constant initialization 21 Constants assembly-time 21,69 character 21

196

INDEX

decimal hexadecimal Controller access, sound ... Covert floating to integer Convert integer to floating point Convert number to string Convert string to number Copy command COPY Cosine routine CZC

21 21 127 192 192 184 191 72 72 186 49

END 73 Entry points 72 EQU 21,69 Equates 21,69 ERR reporting utility 93 Error codes that can be returned ..... 182,184 EVEN 68 External definition 72 External reference 72

F7
Field comment label operand operation code File characteristics File defaults File specification File type Floating point addition . Floating point compare .. Floating point division Floating point multiplication Floating point subtraction Frequencies, sound 23 22 27 86 93 86 86 189 190 190 189 189 130

DATA 70 Data initialization 70 DEC Decimal to Hexadecimal interconversions 12 Decrement by two Decrement 37 DECT 38 DEF 72 DEF/REF table 72 Define assembly time constant 21,69 Define extended operation ... 73 DELETE PAB opcode 89 Device service routine 85 Directives that affect assembler output 74 Directives that affect location counter 66 Directives that initialize constants 69 Directives that link programs 71 Directives, assembler 65 Directives, miscellaneous . 73 DISPLAY, file type 87 DIV 38 DORG 67 DSR 85 DSRLNK 85 Dummy origin directive 67 Duration control, sound .... 132 DXOP 73 EE Editor 20

C3
General addressing modes Get string space GPL routines GPLLNK Graphics GRAPHICS MODE

25
84 83 82 97 101

EA
Hexadecimal system Hexadecimal to decimal conversions 5,11 12

IDT Immediate addressing INC Increment by two Increment INCT Indexed memory addressing

75 26 29 40 40 28

INDEX

197

INIT Initialize byte Initialize text Initialize word INPUT PAB opcode Instructions by group arithmetic branch compare control jump load and move logical shift Interrupt handling INV Involution routine

170 70 71 70 87
,:, ..J

IL_
22 Label field LI 33 LIMI 34 LINK subroutine 173 Load immediate value 33 34 Load interrupt mask Load lower case character set 85 LOAD PAB op-code 89 Load small captitals character set 84 Load standard character 83 set Load Workspace pointer immediate 74 Location counter directives 66 Logical instructions 50 LWPI "1. 4 Ni Maginfication of sprites 120 Mathematical routines ... 183 Memory-mapped devices 77 Miscellaneous directives 73 Mnemonic codes 23 ") I:::" Modes, addressing .e......1 MOV "7 7 MOVES 33 Move command MPY 40 106 MULTICOLOR MODE Multiply instruction 40
1 ...T., .1 s 'II ....)

-7=

42 46 42 42 -.V? 50 57 34 54 185

0
JED JGT JH JHE JL JLE JLT JMP JNC JNE JNO JOC JOP Joystick use Jump if equal Jump if greater than Jump if high or equal Jump if less than Jump if logical high Jump if logical low Jump if low or equal Jump if no carry Jump if no overflow Jump if not equal Jump if odd parity Jump instructions Jump on carry li< KSCAN 42 42 42 42 42 42 42 44 42 42 42 42 42 159 42 42 42 42 42 42 42 42 42 42 42 42 42

P4
Natural logarithm routine routine 186 NEG 41 8 Negative numbers No operation 61 75 No source list Noise specification byte 129 for sound 61 NOF' 179 NUMASG Numbering systems 181 NUMREF D Object code OPEN PAB op-code

....

80 15 87

198

INDEX

Operand field ORI OUTPUT PAB op-code F.:" PAB PAGE directive Page title directive Pattern descriptor table BIT-MAP MODE GRAPHICS MODE MULTICOLOR MODE PEEK subroutine PEEKV subroutine Periodic noise Peripheral access block .... POKEV subroutine Predefined symbols Program counter register Program counter relative addressing Program organization Pseudo-instructions

27 51 87

RTWP Run option

44 146

86 75 75 107 102 106 175 175 132 86 176 77 17 29 20 20

ca
Quit key, interrupts 34 FR READ PAB op-code 89 REF (external reference) 72 REF/DEF 72,144 Registers 16 Registers, VDP 98 Relocatable object code 67 RESTORE/REWIND PAB op-code 89 Return pseudo-instruction 62 Return Workspace pointer 44 Returning 62 Roll-up 143 Roll-down 143 16 ROM ROM routines 82,183 RORG 67 Routines GPL 82 mathematical 183 ROM 183 RT 62

E3 SAVE PAB op-code 90 41 SB Screen image table BIT-MAP MODE 107 GRAPHICS MODE 102 MULTICOLOR MODE 106 TEXT MODE 107 m...... Set ones corresponding . ,J,..) 54 Set to one ic. ... J., Set zeros corresponding Set zeros corresponding == byte ,J,J SETO 54 57 Shift instructions Shift left arithmetic 57 57 Shift right arithmetic Shift right circular 60 Shift right logical 59 Sine routine 187 120 Size of sprites SLA 57 SOC 55 == SOCB ,J,J Sound 127 Sound, duration control . 128 Sound, frequency 130 Sound, noise 132 Sound, table 128 Source listing 20 Source statement 20,22 115 Sprites Sprite attribute list ... 116 Sprite descriptor table . 116 Sprite magnification .... 120 116 Sprite motion table Sprite size 120 Square root routine 186 SRA 57 SRC 60 SRL 59 STATUS byte 17 STATUS PAB op-code 90 Status Register 17 Status Register bits affected 18

INDEX

199

Store status Store Workspace pointer STRASG STRREF STST STWP Subtract bytes Swap bytes SWPB Symbolic memory addressing SZC SZCB

34 34 180 181 34 41 34 34 28 56 56

Workspace Register indirect addressing Workspace Register indirect autoincrement addressing Workspace Register shift instructions WRITE PAB op-code

27 27 57 89

x
X XMLLNK XOP XOR 46 188 31 51

ir
Tangent routine 187 Terms 21 TEXT 71 TEXT MODE 107 TITL directive 75 Two's compliment notation . 8

Li
Unconditional jumps UNL UPDATE PAB op-code Utilities 44 75 87 77

Value stack addition Value stack compare Value stack division Value stack multiplica Value stack subtraction VDP access VDP write only Registers VMBR VMBW VSBR VSBW VWTR

190 191 191 191 190 97 98 79 79 79 78 80

White noise 132 Word boundry 10 Word organization 10 Workspace 16 Workspace pointer Register 17 Workspace Register addressing 26

APPENDIX A

201

IA IF Fft

Nap I

ink

HEXADECIMAL/DECIMAL INTERCONVERSIONS 6 DEC ! !O !1 !2 !3 !4 15 !6 !7 !8 !9 !A !B !C !O !E !F ! !HX! 5 ! DEC !HX! 0!0 65,536!1 131,072!2 196,608!3 262,144!4 327,680!5 393,216!6 458,752!7 524,288!8 589,824!9 655,360!A 720,896!B 786,432!C 851,968!D 917,504!E 983,040!F DEC=decimal

4
DEC

! !H X !

3 DEC

! !HX!

! ! DEC!HX!DEC! ! 0!0 16!1 32!2 48!3 64!4 80!5 96!6 112!7 128!8 144!9 160!A 176!B 192!C 208!D 224!E 240!F 0! 1! 2! 3! 4! 5! 6! 7! 8! 9! 10! 11! 12! 13! 14! 15!

0!0 1,048,576!1 2,097,152!2 3,145,728!3 4,194,304!4 5,242,880!5 6,291,456!6 7,340,032!7 8,388,608!8 9,437,184!9 10,485,760!A 11,534,336!B 12,582,912!C 13,631,488!D 14,680,064!E 15,728,640!F

0!0 4,096!1 8,192!2 12,288!3 16,384!4 20,480!5 24,576!6 28,672!7 32,768!8 36,864!9 40,960!A 45,056!B 49,152!C 53,248!D 57,344!E 61,440!F

0!0 256!1 512!2 768!3 1,024!4 1,280!5 1,536!6 1,792!7 2,048!8 2,304!9 2,560!A 2,816!B 3,072!C 3,328!0 3,584!E 3,840!F

HX=hexadecimal

POWERS OF 2
x

POWERS OF 16
x x

2 1 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16,384 32,768 65,536 131,072

16 1 16
256 4,096 65,536 1,048,576 16,777,216 268,435,456 4,294,967,296 68,719,476,736 1,099,511,627,776 17,592,186,044,416 281,474,976,710,656 4,503,599,627,370,496 72,057,594,037,927,936 1,152,921,504,606,846,976

0 1 2 3 4 5 6 7

0
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

a
9 10 11 12 13 14 15 16 17


202 APPENDIX

se%

IF" Fa E. IN/I ID I X Ec

11 11111 11 11 11

111111 111111 111111 111111

111 III 111 111

0 -C 4-3
CO O ,C 3-4 Hi 3 0) m

11111

11111

11 W
a)T1a/

,Q C 344 IC Q. 41i 0.4 H>4 It E 3-4 to 4-4 0-4 344 $4 JO CO-1 4:0

x
0C > O O

11

II

111111

III

!XIII

11

IX1111

111

XXXX I XXIX!

1 1

11 II

111111 111111

XXX XXI

TMS 9900INSTRUCTIONSETSUMMARY

E O CV 01
- I-10)01

a
A

XX X XX

I I I

XXXIXX

XXI

44-4 03 1-0 rd ID4


S-1.-111)

a) a) -rt C ,Q
0 01 4) %--'0 co l/ to .0 TS 0)

W C

ro .0 Ei

THE TMS9900INSTRUCTI ON

XXXXX

I 1 1

X X X 1 I 1

XXI

X X X X X

1 1 i

X X X i 1 1

X X i

O
Z

4.1

TI 4-)

4P CO LI 0 0 Hi W 4 0) N X
1-10

N N ca 3 0-1 a) 0 4-) C

07 a.

CO CO N N 0 (7(1m NW0)acDC1 N 0 01 01 01 II LI Matz: aaaln CC 'Cr rri CI

4-/

E
U
N

V to C 4:-)

5-4 01W 4-4 .4C 411 N 144 43-4 4-4 .0 -H 40 CU 0


4-1 :/ -10

co E
L
a
1Js

(i (J

r,

- 000 001t1033 00 0 0 3: 0 O

LO O

C7

ra C O1 u) a.)
04

4,4

as 4-7 o o i ww C

CD rC
44-4

U
0

H1 0 I0 4-1 /4 4-1 )-1

E
X

O 7.) M 41) ,C 4-) El 0 CO 3

N u 3 000 00> CO CO 0-4 Z JJ COHJON WWI<<<<< 070703 000000 uuu

a_

F-

APPE:ND I X B A F' F' la IN ID I X Ec

203

1 I

1 1

1 I

1 1

1 1

1 I I
I

1
I

l
I

1 1

1 1

1 I 1
I

1 1 1
I

i i i
1

I 1 1
1

i
1

tn
I 4-3

1 1 1

1 I
I

1 I
I

I 1
I

1 1
I

I I
I

X X
x

1 I
I

III I 1 1

I
1

1
1

I
1

1
1

I
1

1
1

i
1

1
1

i I

O O

Ill

1111114-3

11

(c on t inu e d )

X X
X X

1
I

1111
1111

11114J1
1 1 4-3 1 1 4

1
1

11
1 I

1
1

1
I

X
I

I
1

X X X

4-3 1 4-3 4-3 4-3 4-3 4-3 1

1 4-3 1

X X i

x i

xxx

14-311114-311

1i

x I

xx I

x I

Icn

A
-J xxx 1144441111 1 I x I xx I x I x

TMS 99 00I NS TRUC TI O N

Ill 0) a..

01 0 (r) Cr Li)

LD 113 W LO W U3 113 LO Cr Cr Cr Cr 'Cr 'Cr Cr Cr C Cr Cr Cr Cr

(r) Cr Cr (r)

el 0 (r) (r) Cr

0 Cr LD

I-

I
4J
(U

E
L
0

0 0 0

Ii

E EEEEEEEEEEEE O 000000000000 r-i r-i -r-ir-i r.1 r-i r-1 -r-i r-i r-i (11 (11 (11 (1) (11 111 (11 (11 (11 (1) (11 (11 111 (1) (1) (11 (1) (1) (1) (1) (1) 111 (1) (1) (1) CU CU CU CU CU CU CU CU CU CU CU CD CU L LLLLLLLLLLLL

# 3

1-7 0 3
f-,

3 ID CD CD

CL O. CL CL CL CL CL CL 0_ CL CL CL 0_ XXXXXXXXXXXXX Ill CD U) U) U) U) U) U) U) U) U) U) U)

E
II)

1.--i 1.--i 03 1DU> 0 IL 1.--1 0' 1W 1111-1:LOWOUIL > > >I a. ZZZ WOMI_J-J_JZZZZOO 1-'1-'3 0011 WO CC )--11-11-1 _J_J_J :EXM ZZ 0

204

APPENDIX B

ink Fii FA AID I X Et

X IA CO M 4-3 C
H

I I I 1

I I I I

I I I I

I I I
I

I I

1 1

I I I 1

I I I I

1 1 1 1

X X X
X

x
X X

V l 1 I I

1 l 1

1 I
I

I I
I

I 1
I

I 1
I

V I 1

co -4 w (co n t inu e d)

N 0)

a. o

Ill 3
4J CO 4-3

> o
LJ

X
X

XXI

I I

I I I

I I

X I X I

I I

X X i X I

I X X X I

U)

w A <
A -J

X X I XXX X X X 1 I I XX

X I X

X X i XXX X X X 1 I I XX

X I X

IuJ cn TM S9 900INST RUC T ION

X X I X X X X X X I I I XX

X I X

CU 'Ct CO 'Ct

N n- 'Ct N cl* ID N Cr) Cr) q '1 in in LO 'Ct 'Ct LI) 1.f) in in in cn in PI PI PI lf) lf)

LO N 0 'Ct PI LI)

uJ

I I4J CO E L 0 IL CD CD - L7 CDO t....... %....., co ,---, co %....., ,---, ,---, ,---, 3 3 0 t--, t....... ... ... 3 - 3 3 3 co Lo t....., 0 t...... t....... t....... CD 0 33 ,....... ... ... 0 ID

,.....,

0 ,-i C 0 E CD C X

a.

co

I < U LJ < _1 U CO 3 0_ 0

1-

EL CO

GO C.) CL CC

I I-CC CC

CO li.1 _J 0 0 CC CC CC I I 3 N N U) Ul Ul U) Cf) Cf) (1) C11 CO U) C11 U) Cf) Cf)

0 0
X X X

APPENDIX B IPi F" F" E IN ID I X THE ASSEMBLER DIRECTIVE COMMAND SET

205

The following table summarizes the Editor/Assembler director set. These directives are in alphabetical order. For each directive is shown the general assembler format. The page number given refers to where in the book the directive is described, parentheses indicate where the directive is described when referring to source code created using the mini memory module.

DIRECTIVE COMMAND SET


Mnemonic Format AORG BES BSS BYTE COPY DATA DEF DORG END EQU EVEN IDT LIST PAGE REF FIORG SYM TEXT TITL UNL XOP Symbol,term 'string' 'string' symbol,symbol...symbol expression word[expression] word[expression] word[expression] exp,exp...expression "File-name" Page # 67(138) 68 67(138) 70 72

exp,exp...expression 70(138) symbol,symbol...symbol 72 expression 67 Symbol expression 73(141) 69(138) 68 74 74 75 72 67 (139) 71(138) 75 74 73

APPENDIX D

207

ins IF* IFP NI ID I X ID


This appendix contains a few source code listings that may be of interest. These examples are of short game program modules that you can incorporate into your programs. Where possible, The BASIC version of the program is presented for comparison purposes. The first program module sets a red ball-shaped sprite in motion only when the joystick is moved. The border color is black but the main screen is left uncolored (light green is the default color).

10 20 30 40 50 60

CALL CALL CALL CALL CALL GOTO

CLEAR CHAR(80,n3C7EFFFFFFFF7E3C") SPRITE(#1,80,9,100,100) JOYST(1,X,Y) MOTION(#1,-Y*4,X*4) 40

Notice that the source code listing for the same program is much longer. This allows you much greater flexability, but the price is much more time spent programming.

DEF REF * JOY1 JOY2 JOY3 JOY4 JOY5 JOY6 JOY7 JOYS ONE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE EVEN

SPRITE VMBW,VWTR,KSCAN 4,0 4,4 0,4 -4,4 -4,0 -4,-4 0,-4 4,-4 1

* JOYY EQU >8376 KBOARD EQU >8374 NUMB EQU >837A SATAB EQU >0300 SDTAB EQU >0400 SMTAB EQU >0780 * BALL DATA >3C7E,>FFFF,>FFFF,>7E3C SDATA DATA >70D0,>8008 DATA >D000 * SPO DATA >0000,'>0000 *

208

APPEND I X D

MYREG BSS >20 SPRITE LWP I MYREG LI RO , SDTAB LI R1 , BALL LI R2 , 8 BLWP @VMBW LI RO , SATAB LI R1 , SDATA R2 , 8 LI BLWP @VMBW LI R1 , 1 SLA R1 , 8 MOVB R1 , @NUMB LI RO , >0701 BLWP @VWTR MOVB @ONE , @KBOARD

* * *
* LOOP

LI RO , SMTAB LI R1 ,SPO LI R2 , 4 BLWP @VMBW LIMI 2 LIMI 0 BLWP @K SCAN MOV @JOYY , @JOYY JEQ LOOP C JEQ C JEQ C JEQ C JEQ C JEQ C JEQ C JED @JOYY , @JOY1 M1 @JOYY , @JOY2 M2 @jOYY , @JOY3 M3 @JOYY , @JOY4 M4 @JOYY , @JOY5 115 @JOYY , @JOY6 M6 @JOYY , @JOY7 M7

* LOOP1

APPENDIX D

209

M1 M2 M3 M4 M5 M6

M7 * RO,SMTAB CHANGE LI LI R2,2 BLWP @VMBW

LI B LI B LI B LI B LI B LI B LI B LI

R1,JOY6 @CHANGE R1,JOY5 @CHANGE R1,JOY4 @CHANGE R1,JOY3 @CHANGE R1,JOY2 @CHANGE R1,JOY1 @CHANGE R1,JOY8 @CHANGE R1,JOY7

B END

@LOOP1

The last program worked well enough but it went about it the long way around. Using a little ingenuity we can considerably shorthen the above program. The source listing that follows accomplishes the same task as the last program, only it has been shortened with some programming tricks.

DEF SPRITE REF VMBW,VWTR,KSCAN * ONE BYTE 1 ZERO BYTE 2 * JOYY EQU >8376 KBOARD EQU >8374 NUMB EQU >837A SATAB EQU >0300 SDTAB EQU >0400 SMTAB EQU >0780 * BALL DATA >3C7E,>FFFF,>FFFF,>7E3C SDATA DATA >70D0,>8008 DATA >0000 * SPO DATA >0000,>0000 *

210

APPEND I D

>20 MYREG BSS SPRITE LWP I MYREG RO SDTAB LI R1 , BALL LI R2 , 8 LI BLWP @VMBW

*
LI RC) , SATAB LI R1 SDATA LI R2 , BLWP @VMBW

*
LI R,1 R , SLA MOVB R1 , @NUMB

*
LOOP LI R0,SMTAB R1 ,SF'0 LI R2 , 4 LI BLWP @VMBW LIMI LIMI 0 BLWP MOV @JOYY @JOYY JEO LOOP CB @JOYY , @ZERO JEO GO MOVB @J 0Y+ 1 , @R5 NEG @JOYY MOVB R5 @JOYY+ 1 LI R1 , JOYY JMF' CHANGE

*
LOOP 1

*
GO LI R1 JOYY RO SMTAB CHANGE LI LI R2 ,2 BLWP @VMBW * B @LOOP 1 END

APPENDIX D

211

The last two programs can be loaded via the LOAD AND RUN option of the Editor/Assembler and run by typing in SPRITE in response to the PROGRAM NAME? prompt. In order to run these programs using the Mini Memory module you must: 1. 2. 3. Alter the length of all LABEL fields to two characters. Use appropriate address instead of symbols for the utility programs. Enter the program name and starting point into the REF/DEF table (refer to page 145).

The third program in this series illustrates additive motion. The longer you hold the joystick in one direction, the faster your sprite will move (here a red ball again!) To stop the sprite you will have to cancel out the motion by holding the joystick in the opposite direction to "brake" the sprite. This module lends itself well to incorporation of "space games" where you have to simulate the abscence of gravity.

10 20 30 40 50 60 70 80

CALL CLEAR CALL SCREEN(2) CALL CHAR(128,"3C7EFFFFFFFF7E3C") CALL SPRITE(#1,128,9,100,100) CALL JOYST(1,C,R) X=(X+C)*-(ABS(X)<124) Y=(1-R)*-(ABS(Y)<124) CALL MOTION(#1,Y,X)

NOTE: A direct translation of line 60 is: IF THE ABSOLUTE VALUE OF X<124 THEN X=X+C ELSE X=0 The following program is the assembly language version of the above program. Note how the "CALL SCREEN" code was added. DEF SPRITE REF VMBW,VWTR,KSCAN,VSBW * JOY1 JOY2 JOYS J0Y4 J0Y5 JOY6 JOY7 JOYS ONE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE BYTE EVEN 4,0 4,4 0,4 -4,4 -4,0 -4,-4 0,-4 4,-4 1

212

APPENDIX D

JOYY KBOARD NUMB COLTAB SATAB SDTAB SMTAB

EQU EQU EQU EQU EQU EQU EQU

>8376 >8374 >837A >0384 >0300 >0400 >0780 >3C7E >70D008008 >D000 >0000,>0000 >1000

*
BALL DATA SDATA DATA DATA SPEED DATA COLOR DATA

SPRITE LWPI MYREG LI RO,COLTAB MOV @COLOR,R1 BLWP @VSBW CLR LI LI BLWP INC DEC JGT RO 5102000 52,767 @VSBW RO 52 LOOP

LOOP

*
LI 5000701 BLWP @VWTR LI RO,SATAB R1,SDATA LI LI R2,8 BLWP @VMBW LI RO,SDTAB LI R1,BALL LI R2,8 BLWP @VMBW 51,1 LI SLA R1,8 MOVB R1,@NUMB

*
MOVB @ONE,@KBOARD RO,SMTAB LI LI R1,SPEED Rd, 4 LI BLWP @VMBW
`,

APPED I X D LOOP1 LIMI 2 LIMI 0 BLWP @KSCAN MOV @JOYY , @JOYY LOOP1 JEQ @JOYY ,@JOY1 C JEQ UP @JOYY , @JOY3 C RIGHT JEQ @JOYY , @JOY5 C JEQ DOWN C @JOYY , @JOY7 JEQ LEFT @JOYY , @JOY2 C JEQ UPRT @JOYY , @JOY4 C JEQ DNRT @JOYY , @JOY6 C JEQ DNLT C @JOYY , @JOYS JEQ UPLT JMP LOOP1 UP UPRT DECT R5 @ADJUST B DECT R5 INCT R6 B @ADJUST I NCT R6 B @ADJUST INCT R5 INCT R6 B @ADJUST INCT R5 @ADJUST B INCT R5 DECT R6 B @ADJUST DECT R6 B @ADJUST DECT R5 DECT R6

213

RIGHT DNRT

DOWN DNLT

LEFT UPLT

* ADJUST LI RO , SMTAB MOVB R5 , R1 BLWP @VSBW

LI RCS , SMTAB+ 1 MOVB R6 , R 1 BLWP @VSBW B LOOP END

214

APPENDIX D

This next program will illustrate the double-size and m,agnified sprite concept. When the program is run the sprite (a red ball) is standard sized and in motion across the screen. When any key is pressed the sprite is doublesized. When a key is pressed again the sprite is magnified. Finally, a third press of a key will make the sprite double-sized and magnified. Subsequent pressings of a key will repeat the cycle. DEF REF SPRITE VMBW,VSBR,VSBW,KSCAN,VWTR

* KBOARD EQU >8375 SKEY EQU >8374 SATAB EQU >0300 SDATA EQU >0400 * BALL DATA >3C7E,>FFFF,>FFFF,>7E3C SDATA DATA >7080,>8008 * STATUS EQU >837C SET DATA >2000 MYREG BSS >20
*

SPRITE LWPI MYREG LI R3,4 LI RO,SDTAB START LI R1,BALL LI R2,8 BLWP @VMBW AI R0,8 DEC R3 JNE START LI LI LI BLWP RO,SATAB R1,SDATA R2,6 @VMBW RO,SATAB+1 @VSBR R1,8 R1 MOVE R1,>00FF R1,8 @VSBW R8 R8 R8,800

* LOOP READ

LI BLWP SRL DEC JNE LI SLA BLWP CLR INC CI

* MOVE DELAY

JNE DELAY

APPENDIX D

215

* OUT

CLR @KBOARD BLWP @KSCAN MOV @STATUS,R3 @SET,R3 COC JNE LOOP INC R6 R6,4 CI JLT GO CLR R6 R6,1 CI JEQ MAG R6,2 CI DSIZE JEQ R6,3 CI DSIZEM JED Can you sum all this code into a two line statement?

* CHECK

* GO

* SMALL

RO,>01E0 LI WRITE JMP R0,>01E1 LI MAG WRITE JMP RO,>01E2 LI WRITE JMP R0001E3 DSIZEM LI WRITE JMP * WRITE BLWP @VWTR B @LOOP END

The next program places six red ball-shaped characters (not sprites) on the screen in a diagonal pattern. The screen is then scrolled upwards. This type of motion is familiar to anybody who has played the Alpiner game from TI. In oreder to run this program you must type GRAPH in response to the PROGRAM NAME? prompt. DEF GRAPH REF VSBW,VMBW,VMBR * DATA BALL COLOR DATA * COLTAB EQU PATTAB EQU * MYREG BSS * GRAPH LWPI LI >3C7E,>FFFF,>FFFF,>7E3C >8100 >0384 >0908 >20 MYREG RO,COLTAB

216

APPENDIX D

MOV @COLOR,R1 BLWP @VMBW RO,PATTAB LI LI R1,BALL LI R2,8 BLWP @VMBW LI R0,325 LI R1,>2100 LI R2,6 BLWP @VMBW AI R0,33 DEC R2 JGT LOOP BSS BSS 32 32

LOOP

LINE1 LINEX

*
SCROLL CLR RO LI R1,LINE1 LI R2,>20 BLWP @VMBR LI R00, 20 LI R1,LINEX LI R2,>20 BLWP @VMBR

*
LOOP1 LI R0,0 BLWP @VMBW AI RO,>40 CI RO,>300 JHE OUT BLWP @VMBR AI R0,>FFE0 JMP LOOP1 LI R0,>2E0 LI R1,LINE1 BLWP @VMBW JMP SCROLL END CB @KEYUP,@KEY JED PUP CB @KEYDN,@KEY JED PDOWN CB @KEYRT,@KEY PRIGHT JED CB @KEYLT,@KEY

*
OUT

*
OUT

APPENDIX D

217

PLEFT JEQ JMP START PUP LI JMP PDOWN LI JMP PRIGHT LI JMP PLEFT LI JMP R1,UP PRINT R1,DOWN PRINT R1,RIGHT PRINT R1,LEFT PRINT R0,325 R2,17 @VMBW START BEGIN

*
PRINT LI LI BLWP JMP END

APPENDIX E

219

AlP1FlaMOIX e.

INJF-u -rxclourimurr IIRFccilFc


Error code 0 1 4. 2 Meaning Bad device name.

c:Nois

Device is write protected. Bad open attribute. 1. incorrect file type. 2. incorrect record length 3. incorrect I/O mode 4. no records in relative record file Illegal operation. 1. conflict with OPEN attributes 2. peripheral does not support operation Out of buffer space on device. Attempt to read past end of file. File is closed. Device error. Mechanical or medium failure. File error. 1. program/data mismatch 2. openning non-existing file in INPUT

4 5 6 7

220

APPENDIX F

A F" IR INI ID I X F

E X

la

Ul "T I 01 NI ---- ir I IMI la

la FC F C3F E

This table lists errors that may be generated when you attempt to run your program. Error code 00-07 08 09 OA OB OC OD OE OF 10 11 12 13 14 15 16 17 18 19 1A IB 1C ID 1E 1F 20 21 22-FF Meaning Input/Output error MEMORY FULL INCORRECT STATEMENT ILLEGAL TAG . CHECKSUM ERROR DUPLICATE DEFINITION UNRESOLVED REFERENCE INCORRECT STATEMENT PROGRAM NOT FOUND INCORRECT STATEMENT BAD NAME CAN'T CONTINUE BAD VALUE NUMBER TOO BIG STRING-NUMBER MISMATCH BAD ARGUEMENT BAD SUBSCRIPT NAME CONFLICT CAN'T DO THAT BAD LINE NUMBER FOR-NEXT ERROR Input/Output error FILE ERROR INPUT ERROR DATA ERROR LINE TOO LONG MEMORY FULL Unknown error code

\
STUDY EXERCISES 221 02,111,1 TAD ICHIAIF" -T 1-11i.MFc
1. a) 1111 b) 0001 1000 c) 0111 0101 1010 1001 d) 1101 0111 1111 0110 2. a) 4 b) 9453 3. a) b) c) d) >F >18 >75A9 >D7F6

ICIUBTICOMB

4. a) 7220 b) 7220

ICIFA IPIP* -TIR


1. Assembler program 2. Sixteen 3. Overflow bit (OF)

=3,

4. a) Label field, Comment field, Operand field b) (*) asterisk c) Op-code field (operation code) 5. Assembler directives give instructions to the assembler program as to what to do with program instructions while the program instructions make up the actual object code. 6. NO (G is not a HEX character) 7. Op-code field (operation code)

IC4-111PCFNT IFZ

41-

1. * R3 CONTAINS VALUE MOV R3,R4 SLA R3,2 SLA R4,3 A R3,R4 2. Workspace Register 11 (R11)

222

STUDY EXERCISES

=. 256 bytes (>100) ,. 4. Conditional jump instructions 5. Return (RT) 6. a) b) c) d) WR,WR-indirect WR-autoincrement,WR Symbolic,Symbolic WR,Indexed
I--II Al IF* -11. FC ffi

1. a) b) c) d) e) 2.

No such instruction as 'AND' No such instruction as 'OR' >5756 >126C >48E8

It is an endless loop because R3 is constantly re-loaded and never will be equal to zero. DATA MOV >0000 R3,@SAVE

3. SAVE

4. Nothing, MPY requires two operands.


IC /-1114 F' -1- la Fc
1.

,63.

LI LI BLWP

ROI- 1000 R1,>2200 @VSBW

''" No key has been pressed. 2. MOVB >01,>8374


IC II-1 IA IF" -II- la R.' 7'
1.

REF

VWTR

R0,>01E8 LI BLWP @VWTR


1-

.L.

7.

REF

VWTR

R0,>01EB LI BLWP @VWTR

\
STUDY EXERCISES 223

3. 4. 5.

Change the value of VDP register 1 to >01. Review pages 117 to 125. The computer views the screen as a series of memory locations in VDP RAM numbered >000 through >767. Place the entry point of the program in a END directive. The program will begin running as soon as it is entered.

6.

You might also like