I started working on this tutorial for Z80 after I started learned how to use basic Z80. Now that I'm getting better, I decided to create the tutorial, presenting the learning of Z80 in the way that worked for me. Here is my request to you. Please read this over with a fine tooth comb. Correct anything you want to correct. Add anything you feel needs added. I want this to be as comprehensive and as detailed as possible. Please and thank you.

Intro and Concepts

Code:
Introduction to Z80 Assembly for the TI Calculator
   
Welcome to the beginner’s guide to Z80 assembly. Before you read on, know that Z80 is not an easy language. In fact, it is an extremely hard language to learn and annoying to code in. However, the learning curve is drastic. This is because, once you understand the concepts behind assembly and what commands do what, Z80 all of sudden becomes less cryptic.

Most programming guides will start you off with a compiler and some code examples, without really explaining why you need to do what you do. For me, this resulted in confusion. As is typical with human nature, the mind cannot begin to comprehend the “what” until it understands the “why”. For this reason, this tutorial will start with the “why”? Please know that you can email me at acagliano.blast@gmail.com at any time if you have any questions. Also, let it be known that this guide will only deal with Z80 for the Texas Instruments graphing handheld, not computer assembly.

The Merits of Z80

   What are the benefits of using Z80 over another programming language? Well, for calculators there are three languages. TI-Basic, Axe, and Z80. TI-Basic is the easiest. It can be programmed directly on your calculator and can do basic math, as well as complex math, create lists, and other cool things. However, it cannot check the battery, set the contrast, or create and delete external variables. Also, TI-Basic is extremely slow. This is because it is an interpreted language, not a compiled one. Interpreted languages are read line-by-line by a processor and are translated before they are executed. I’ll return to this in the next title. Axe is a slightly more powerful language. It is sort of an intermittent language. It has a TI-Basic like syntax, but it compiles on-calc into Z80. This is achieved through the use of the Application “Axe Parser” by Quigibo. A compiler is a program that converts a program into machine code. Axe provides a lot of the power and functionality that pure Z80 does, but it’s command set is incomplete, considering that Axe is a fairly new product.

   Z80 is the most powerful language. It can read and write directly to areas of hardware such as LCD RAM, the link port, the keyboard, and others. It is also so much faster than TI-Basic and slightly faster than Axe. Z80 can modify all memory areas, including system variables, free RAM, and Flash. The significance of all of these will be visited later. It can create, delete, and modify memory without much hassle. This makes Z80 very efficient and useful. It can be used for a wide range of programs. However, for a beginner, I do not recommend using it for anything that requires fractions and math with fractions. You’ll see why in a bit.

The Caveats of Z80

   Just as much as Z80 has benefits, it also has some caveats (negatives). I cannot say weaknesses, because they really aren’t weaknesses. To start with, Z80 has a memory system in which data can be used in increments of one or two bytes. What significance is this to us? Remember when I said that beginners should avoid using Z80 for anything requiring fractions. Well, that’s why. One (1) byte of memory encompasses integers from 0 to 255 (for negatives, you halve that and get -128 to 127). Two (2) bytes of memory encompasses integers from 0 to 65,536 (for negatives, halve that and get -32, 768 to 32,768). Z80 does not really support anything other than integers, although there are ways to achieve them. That is an advanced topic.

   Remember when I said that Z80 can write to memory with little hassle? Well, that also means that it can corrupt your data easily. One mistake in addressing or a mathematical mistake in a routine that edits memory and you can alter data that you didn’t want to. That data is rarely recoverable. If you can get past these risks, then Z80 is the language for you.

TI Calculator Programming versus Traditional Z80 Programming

   What sets TI-calculator programming aside from computer assembly? Well, this is simple and it really doesn’t warrant a whole new title, but whatever. It has to do with the system variables and instructions. Ever wonder why some programs are compatible with some devices and not others. Why can’t I run Windows on an iPod, or Max OS X on a Android? It is because the system equates are different and the memory areas differ. Thus, a perfectly good instruction to move a song from one playlist to another on your iPod might move the headphone driver to the trash on your Android. A program has no idea what device it is on or what it “should” be doing. All it’s doing is looking at your memory and doing what it is told to do.












Important Concepts to Understand

As I said, this tutorial will start with the necessary concepts from the beginning, instead of interrupt the programming to do so as you encounter them. This way, you will enter the commands and programming sections of this tutorial already knowing why certain things must happen.

