Re: A86: TI-86 - how assembly works


[Prev][Next][Index][Thread]

Re: A86: TI-86 - how assembly works



On Fri, 29 Aug 1997, Matthew Johnson wrote:

> I am writing this to figure out how to program assembly using the TI-86 and
> asm86 as a compiler... Maybe some
> of you guys can help me out on some questions I have. If you can answer even
> one question, I would be happy!

This is prime material for a FAQ document.  Anyone want to maintain one?


> .org $D748 ;This is used to tell where all asm programs start on the TI-86,
> correct?

Yes.  It's probably better to use ".org _asm_exec_ram" because it's more
meaningful to the programmer.  _asm_exec_ram is defined in ti86asm.inc.


> --------------------------------------------------------------
> What does the term equate mean? and shadow ram?
> 

An equate is a definition the assembler will use when it's assembling.
For example _asm_exec_ram is equated to $D748.  It makes programs more
readable.

Shadow RAM is a place to store (shadow) information.  When you turn on
your calculator, you see what's on the LCD, but those letters are just
pixels.  The text is shadowed elsewhere.


>
> What exactly is the _cmdShadow? What does it mean? How large is it?
>
> What do the other two shadows mean? How large are they?
>

I think it's where the commands that the user enters are stored.
_textShadow holds the text on the home screen (168 bytes), and
_plotSScreen is probably a bitmap of the graph screen (1024 bytes?).

> 
> How do you display a string in asm using interrupts?
>         Is there another way?

You don't use interrupts; you use system calls.  To display a string,
call _puts, _putps, _vputs, or _vputsn.  For example, to display
"Pat hacked a black calc" in the fixed-width font, use the following
program:

	#include "ti86asm.inc"

	.org _asm_exec_ram

		ld a,3
		ld (_curRow),a    ; set the cursor location
		ld a,0            ; (not the best way, but clear)
		ld (_curCol),a

		call _clrLCD      ; clear the home screen

		ld hl,String      ; hl contains address of String
		call _puts        ; put the string on the screen

		ret               ; return from the program

	String: .db "Pat hacked a black calc",0   ; notice null byte
		

> 
> How do you show characters using an interrupt?
>     Is there another way?

To show a character, call _putc, _putmap, or _vputmap.

>
>         Are the certain preparations you need to make before using graphics?

I depends what you want to do.  Usually, no.


>             How do you change the window property like AxesOff did in Basic

There is a bit table in the RAM, accessed relative to IY.  I don't want to
explain this now, and it's not crucially important for getting started.
Besides that, the information we have about the IY bit table is still
unofficial.

> Is there a faster way to write a pixel, like write it to the video memory?
>         If so, how? How does the video memory work?

The video memory ($FC00) is a 1024-byte bitmap.  If a bit in the memory is 
set, it's corresponding LCD pixel will be black.  Attached to this message
is a FindPixel routine by James Yopp and me.  Its job is to translate 
screen coordinates (x,y) into a memory address and bitmask. After calling
FindPixel, you can do

	or (hl)
	ld (hl),a

to turn on a pixel, and similar things to turn it off.

If you don't need speed, using the ROM _IPoint call will save space.

 
> Are there any more rom calls available that are not in the TI86ASM.INC file?
> Which are
>     they?

There are over 4000.  We don't know them all.  (Well, ONE of us does, but
he's not allowed to disclose the information.)

DISCLAIMER:  Don't trust anything I present between here and my signature.
It's all unofficial, untested, and possibly incorrect (though I hope not).

> 
> How do you multiply or divide in Z80? In Turbo Breakout 2, they had the
> paddle go from a complete
> stop to full speed. How was that accomplished?

Multiply?  Divide?  You have to program it to do so.  Fortunately there
are some routines in the ROM.  If you have a long number that you want to
divide by 10 (decimal), use the following two calls:

	$4044  Divide HL by 10
	$404C  Divide HL by 10, taking into account a previous division

I can't remember the details of these calls because I discovered them
three weeks ago.  They're written down somewhere in a stack of papers on
my desk.  Anyway, these routines aren't all that useful to you and me.

There's another routine, $4048, that divides HL by A.  Experiment to find
out where it puts the quotient and remainder.  (I forget.)

Division by powers of two is fast and easy: use right-shift instructions.

Typically, when you need to mutiply in a program, you know ahead of time
what value you want to use, which is good.  Any positive integer can be 
expressed as a sum of powers of 2, and it's possible to multiply using bit
shifts and additions.  For example, to multiply register A by 21 (the
number of characters in a row of fixed-width text), do this:

	ld b,a   ; save original value for later use
	add a,a  ; a = 2*(original value)
	add a,a  ; a = 4*(original value)
	add a,b  ; a = 5*(original value)
	add a,a  ; a = 10*(original value)
	add a,a  ; a = 20*(original value)
	add a,b  ; a = 21*(original value)

There's also ROM routine to multiply by 10, if you want to save space.

	$41BF  Multiply HL by 10 (decimal)

Here are some additional routines that may be worth calling, if you don't
care about speed.

	$437F  A = C/16
	$4383  A = A/16
	$4387  A = C*16
	$438B  A = A*16

> 
> How did the author of TB2 and Pengiuns figure out how this freaking
> calculator worked!!?!??!
> 

Some of it was disassembly... some of it was... ahem, well... never mind.


> Sorry for all these questions, but you just can't say, its on the internet,
> read a book about it, your not looking
> hard enough because neither is true or possible... and I just cant read 2000
> lines of asm code and figure
> out how everything works...
> 

Take a look at the TI-83 programming info at www.ti.com.  It will describe 
many of the functions in ti86asm.inc.

There are a few examples of source code at www.ticalc.org.

If you're serious about Z80 programming, go to www.zilog.com and order the
"Z80 Microprocessor Family Discrete Devices and Embedded Controllers
Product Specifications Databook."  (It's not listed as that on the page,
but you shouldn't have difficulty spotting which one it is.)

Check your local library for assembly language books, specifically on the
TRS-80 (it used a Z80).  That should give you some examples of program
structure.

--------
Dan Eble (mailto:eble@cis.ohio-state.edu)
         (http://www.cis.ohio-state.edu/~eble)

;--------------------------------------------------------------------
; The Eble-Yopp-Yopp-Eble-Eble-Eble-Yopp Fast FindPixel Routine :)
; 36 bytes / 121 t-states not counting ret or possible push/pop of BC
;--------------------------------------------------------------------
; Input:  D = y
;         E = x
; Output: HL= address of byte in video memory
;         A = bitmask (bit corresponding to pixel is set)
;         C is modified
;
; +-----------+
; |(0,0)      |  <- Screen layout
; |           |
; |   (127,63)|
; +-----------+
;
;--------------------------------------------------------------------
FindPixel:
        ld hl,FP_Bits
        ld a,e
        and $07         ; a = bit offset
        add a,l
        ld l,a
        adc a,h
        sub l
        ld h,a
        ld c,(hl)       ; c = bitmask for (hl)
;48 t-states up to this point
        ld hl,FP_RLD
        ld (hl),d
        ld a,e          ; a = x/8 (byte offset within row)
        rrca
        rrca
        rrca
        rld
        or $FC
        ld l,(hl)
        ld h,a          ; hl -> byte in vid mem
        ld a,c          ; now a = bitmask for (hl)
;121 t-states up to this point
        ret

FP_RLD:  .db $00
FP_Bits: .db $80,$40,$20,$10,$08,$04,$02,$01

.end
;--------------------------------------------------------------------



References: