Tuesday, February 9, 2010

Assembly Language for Z80 processor on TI83+ Calculator

This article is about assembly langauge for the z80 processor, and running the code on the TI83+ calculator system. The z80 processor is a robust, 16bit processor produced by Zilog. This processor is used in your TI83+ calculator, GameBoy Color, Sega Game Gear, and a fair list of electronics. I'm writing this article for both experienced assembly langauge guru's interested in z80 processor and n00bs who want to get their hands in on the action.

WHY LEARN ASSEMBLY LANGUAGE AT ALL?
I can tell you personally that it is a rewarding langauge to understand because you will have that much more understanding of computers and gives you much more control over memory. This is also the mnemonic code for for a byte instruction set. The byte instruction set is what is used for shellcode!! Shellcoding is part of remote buffer overflows part of leet still legit hacking methods. Another reason is because this is FUN STUFF! come on! get your hands dirty and do some z80. Once you know one assembly language, you can teach yourself any assembly language for any processor.
This article is from information, research and hacking around a couple years ago over a christmas break.

WHAT IS GOIN DOWN IN THIS ARTICLE?
In this article I will explain what you need to set up your coding environment, Learn instructions of z80 processor along with nifty Interrupt Service Routines provided by TI83+ System, write a HelloWorld application and do some simple math instructions, along with tangents I find relevant from personal experience. I hope this is one of 2 or 3 articles, where the second article should cover arrays, conditional statements, and write a Game. The 3rd will cover the stack and monochramatic graphics.

YOU NEED!
-Windows XP (Linux is available, but I couldn't find a decent assembler/linker)
-Silver USB cable available at (http://education.ti.com/educationportal/sites/US/productDetail/us_connectivitycable_silverusb.html)
this is used for transfering files to and from the calc and PC (note: if you're cheap you could make one yourself if you have the skillz :X, if so hats off to you)
-TASM.exe (Table assembler NOT Turbo assembler) This is the assembler
-devpac8x.com This is the linker it generates the executable code that will be the file to upload to calculator

SETTING UP THE ENVIRONMENT?
I'm assuming you have the silver link cable now and the software that came along with it installed on your PC. Now...

1) Now make a folder called z80 and put both the TASM.exe and devpac8x files in same directory.
2) Make a makez80.bat batch File with following code...

CODE :
__________________________________________________________________________
::@Author - xfelix
::@File - makez80.bat
::Description - assemble and link z80 programs

tasm -80 -i -b %1.z80 %1.bin
devpac8x %1
__________________________________________________________________________

3) Open up a DOS shell and move to TASM root directory

Environment is set now let's diggin.

Before you Begin
----------------
Writing instructions and registers are not case sensitive although useing labels are, but as one is learning assembly language they should develop their own style of writing, this can be thought of as your trade mark as a programmer. You can tell alot about a programmer just by the way they write code, and once one has been programming for a while they can tell the difference between a true poet and a script kiddie. So when doing this tutorial take your time, and make sure you are taking in many of the juicy details because this is a jam packed tutorial. Even though this tutorial is broken up in to two parts, any one is welcome to break it up into their own parts, and follow it at their own pace, this is a good strategy to approach this article.

Part 1
-------

Instructions
There are many instructions provided with a processor, which can be thought of as commands to peform some action. An action could be to move data from a register to memory, to add the data of one register to another register, compare two registers, jump to a location in memory, etc. If one has ever done assembly language for the Intel-IA32 processor there are many instructions that you will probably take for granted when working with Z80 processor. The z80
processor does not contain a multiply instruction MUL or a divide instruction DIV like the intel IA-32. One must develop their own clever ways to do this.

Registers
Registers are used for quick access of memory and is what also performs all computations. You can move data from memory to a register in the processor, move data froma a register to memory, and move data from a register to another register, but one may never move memory directly to memory. The Instuction to peform these actions is LD, which is short for load. The format of this instruction is

LD DESTINATION, SOURCE

where DESTINATION can be any register or memory address, and SOURCE can be any register or memory location. What ever the type of data storage it is (memory or register) it will move the data in the SOURCE storage to the DESTINATION storage. One can also use constant number values as the source seen in the sample code below...

First a table of the z80 register names for 8 bit and 16 bit, then some sample code.

8 bit registers
---------------
A - 8 bit accumulator register
B - general purpose / b is high byte of BC register
C - general purpose / C is low byte of BC register
D - general purpose / D is high byte of DE register
E - general purpose / E is low byte of DE register
H - H is high byte of HL register
L - L is low byte of HL register

16 bit registers
-----------------
BC - general purpose/base pointer register
DE - general purpose register
HL - 16 bit accumulator register
SP - stack pointer
IX - Index register
IY - Index register

I don't use the last two register IX and IY very often since they both contain (I) register, which can make life hell, so I avoid them at all costs, but there are times when they are necesarry.

SAMPLE
------
CODE :
__________________________________________________________________________
LD a, b ;moves the contents of register b to register a
__________________________________________________________________________

CODE :
__________________________________________________________________________
LD a, $10 ;moves the constant hexadecimal number 10
LD b, a ;now we move the contents of a to b
LD HL, memoryData ;moves the memoryData memory address into HL,
LD (HL), b ;moves the contents of b into the memory address storage

memoryData: .db 0 ;memoryData variable initialized to zero
__________________________________________________________________________

*****CAUTION****
I do not recommend moving data into memory similar to the following example

CODE :
__________________________________________________________________________
LD ($FFFF), a
__________________________________________________________________________

...although this is valid and will execute your calculator will most likely crash and your RAM will erase itself and you will have a freshly wiped RAM on your hands. While programming on your TI83+ it will most likely crash often, even if you only have logic errors. This is due to the fact that programming on your calcuator is in REAL mode, unlike when you program on your computer which is in PROTECTED mode.

HelloWorld

If you have not figured out by now a semi-colon ; is a comment in TASM and most other assembly languages. The white spaces used before and after the instruction is a TAB space, TASM will not like your code if you don't use a TAB space inbetween your instruction and storage placers.

CODE :
__________________________________________________________________________
;***************************************************************************
;@author - xfelix
;@date - 12/05/09
;@file - hello.z80
;@description - This is a HelloWorld application for learning how to
; develop z80 applications for TI83+ Calculator :D
;Compile Instructions: tasm -80 -i -b hello.z80 hello.bin (For linking)
; devpac8x hello (For byte code)
;***************************************************************************

#include "ti83plus.inc"

.list
.org $9d93
.db $bb,$6d
code: xor a ;zero a by exlusive or-ing it by itself
ld h, a ;load a into h
ld l, a ;load a into l
ld (PenCol), hl ;put hl in PenCol memory

ld hl, str1

bcall(_PutS) ;_PutS takes HL register as parameter
bcall(_NewLine)

ret
data:
str1: .db "Hello World!! w00t, calc codez (^_^!)", 0
.end
.end
__________________________________________________________________________


Explanation

Line 1 #include "ti83plus.inc"

The #include directive is similar to the one in C only instead of including .h (header files) you can include .inc (include files). The ti83plus.inc file contains names of kernel functions and important memory locations used by the mirageOS.

Line 2 .list
Line 3 .org $9d93
Line 4 .db $bb,$6d

make sure these lines are always in any program you ever run. Line 3 contains the .org directive, which specifies where in memory the application will run, which is always $9d93. Make sure this number does not change because your program will not run correctly and crash your calculator, I was writing a program before and accidently typed $9593 instead, but it took me a long time to figure out why my application wasn't working. It is suddle details like this that can hold you back. Line 4 .db (define byte) will define two bytes at the very beginning of the program $bb,$6d. These two bytes are magic numbers that the mirageOS will like to see to make sure it's executing a valid TI83+ progam.

Line 5 xor a

The only instruction in this program that you have not seen before is xor, which will perform an exlusive or operation on the register given with the a register. Since I have given the (a) register, the operation will be a XOR a, which zero out the a register. If I had the following sample code

xor b ;Then the operation will become a XOR b

You should know what Line 6-10 does by reading the comments, but I would like to explain more Line 11

Line 11 bcall(_PutS)

bcall instruction is defined in the include file as well as the (_PutS) function name. The kernel function (_PutS) takes the hl register as a parameter, which should be the memory address of the string you would like to be displayed. The (_NewLine) kernel function will go to the next line for printing data or recieving input.

Line 14 ret

The ret instuction returns to the memory location that called the executuable. This memory location is stored in the stack, but I will talk more about the stack and procedures in the 3rd article.

Labels
---------------