Addressing

   One of the most important things about learning Z80 is understanding “addressing”. What does it mean? What significance does it have. In your calculator, or any electronic device for that matter, memory is addressed by bytes. Each byte on your calculator has a two-byte numerical address . The first byte is addressed as 0. The second as 1. And so on, until you hit 65,536.

   Now, let’s look at referencing conventions for those addresses. Let us assume we are trying to look at the byte addressed 1000. There are two ways to reference that address.

   1000
   (1000)

   The first one references the address itself. That will always be the two-byte value 1000, regardless of what is held there. This will be further explained in the Pointers section. The second one references the data held at that address. That will be the one-byte value of the data. You may ask why this is so? Well, there is no reason. That is just the convention used by the designers who developed this language. It’s a distinction you just need to remember.

Numerical Systems

Most programmers choose to use other numerical systems instead to represent their numbers. This may be because they wish to compress the data, or they may wish to read it in a way that suits the hardware. Other than decimal, there are two other numerical systems that are commonly used: hexadecimal notation (hex) and binary. To avoid yourself headaches while I elaborate, please remember these rules:
1.   A number in decimal and its hex or binary equivalent are the same number. If you say a word in another language, does its meaning change?
2.   Regardless of the numerical system used to write the number, its value and its size does not change. If you use a one-byte number, it will always be one byte.
3.   You may use numerical systems interchangeably within a program. You simply need to use some sort of notation to indicate so.

Let’s start with hexadecimal. Hexadecimal numbers are denoted by placing a ‘$’ in front of the number OR an ‘h’ after. Do not use both. Also, as a general rule, place an extra ‘0’ in front of the hexadecimal value only if using the ‘h’. That’s because of a compiler error.

 Hexadecimal extends its digits to F, not just 9. So, watch the counting below. Note that once you understand this system, digits carry the same way as they do in the decimal number system.

$00, $01, $02, $03, $04, $05, $06, $07, $08, $09, $0A, $0B, $0C, $0D, $0E, $0F, $10, $11, $12, $13.

   $13 is the hexadecimal equivalent of 19. Both are the same number, and both are one byte large. Hex is mainly used to represent addresses, as well as for tile mapping.

   Now, let’s move on to binary. Binary numbers are denoted by placing a ‘%’ in front of the number or a ‘b’ after. Do not use both. Binary is used mainly for bit-level things, like writing to the LCD (display), link port, and keyboard. This is because those drivers have their memory areas compressed as such. The LCD, for instance, uses only twelve (12) bytes across to hold it’s data. Why? Because a pixel can be only on or off. Why waste a full byte on one pixel when a value of 1 or 0 can suffice and binary can handle that. Remember that eight (8) bits make up a byte, and thus, one byte can hold the values of 8 pixels. Watch me count to 19 in binary.

%00000000, %00000001, %00000010, %00000011, %00000100, %00000101, %00000110, %00000111, %00001000, %00001001, %00001010, %00001011, %00001100, %00001101, %00001110, %00001111, %00010000, %00010001,
%00010010, %00010011

   %00010011 is the binary equivalent of 19. Both are the same number and both are one byte large.

Data Types and Usage

   Now, let’s talk more about data. You know that your calculator has strings, picture variables, graph databases (GDB’s), lists, and matrixes, right? Well, let me rock your world straight away. Wrong! All your calculator has is a sequence of bytes. It has absolutely no idea what the hell type of data is in that type. It is up to you to tell the calculator, through your program, what is there. Isn’t it great to be in control? Also, let me rock your world some more. In Z80 (and in Axe too), it is perfectly fine to call your picture data Str1 and your string data Pic1 (I don’t see why you would want to, though, since you can name your data anything in Z80). It doesn’t make a difference, as long as you remember what you called it. It’s just a name. When you compile your program, the compiler replaces all instances of that name with the address of the data named such. All hail referencing.

   When you write your program, you know the format of the data you are holding there. You also know how it is to be used. So, you will need to write code to handle it in that way. Remember that there are system routines to do some things with data. We’ll deal with that later. But, for ease of use, we will discuss main data types below. Remember, though. Your calculator does not know what data type you are intending. You need to.
