• Please review our updated Terms and Rules here

TRS-80 Level II BASIC cross-assembly source?

For those looking for commented TRS-80 Level II v1.0, Model III, TRSDOS v1.3, TRSDOS v2.3, etc., please visit
Yup, that's a good reference, and I link to it in my documentation. It's aimed at a very different audience from my files, though. First, it's not in the form of a file that can be re-assembled. Second, it's extremely verbose, which is no doubt a good thing for people unfamiliar with Z80 assembly language, but makes it more work to read for more experienced Z80 programmers. For example my disassembly of a couple of simple routines is:

Code:
;   ♠BC ♣AF Delay loop, count in BC.
pause       dec  bc
            ld   a,b
            or   c
            jr   nz,pause
            ret

;   The RESET button generates an NMI, not an actual reset.
NMI         ld   sp,$0600       ; ???
            ld   a,(diskstat)   ; $FF if no expansion interface present
            inc  a
            cp   $02            ; disk present?
            jp   nc,rst00       ;   yes: restart as if power-up
            jp   ready          ;    no: go to BASIC prompt

On that web site, it's expanded to something much larger and more verbose; see the attached image.

I'm not saying that the web site is bad; it's a well done resource, and no doubt especially good for Z80 beginners. It's just aimed at an audience rather different than mine.

BTW, the web site doesn't explain why the stack pointer is set to $0600, which is pointing into ROM.
 

Attachments

  • 1712785252675.png
    1712785252675.png
    123.1 KB · Views: 8
; The RESET button generates an NMI, not an actual reset.
NMI ld sp,$0600 ; ???

BTW, the web site doesn't explain why the stack pointer is set to $0600, which is pointing into ROM.
Nope - never found any reference ANYWHERE to why they picked it, except that its a super nice round number in Octal (3000O).

In going through the original ROM source, whenever they hard code a number of bytes like that is when they were forced to use a hard RAM location. When they set up the vectors, they used "$CODE + 40410 Octal" instead of a nice label. Pointing the SP at at non-writable location would really only be known to the authors.

If you trace the ROM, before it hits 0066H the SP is set to FFBF and it has 8 values in it already. Once you hit 0066H the stack just points to the instruction at 600H, but in LSB / MSB format so they are backwards insofar as the opcode processing would normally go. Nothing really useful. It sits that way, and certainly nothing uses it, until it gets reset to either FFCBH at 19AEH if there is no disk drive, or 407DH at 0693 if there is a disk drive.

I suspect that unless someone corners Bill Gates, and he even remembers, that little nugget is not going to get clarified
 
Once you hit 0066H the stack just points to the instruction at 600H, but in LSB / MSB format so they are backwards insofar as the opcode processing would normally go.
Well that's an interesting little mystery.

If the data to which SP points are taken as any address, as a ret would do, you get $9FE, but that just points to one byte before the start of a math routine (and that byte doesn't appear to act as a "skip instruction" trick), so that doesn't seem to provide any functionality. I suppose it might help in a debugger or simulator to catch where something is going wrong, and then just could have been left there afterwards.
 
Well that's an interesting little mystery.

If the data to which SP points are taken as any address, as a ret would do, you get $9FE, but that just points to one byte before the start of a math routine (and that byte doesn't appear to act as a "skip instruction" trick), so that doesn't seem to provide any functionality. I suppose it might help in a debugger or simulator to catch where something is going wrong, and then just could have been left there afterwards.
I did use a debugger to do that analysis. TRS80GP allows you to set breakpoints, so I broke at the routine. Neither branch (disk present / disk missing) uses the stack between the time it is set to that value and the time it is reset. My only guesses are [1] when the NMI hits, they want to work independently of RAM size, and pulled the highmem stack pointer down to an unchangeable area of memory or [2] they did this for debugging purposes, since all references in the original source code that are based on hard addresses are coded the same way ... $CODE + xxxx instead of using labels. If anyone reading this is friends with Bill, please ask him!
 
  • Like
Reactions: cjs
I don't know why I never noticed that LD SP,0600 in the reset button NMI handler. I've certainly had years to get familiar with the contents of that ROM. Anyhow, it's pointless because unless something interrupts it, nothing will use the stack until it can be loaded again, either by rebooting to the disk loader, or the BASIC warm-start.
 
Anyhow, it's pointless because unless something interrupts it, nothing will use the stack until it can be loaded again, either by rebooting to the disk loader, or the BASIC warm-start.
Nothing can interrupt it (except another NMI), as far as I can tell. On receipt on an NMI, all other interrupts are masked (an implicit di instruction, basically), and from a quick glance it looks to me as if all the code paths from there reload the stack pointer before ever enabling interrupts again.

This whole investigation has been quite interesting to me; I didn't even realise that the so-called "reset" button doesn't generate a reset signal, but an NMI. Which is maybe something to keep in mind when you're building devices to add to the system; you'll receive a reset at power on, but not from the reset button.
 
Back
Top