There are three labels in this program and two of them are optional that I put in for clarity, so I know where my code section and data section are located. The code section is where your code should be, and the data section is where you should declare all of your variables. Here is how you declare a string variable


Line 16 str1: .db "Hello World!! w00t, calc codez (^_^!)", 0

Notice the name of the variable is just a label followed by a .db (define byte). Inorder to declare a 16 bit variable you would use the following sample code

CODE :
__________________________________________________________________________
myNum: .dw $1337
__________________________________________________________________________

... which is a .dw (define word) a 16 bit variable myNum, set to a value of $1337 in hexadecimal. Typically the data section is before the code section, but people who write viruses and shellcode will put the code section first followed by data section ^.^ Try to rewrite the hello application so that the data section comes before the code section.

Make sure there are two .ends at the end of the file since who ever wrote TASM screwed up and expected two .ends as if it's already not hard enough to make a typo mistake.

Compiling

----------


Make sure you save the file as a .z80 file, I called mine hello.z80. Then type the following in command prompt makez80 hello and should then assemble and link the file like in this image.




Now once this is accomplised this makez80 has assembled and linked your application, which has generated a TI83+ executable file hello.8XP. Asssuming you have installed the software that came with your TI83+ silver link cable, right click the file and hit send to TI device, and you will get a menu like this



It will automatically start the transfer after a short time has passed.