Strings
   Strings are data types that hold text. Strings can hold any legal ASCII character, including symbols, numbers, and letters, whether upper or lowercase. Strings are generally sized at one larger than their length, where their length is how many characters they are holding. You make them one larger because you will need to mark where the end of the string is. This is accomplished in two ways. Either you can prepend the string with the length of the string (place a number before the string, where that number is the length of the string. Ex: The string “Hello!” would be written as ‘ 6  H  e  l  l  o  ! ’) or can terminate the string with a zero (Ex: the string “Hello!” would be written as ‘ H  e  l  l  o  !  0 ‘). Strings are very widely used in Z80.
Sprites
   You would not encounter this data type in TI-Basic, because it does not support sprites. The closest you get are the RecallPic and StorePic commands, which save and recall the entire screen. In Z80, you can place sprites of variable height and width on the screen. A sprite is, simply put, an image. Sprite data is put on the screen by writing the data to the LCD port. More on that later.
Numbers
   You may use memory to hold one- or two-byte integers. If you are advanced on doing so, you can use two bytes to hold a one-byte non-integer. In this case, the decimal part can only be accurate in intervals of 255 (1/(2^8)). Note, that the calculator will not do this automatically. You must handle it with your code. You can also create lists (arrays) by storing a succession of numbers into memory.

   You can have your data be almost anything you want it to be, as long as you tell your calculator how to use it.
Pointers

   Pointers are the “bread-and-butter” of Z80. You can’t really do anything without knowing what they are and how to use them. So, here we go.

   Do me a quick favor and scroll back to the section on addressing and look at the two examples of referencing that you saw there. The first example, the one that references the address itself is just one example of a pointer. Why? Because the value 1000 points to the data you want. That’s all a pointer is. It points to data or a section of data. Most routines or commands in Z80 require that pointers be passed to them. More on that in the CPU-Based Math section.

Memory Areas

   Another facet of programming is knowing what areas of memory to use for what. Well, this is one of the hardest tasks a programmer can encounter. Because it often changes depending on the purpose. The good thing is that Z80 gives you a great deal of control over what you can use. Below, I will list areas of memory, their uses, their versatility, and how to write to them.
User RAM
   This memory area is very dynamic and always changes, and it is very unwise to use it within a program. This is because this area of memory is where the calculator stores other programs and non-system variables that you have installed. Using this area of memory can corrupt the data stored there. The user RAM is great for long term storage, by means of external variables. You are free to create a program or application variable and hold your data there. You are also free to modify data held there, so long as you do not alter anything else.
Free RAM
   This area of RAM is great for short term storage. It does not interfere with anything, and will not be used by anything else while you are using it. There are several areas of free RAM that are open for use.

Name   Address   Size   Versatility
APDRAM   $9872   768 bytes   Auto-power down will corrupt
statRAM   $8A3A   531 bytes   Using stat graphing will corrupt
textMem   $8508   128 bytes   --
OpXs   $8478   66 bytes   --
System RAM
   This area of RAM is not good for anything, but sometimes must be modified in order to accomplish things systematically. For instance, let’s say we wanted to put a letter on the screen. In order to do that, you will need to move the cursor. Well, go into the folder in which your choice compiler is and find the compiler’s working folder, where all of its subprograms are. You should see a file named ‘ti83plus.inc’. If you cannot find it, use the one enclosed with this tutorial. Open it. Then, search for the phrase “curRow”. When you find it, you should see “curCol” right below it. Those are the system variables that control the position of the cursor on the home screen. Further down on the list, you should see “penCol” and “penRow”. Those are the variables that control the position of the pen on the graph screen. There are many, many other system variables. You will never need to know their addresses. You will simply need to know what they control.
Archive Memory
   This area of memory is not a part of RAM. It is a much more secure area of memory. It is also write-protected, meaning that you cannot edit it. You can, however, move variables there. This is a great place to keep variables that may be needed later, like game saves. There is a command to do this. That will be discussed later.

CPU-Based Math

   This is the final concept that we need to discuss, before we can start learning the Z80 command set. In TI-Basic, you could store a number into memory, then just have math done with it. In Z80, you cannot do math with the RAM. You must use the CPU of your calculator. You calculator has several registers that are utilized for functions like math. These registers can hold values and do math on them. You must understand the concepts of pointers and addressing before you can understand how to use the CPU effectively. Your calculator’s CPU has two sets of registers, the 8-bit (1-byte) and the 16-bit (2-bytes). Note how, the two byte registers contain the one byte registers. They will modify each other. You will often times be done with a calculation before this becomes an issue, but if it is, there is a way to save the value of a register. More on that later.
8-Bit Registers
A : called “The accumulator”. Used mainly for math.
B : commonly used as an 8-bit counter. Can also be used for math.
C : used for interfacing with hardware. Can also be used for math.
D : not normally used in its 8-bit form, but if necessary, can be used for math.
E : not normally used in its 8-bit form, but if necessary, can be used for math.
F : holds the flags. Never use.
H : another register not normally used in 8-bit form, but can be used for math.
L : another register not normally used in 8-bit form, but can be used for math.
I : the interrupt vector register. It is used by the calculator in the interrupt 2 mode.
R : the refresh register. Can be used to generate random numbers.
IXH : The higher (first) byte of the IX register.
IXL : The lower (second) byte of the IX register.
IYH : The higher byte of the IY register.
IYL : The lower byte of the IX register.
16-Bit Registers
AF : not used because of the F, which is used to store flags.
BC : is also used as a 16 bit counter. Can also be used for math.
DE : often used as a pointer to some memory location, usually a destination.
HL : the general 16-bit register, used everywhere you use 16 bit registers. Used for both math and for holding a pointer to some memory location, usually for a read.
PC : the program counter. Points to the current address the calculator is executing code from. You can’t change this.
SP : the stack pointer. It holds the current address of the top of the stack.
IX : is called an index register. It's use is similar to HL, but it's use should be limited as it has other purposes, and also runs slower than HL.
IY : is another index register. It holds the location of the system flags and is used when you want to change a certain flag. For now, we won't do anything to it.


Using the language

Code:

Assembly Commands and their Uses

   This section will be your first real exposure to the world of assembly. The command set of assembly is very complicated, but mnemonically-based. Please do not be discouraged. You will be asking yourself “How the hell am I going to remember all of these different commands?” Well, you don’t have to. Nothing will stop you from looking back at this document. I’d rather you do that than make a mistake. However, you will find, over time, that if you stick with it, a lot of the commands will just sink in. You’ll remember them and their functions by sheer repetition.

Memory-Based

   In assembly, you will find that almost all of your code will be about moving or reading some memory. TI-Basic programmers take for granted how easy it is to store variables or move a variable, then get it later . When you start to work with assembly, you will realize just how tedious it actually is.

   One of the first things you need to do in assembly is move memory. For that, you will need the ld instruction. That instruction will be your bread-and-butter. Use that instruction to move a value from one location to another. For instance, the following examples are valid:

ld   a, b   ;loads b into a
ld   a, 8   ;loads 8 (as 1-byte) into a
ld   hl, 8   ;loads 8 (as 2-bytes) into hl
ld   a, (hl)   ;loads the 1-byte value at the address pointed to by hl into a
ld   hl, [PTR]   ;loads the 2-byte address of [PTR] into hl

   Remember that when loading data you cannot load a 1-byte value into a 2-byte register or vice versa. Also, please note that you cannot load the value of one two byte register into another two byte register. Instead, you have to load them by loading their 1-byte register components. For example:

Invalid                  Valid

ld   hl, de               ld   h, d
                  ld   l, e

   The ld instruction is all that you need in order to create a pointer. Let’s have a look at the code below:
   ld   a, 0
   ld   (curCol), a
   ld   a, 0
   ld   (curRow), b
   ld   hl, TextMessage
   bcall(_PutS)
   ret
TextMessage:
   .db   “Hello!”, 0
   .end
