============================================================================== Programming for Kernel ============================================================================== Adapted from Fargo Sofware Developement Kit by PpHd ------------------------------------------------------------------------------ 1: Introduction ------------------------------------------------------------------------------ It explains the fundamentals of creating Kernel Asm programs, including pointers to sources of information and a description of the high level source code format recognized by the development kit. Kernels, along with the development kit included with it, automatically handle relocation, library linking, and many platform technicalities, such as support for multiple ROM versions and hardware versions. In order to use these features properly, the kernel requires that you follow a certain format in your source code files. There are several impediments to running assembly language programs on the TI-92+/ti-89/v200. The kernel deals with all of these, leaving the programmer to concentrate on what is most important. Here are the three most predominant issues: - Different versions of the ROM are very much alike, but differ slightly in the offset of most calls and the way of getting some undocumented features. - Different versions of the hardware! - The calculator dynamically rearranges its memory, so there is never a sure way to pinpoint the location of a program in order to access data and do JMPs and JSRs. The kernel does not face this problem, since it uses only local calls. For programs, which do move around, the kernel solves this problem by automatically relocating programs before they are executed. - There is very little RAM (about 196K ) to work with, so routines should be optimized to work under low memory conditions. In order to work with this difficulty, the kernel and program format have been designed to take as little space as possible while still being efficient and modular. ------------------------------------------------------------------------------ 2: Lists of helpful information ------------------------------------------------------------------------------ The text files included in the distribution contain information that may be useful for writing Kernel programs. These files are nowhere near complete, so I welcome corrections and additions. The files in this package are not meant teach you from scratch how to program in 68000 assembler; for this, please consult other sources. The text files are as follows: Preos.txt Main documentation SDK.txt This files History.txt Describes the history of Preos LowLevel.txt Describes and lists all the known I/O ports along with descriptions. Traps.txt Describes the TI-92+/Ti-89's usage of the exception vector table. ProgFormat.txt Describes the kernel program format. Vectors.txt Describes whate are the kernel vectors and how to use them (EXPERT). RamCalls.txt Describes the RAM_CALLS and the kernel functions. For all the text files, the following conventions apply: All numbers are in hexadecimal, except for bit indices or numbers ending with the suffix (d). In certain places, the prefix '$' will be used to clarify that a number is in hex. B = byte ( 8 bit integer) W = word (16 bit integer) L = long (32 bit integer) Brackets [] designate pointer indirection. This may be followed by ".B", ".W", or ".L" to designate the size of the integer being pointed to. Remember that the 68000 processor uses "Big Endian" to store integers in memory; the most significant byte (MSB) is stored first, and the least significant byte (LSB) is stored last. For example, the number $1234 is stored as 12 34 in memory. ------------------------------------------------------------------------------ 3: Programming overview ------------------------------------------------------------------------------ Kernel executables consist of two classes: programs and libraries. Programs can be executed directly, and are displayed in the shell. Libraries provide commonly used routines to programs; these routines can be used by simply linking the library to the program. This is an alternative to copying the source for each routine into the source for the program that uses the routines. Asm source code is contained in .ASM files. Compiling a program or library consists of two steps: 1) Assembling the ASM source file(s) using A68k 2.71.F2 at least. 2) Using the Linker to link the object file(s) generated by A68k (Makeprgm). This generates a single .9xz / 89z file. ------------------------------------------------------------------------------ 4: The Kernel source code format ------------------------------------------------------------------------------ This section describes how to create an .ASM file that will be assembled into an object file that the Linker can then link into a working kernel .??z file. This section precisely describes how to create source code. It might also be hard to understand, especially for beginners. To see it in practical use, please examine the sample source code that is included with Preos. +-----------+ | Libraries | +-----------+ To generate a library, you must export a symbol named "_library", and all the library functions, using the template "libname@XXXX" where "XXXX" is a hex number signifying the function index. You should also define the target (ti89 / ti92plus / v200) by exporting : xdef _ti89 xdef _ti92plus xdef _v200 You could add a library version number. A library version number is a byte (0-255), so you should not increase it every day. You should increase it only if you have found an error in your old versions of the library, and newer programs want to be sure that they won't be linked to an outdated library. You should define and export a symbol "_versionXX" where "XX" is an hex number signifying the version number. If you just add new functions to your library, it is useless to increase the version number. This is done like so: include "tios.h" ; Include tios / kernel header file. xdef _ti89 ; Target is ti-89 xdef _ti92plus ; And Target is ti-92+ xdef _v200 ; And also Target is V200 DEFINE _version01 ; Define and export version 01 xdef _library ; Creating library xdef testlib@0000 ; Export one function xdef testlib@0001 ; Export one function xdef testlib@0002 ; Export one function ... xdef testlib@XXXX testlib@0000: ; exported library symbol number $0000 ... testlib@0001: ; exported library symbol number $0001 ... testlib@0002: ; exported library symbol number $0002 ... testlib@XXXX: ; exported library symbol number $XXXX ... END +----------+ | Programs | +----------+ To generate a program, you must export a symbol named "_main". This symbol should point to the program entry point. If you want to give the program a comment/description, you must also export a symbol named "_comment", which should point to a null-terminated string. This is done like so: include "tios.h" xdef _main xdef _comment ; include this only if you define _comment ... _main: ; program entry point ... rts ; return from program ... _comment dc.b "Space Goobers version 19.8",0 END +-----------------+ | Using Libraries | +-----------------+ Library symbols are accessed as "libname@XXXX". However, each library should have its own include file which makes the names much more friendly. For example, "graphlib@0000" is aliased to "graphlib::fill" and "util@0004" is aliased to "util::prep_rect". You could also add in the include file of the library its current version number by adding such a line : DEFINE graphlib@version02 But it requires that the MACRO "DEFINE" is defined (Ok ?). So you could also use : graphlib@version02 xdef graphlib@version02 NOTE: Although exported library symbols are usually functions, they are not required to be so. They may just as easily point to data. If your library has only data which is not relocated (like dc.l address1), you could add this flag to your library : xdef _readonly If it is set, the library won't be unarchive, so you gain some RAM and you can access easily your data. NOTE2: A program can also export functions (Just like libraries). +-----------+ | Using BSS | +-----------+ You can also define a BSS section in your program. What is a BSS section ? It is an area of memory which is not included in your program (it doesn't increase program size). As a consequence, you can fill it only with '0'. When your program starts, the kernel will alloc a handle and fill it with zero. You can access this handle just like normal variables, but you can not access them in Pc form : include "tios.h" xdef _main xdef _comment ; include this only if you define _comment ... _main: ; program entry point ... ; Clean Up handles move.w MyHd,-(a7) beq.s \no jsr tios::HeapFree \no addq.l #2,a7 rts ... _comment dc.b "Space Goobers version 19.8",0 BSS MyHd dc.w 0 END If you have wrotten MyHd(Pc), it won't work. +------------+ | Using Exit | +------------+ When a program terminates in an anormal way (a crash), it may be usefull to clean up some things before returning to Tios, even if kernel tries to clean up as much as possible. You can define an '_exit' function which is called if the program/library terminates in an anormal way : include "tios.h" xdef _main xdef _comment ; include this only if you define _comment xdef _exit ... _main: ; program entry point ... rts ; return from program _exit: ; Clean Up handles move.w MyHd,-(a7) beq.s \no jsr tios::HeapFree \no addq.l #2,a7 rts ... _comment dc.b "Space Goobers version 19.8",0 BSS MyHd dc.w 0 END (From UniOs). Imagine this case: Library X uses library Y in its exit point and Y uses X in its exit point. If X or Y needs any information it had deleted, there is a bug, no matter how sophisticated the anti-crash protection is. My message is that you shouldn't use libraries in your exit point. +-----------+ | Compiling | +-----------+ To compile a .ASM file into a .??p file under DOS: F:\PREOS>asmp Where is the name of the .ASM file, without the extension. Or you may manually do this: F:\PREOS>a68k .asm F:\PREOS>makeprgm Or you may simply type "make" if you have already written a proper makefile. Or you may simply use tigcc if you have installed it : F:\PREOS>tigcc .asm