Now pick up your TI83+ calculator and hit the PRGM button and you should see your application sitting in RAM Hello. To Run this program you must hit
-2nd Catalog
-Choice Asm(
-Now hit the PRGM button
-Choose the Hello application
-Now hit ENTER

Your application should have run and exited very quickly ^^ congradulations!! you've run your first application on the z80 processor. Now take a break or play around with the output text or what not, but wait to continue to Part 2 of this paper, you have taken in alot of information. But before I begin part 2 here is another useful kernel function bcall(_DispHL) (display HL register), this function will dump what ever data is stored in the HL registers, so feel free to play around with loading data from memory to registers during this grace period :D

Part 2
------------------
Math instructions

I will discuss the following math instructions ADD, INC, DEC, SUB, and SRL, but there are many more. Check the references for an entire list of the Z80 processor instructions set and more. The format of these instructions is similar to the LD instruction only when adding the 8 bit registers make sure that the (A) register is always getting added to, and for 16 bit registers either the HL,IX, or IY registers. This is because A and HL registers are considered the accumulator registers for their respective size, it's just how it is. All assembly languages have their accumulator registers, only Z80 takes advantage and is more strict then any 32 bit processor. Say we have to following sample code

CODE :
__________________________________________________________________________
LD HL, $10
LD DE, $5
ADD HL, DE ;Add the contents of DE register to the HL register
bcall(_DispHL) ;dump the HL register in decimal notation
__________________________________________________________________________

This will add the contents of the DE register to the contents of the HL register. After the ADD instruction is executed the HL register will equal $15 and the DE register will equal $5. When executed the following output of this sample code will be 21. Caution the z80 processor does not support the following instruction

CODE :
__________________________________________________________________________
ADD BC, DE
__________________________________________________________________________

it's simply not supported by the Z80 processor to peform this operation, which can cause headaches ontop of headaches at times. One may also add to a register directly from memory, but never to memory from a register. Check out the next example

CODE :
__________________________________________________________________________
remainingHealth: .db $35

LD A, $65 ;damage after getting knifed in counter strike sorce into B register
LD HL, remainingHealth ;HL register points to remainingHealth memory address
ADD A, (HL) ;adds the contents from the memory to the B register

;There is a suddle problem in the above code can you think what it is?? Hint what is the maximum number that can fit into an 8 bit register?
;Can you fix it??
__________________________________________________________________________

When you load the memory address of the variable into the HL register, it is essentially pointing to that place in memory, which is similar to how pointers in C and C++ work. When you put parantesis around the HL register you are accessing the byte data at the location in memory. To give you an idea of how working with arrays would work to get the next item in the array you would use (HL+1), then (HL+2), etc. How would you display the register in A?? here is the following code
CODE :
__________________________________________________________________________
LD HL, 0 ;zero/clean out the HL register
LD L, A ;Load A register into lower register of HL register
bcall(_DispHL) ;Display HL register contents
__________________________________________________________________________

The subtract instruction will substract the contents of the specified register from the A register. Here is a following sample code

CODE :
__________________________________________________________________________
LD A, $FF ;Load the hex value $FF into the A register
LD B, $FE ;Load the hex value $FE into the B register
SUB B ;Subtract the contents of B register from A register, aka A=A-B
__________________________________________________________________________

After the following sample code is executed the A register will be equal to 1. The next two instructions are insanely easy to follow INC and DEC. The INC instruction will increment a register by 1, and the DEC instruction will decrement a register by 1.

CODE :
__________________________________________________________________________
DEC HL ;decrement HL by 1
INC HL ;increment HL by 1
__________________________________________________________________________

HL register will not be changed after the execution of the previous sample code. Now the next instruction that will be discussed is the srl instruction, which stands for (Shift Right Logical). This performs a bitwise operation of shifting the bits to the right by 1 on the specified register. Shifting bits to the right on a register is like dividing the contents of the register by 2^n where n is the number of shifts to the right. If we had the following value in the A register $FF then A will look like this in binary:

A: 11111111 //Also equal to 256 in decimal notation

Now if we call the SRL instruction like this

CODE :
__________________________________________________________________________
SRL A
__________________________________________________________________________

All the bits in the A register will be shifted to the right and drop off the right most bit to the carry flag. I will discuss more on flags and their purpose in the 2nd article when I talk about conditional statements, loops, etc. Now the A register looks like this

A: 01111111 //Also equal to 128 in decimal notation or 256/2 which is what happen after the SRL instruction executed

Now let's right a useful application with the knowledge you've accumulated. The application that We will write is one that will determine the first five numbers of the fibonacci sequence. It's important to note that this code would be alot shorter if we had learned loops, which we haven't yet and/or the use of macros and procedures which are also in later articles. Anyway here is the code that will display the first 5 numbers of the fibonaccie squeunce. It is also important to note that (_NewLine) will destroy all registers:(

CODE :
__________________________________________________________________________
;***************************************************************************
;@author - xfelix
;@date - 01/06/10
;@file - fib.z80
;@description - This is a Fibonacci sequence application that will determine the first
; 5 numbers of the Fibonacci sequence. This application is for learning
; how to develop z80 applications for TI83+ Calculator :D
;Compile Instructions: tasm -80 -i -b fib.z80 fib.bin (For linking)
; devpac8x fib (For byte code)
;***************************************************************************

#include "ti83plus.inc"

.list
.org $9d93
.db $bb, $6d
code:
LD A, (firstNum)
LD HL, secondNum
LD B, (HL)
LD HL, $0000

LD L, A
bcall(_DispHL)
bcall(_NewLine) ;Destroy Registers in process of going to new line

LD HL, $0000

LD L, B
bcall(_DispHL)
bcall(_NewLine)

LD A, (firstNum)
LD HL, secondNum
LD B, (HL)
LD HL, $0000

ADD A, B
LD (firstNum), A ;save the third number to first number

LD L, A
bcall(_DispHL)
bcall(_NewLine)

LD A, (firstNum)
LD HL, secondNum
LD B, (HL)
LD HL, $0000

ADD A, B
LD (secondNum), A ;save the fourth number to second number

LD L, A
bcall(_DispHL)
bcall(_NewLine)

LD A, (firstNum)
LD HL, secondNum
LD B, (HL)
LD HL, $0000

ADD A,B
LD L, A
bcall(_DispHL)
bcall(_NewLine)

ret
Data:

firstNum: .db $1
secondNum: .db $1

.end
.end
__________________________________________________________________________

Final Notes
--------------------
This ends the first article of programming in assembly language for the z80 processor on your TI83+ calculator. I hope it was useful and you picked up a thing or two about assembly language. I have listed references below for instruction set and tutorial/ code examples, which should be useful, you don't have to wait for the second article inorder to continue your quest of learning z80 assembler. Once you have been working with assembly language you have my permission to walk proudly amoung your programmer/hacker peers, and can look down on those who don't know assembly language. You are now apart of the z80 scene.

References
-------------------

z80 Heaven tutorials http://z80-heaven.wikidot.com/system:tutorials
z80 instruction set http://nemesis.lonestar.org/computers/tandy/software/apps/m4/qd/opcodes.html
official Zilog manual http://www.zilog.com/docs/z80/um0080.pdf

No comments:

Post a Comment

try to make something then you never be lost

+++

Share |

"make something then You never be lost"

wibiya widget