End

   This code has a lot of elements you will not yet be familiar with. Let’s work with what you do know. The ld instruction. You also know what curCol and curRow are. So, what we first do is load 0 into the register a, then load that into (curCol). Note that you cannot load a value directly into RAM. It must be passed through a register. We repeat the loading for curRow, so that we now have our cursor set to (0,0). But, what is that we are seeing next? A pointer is being created. The pointer is now hl, which holds the address of “TextMessage”. Note that “TextMessage” will have a 2-byte address and that is why we use hl. A pointer of any kind will always require two bytes. The next thing you see is a system routine, known as a base call. It places a string on the screen, at cursor position indicated by the system variables curCol and curRow, with the string to display pointed to by hl. Remember when I said that a lot of system routines require arguments or pointers passed into various locations. The _PutS routine displays until it reaches the end of the string. In this case, the routine reads the 0 at the end to represent the end of the string. The last command you see is ‘ret’ which simply stops the program. It has a more complex purpose, but for now all you need to know is that is what it does here. After that, you have your data and your two END directives. We use two because of a assembler bug that causes the last line of your program to be ignored.

   Sometimes, you may wish to perform a ld instruction multiple times, for instance, to copy a block of memory. In this case, there is a variation on the ld instruction, ldir. This instruction loads the value at the address pointed to by hl into the address pointed to by de, then increases both hl and de, then decreases bc. It then continues to repeat until bc is equal to 0. So, let us say you wanted to copy the ten bytes starting at memory location $1120 to memory location $2316. You could use the following code:

   ld   hl, $1120
   ld   de, $2316
   ld   bc, 9
   ldir

   It is also possible to save the value of a register and get it later. There is something called the “stack” in your calculator, which is a list of values. When you need to retain the value of a register, you can place the value onto the stack. Use the push command for that. Retrieve the value with the pop command. Note, that you need to push a 2-byte register and pop a 2-byte register. Also, if you push hl, you are not obligated to pop hl. That can be used to switch the values of two registers. The ex command can accomplish this as well, but it has very few arguments. Let us suppose that you wanted to swap the values of de and bc, which ex does not support:

   push   de
   push   bc
   pop   de
   pop   bc

   This works because entries are pushed onto the stack in chronological order. So, in the above example, the value of de is pushed before the value of bc. Below, you will see what happens to the stack with the commands above.

value of ‘de’
Previous value
Previous value
Bottom of Stack
push   de        →


Value of ‘bc’
Value of ‘de’
Previous value
Previous value
Bottom of Stack
push   bc   →

Value of ‘bc’
Value of ‘de’
Previous value
Previous value
Bottom of Stack
pop   de   →
**former ‘bc’ is now
in ‘de’

Value of ‘de’
Previous value
Previous value
Bottom of Stack
pop   bc   →
**former ‘de’ is now
in ‘bc’

   This is a very useful technique, as it gives you liberty as to using registers in routines. Oftentimes, if I need to use a register in a routine, I’ll push the register before calling the routine, then pop the value back into the register afterwards. Also, I use this as a great method for collaborating work with others. When several people are doing different parts of a program, sometimes it can be difficult to communicate what data is needed. But, it becomes easier when you provide the data on the stack. For instance, in my Legend of Zelda project, I had another programmer working on artificial intelligence. Instead of having him reload the map data, find the correct screen, then read it for enemies, I pushed a pointer to the map onto the stack. Thus, my helper only need pop the value, saving us both a lot of work.

Controlling Program Flow

   How do we control what a program does when? How do we have it do something only if a condition is true. This is one of the most complex facets of assembly, and so we will address it now. Best to get this out of the way. Since it is important to grasp these concepts in a certain order, I will break this section down into several topics. First, we will learn about the number system in assembly and the flags. Then, we will move to conditionals and how to use them. Then, we will discuss several commands that control program flow.
The assembly Number System
   Counting in assembly is pretty simple. There are no decimals, only integers. You count from 0 up until…well, how high can you count? Remember that in assembly, you can only hold one- or two- byte numbers. A one-byte number can go from 0 to 255 or from -128 to 127 in signed mode. A two-byte number can go from 0 to 65,536 or from -32, 768 to 32,768 in signed mode. So, what happens if you add 1 to the one-byte number 255? Will the calculator self-destruct? Will it take over the world? No! It simply cycles back to 0. Add 1 to 127 in signed mode and you get -128. Why does this happen?

   $FF is the hexadecimal version of the one-byte value 255. If you add 1 to this, the result is $0100. That is a two-byte value. But when you are only supporting one-byte arithmetic, the second byte is dropped and only the $00 is retained. Hence, you cycle back to 0.
The Flags
   Whenever we do any sort of instruction that adds or subtracts, the flags are changed. The flags are held in the ‘f’ register. Please do not confuse these flags with the system flags. To preserve the flag values into a routine, push the ‘af’ register, then pop it when you need them. Each bit in the ‘f’ register means something. Below, you will see them all. Please note that bits are numbered from right to left. Thus the left-most bit is bit 7 and the right-most bit is bit 0.

7th bit Signed flag (S). Determines whether the accumulator ended up positive (1), or negative (0). This flag assumes that the accumulator is signed.
6th bit Zero Flag (Z). Determines whether the accumulator is zero (z) or not (nz). This is the flag you will use a lot.
5th bit The 5th bit of the last 8-bit instruction that altered flags. You will probably not use this.
4th bit Half-carry (H). Is set when the least-significant nibble overflows.
3th bit The 3rd bit of the last 8-bit instruction that altered flags.
2nd bit Parity/Overflow (P/V). Either holds the results of parity or overflow. It's value depends on the instruction used. Is used for signed integers.
1st bit Add/Subtract (N). Determines what the last instruction used on the accumulator was. If it was add, the bit is reset (0). If it was subtract, the bit is set (1).
0th bit Carry (C). Determines if there was an overflow (c) or not (nc). Note that it checks for unsigned values. The carry flag is also set if a subtraction results in a negative number. You will also use this flag a lot.
Conditionals
   One of the advantages of using TI-Basic over assembly is that you can use an If-Then statement to control your program flow. In assembly, you cannot. There is no command-based support for testing conditionals. Instead, you must do some sort of math, check the correct flag, and then do something based on the value of the flag. In TI-Basic, you can simply do If A=5. In assembly, it is so much more complex. You must realize that if you subtract 5 from the ‘a’ register when it equals 5, the result will be 0 and will be non-zero otherwise. Luckily, assembly does provide a command that compares two values. The cp command compares a value with the ‘a’ register, without changing the value in the ‘a’ register. So, a cp 5 will compare 5 to the value in a and will alter the flags as necessary. The zero will be set (z) if the result was 0 or reset (nz) if the result was non-zero. So, the following code will be necessary to achieve If A=5.

   cp   5
   jr   z, DothisifA=5

   We will discuss the command jr later.

   Similarly, we could do the same for the carry flag. In games, where you need to check to see if the player’s health drops below zero, the carry flag is perfect. The carry flag will be set if the result of an operation has “carried” to the other end of the cycle. If we are at 255 and add 1, the result will be 0, and the carry flag will be set. An example of the use of the carry flag is the following code:

   ld   a, 255
   add   a, 1
   jr   c, Dothisifcarryset
Controlling Program Actions
   We have just learned how to use the flags register to determine if certain conditions about a calculation are true. Now, we will learn how to determine what parts of a program get executed if said condition is true. There are several commands that control what a program does. This first are the jp and jr set. The first one is an absolute jump. The second is a relative jump. Let’s start with the relative jump, jr. This jump moves to a spot in memory relative to the current location. It is a one-byte instruction, and as such it can only jump 128 bytes in either direction. It is also slower that it’s alternative. When you can, use jr to save memory. Jp is a two-byte instruction and it can jump anywhere in memory, even outside the program (though I do not recommend this). The arguments for both commands are only the pointer to the place you want to jump.

   There is another command that you can use in a similar manner to the jumps. It is the call. There is one major difference. When you call a routine, the next time the program encounters a ret (return), it will jump back to spot where it encountered the call instruction and continue. Remember earlier, when I said that ret had a more complex purpose than to simply exit a program? Well here it is. Ret and call are opposites. The call command pushes the ‘pc’ (program counter – indicates what location in memory the calculator is executing from) register onto the stack, then loads the address called into ‘pc’. The ret command pops the prior executing location into ‘pc’, causing a jump back to that address. This differs from the jp/jr set, which you cannot ret from. When ret is used in the main program, there are no other executing addresses pushed, so it exits the program.

   All four instructions, jr, jp, ret, and call can take flag-based arguments to make them conditional. The following four commands are valid, as will they be with any of the flags.

   jp   z, Address   ;jump to Address if the zero flag is set
   jr   nz. Address   ;jump to Address if the zero flag is reset
   call   c, Address   ;call Address if the carry flag is set
   ret   nc      ;return if the carry flag is reset

Rendering Text and Images

   Before we get into the ways to display text and images, I just want to rehash what I’ve said once before. Data, whether it be text or numbers or images, is just data. It is up to the user to handle it properly.

   Let’s discuss naming conventions. In a assembly program, you are free to name your code segments or data anything you want. Yes, that’s right! Even code segments. If you write a routine that has to do with moving a variable, you may call it anything you want. Think of the this name in the same way you would think of the Lbl command in TI-Basic, because it acts in the same way, marking a location in the program.
Displaying Text
   The “text” variable class includes letters, numbers, and any ASCII symbols. The display of text is not difficult at all. It requires something to display, a cursor or pen position, and a system call. Before we discuss how to achieve the display, let’s visit the system routines that are needed to display text. Note that these routines should be called with the instruction bcall(.

_PutS: Places a zero-terminated string on the screen, using the large font, at the current cursor location. Accepts a pointer to the string to display in ‘hl’. Advances the cursor to the next free coordinate.

_PutC: Places a character on the screen, using the large font, at the current cursor location. Accepts the ASCII (hex) code of the character in ‘a’. Advances the cursor to the next free coordinate.

_PutMap: The same as _PutC, except it does not advance the cursor.

_vPutS: Places a zero-terminated string on the screen, using the small font, at the current pen position. Accepts a pointer to the string to display in ‘hl’.

_vPutMap: Places a character on the screen using the small font, at the current pen position. Accepts the ASCII (hex) code of the character in ‘a’.

   Also important to the display of text are the four system variables: curCol, curRow, penCol, and penRow. You should load the text position you desire into these variables and they will move the cursor and the pen, respectively. Note that when displaying a string, the position you indicate will be where the string STARTS being displayed.
Displaying Images
   There are several ways to display images, but they all have some things in common. First off, they require data; referred to as a bitmap. A bitmap controls the screen because, when passed though the LCD port, it indicates which pixels are turned on and which are turned off. You will read more about using this in a later section about graphics. For now, all we will discuss is how to achieve an image display...



Note...as I complete sections, I'll upload them to this post.
It seems pretty solid, but it also seems like too much for one person to take in at one time. I think it would be better if this was spread out through the tutorial, like ASM in 28 Days.
souvik1997 wrote:
It seems pretty solid, but it also seems like too much for one person to take in at one time. I think it would be better if this was spread out through the tutorial, like ASM in 28 Days.


I agree. My concern is that I don't want to start replicating asm in 28 days, although I can divide them into lessons.
Random comments:

compiler -> assembler: A compiler turns high-level code into ASM. An assembler turns ASM into machine code.
"Well, for calculators there are three languages": three *widely-used* languages, or three top languages, or something
"However, it cannot check the battery, set the contrast, or create and delete external variables.": ..." to name a few shortcomings".
"Also, TI-Basic is extremely slow.": "can be slow" I think is better
"Z80 is the most powerful language.": "assembly" or "z80 assembly". z80 is a cpu.
"Just as much as Z80 has benefits" -> "Just as assembly has..."
"CPU-Based Math": Slightly confusing chapter name imho, even though I know what you mean.
"It's use": It's is "It is". Its is possessive.

Kudos for STARTING with binary and hexidecimal instead of omitting them or leaving them to the end!
If you'd permit, I'd love to host a copy up on TI-Freakware, in the tutorial archives. Smile
tifreak8x wrote:
If you'd permit, I'd love to host a copy up on TI-Freakware, in the tutorial archives. Smile
I think this is an excellent idea, since TIFreakware is widely recognized in the community as the place you go for tutorials. In the meantime, keep those sections coming so we can critique them. Smile I should mention that I would like a re-working of the 16-bit register descriptions, but I'm still thinking about what exactly.
tifreak8x wrote:
If you'd permit, I'd love to host a copy up on TI-Freakware, in the tutorial archives. Smile


Go for it.

@Kerm: I fixed everything you suggest, minus that heading and the "it's use" cuz i can't find it.
It's under the IX description. Ctrl-f is your friend. Wink
KermMartian wrote:
It's under the IX description. Ctrl-f is your friend. Wink

=) found
More posted.
Quote:

3th bit The 3rd bit of the last 8-bit instruction that altered flags.
I learned something; thanks! Nothing big on this new lesson that I see thus far, although I'll do a second pass later.
I will need assistance with two topics:

1. Writing to the various ports.
2. Application programming.

Would anyone be willing to write those sections? I'll give full credit, of course.


@Kerm, don't thank me, thank z80 heaven. I got that information from there. I don't use z80 heaven much, but I'll need to cite them.
Looking nice, except for the weird highlights from those code boxes XD
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 1
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement