• Please review our updated Terms and Rules here

IMSAI 8080 programming (I need help!)

ComputerGeek

Member
Joined
Dec 9, 2017
Messages
21
I'm trying to make a simple program that loops through all of the output ports on my imsai 8080 so I can figure out which port my serial connection is located at. My question is how do I use a register to tell the out command which port I want to output to. This is an example of what I want:

MVI B, 00
MVI A, 55

OUT //use B register for port # eg. B is at 00 at the beginning so output to port 00

INR B
JMP 00

So what instruction should I use? Thanks for the help.

-Oliver
 
It's a peculiarity (some would say a "deficiency") that the 8080 does not feature indirect I/O port addressing. There is a single port output instruction - OUT xx, where xx is the port number; it's encoded as D3 xx.

Were I to write your program, it might look like this:

Code:
    XRA  A
    LXI H,PORTNO
    MOV  M,A             ; Set initial port to 0
    MVI  A,55H           ; assuming that's what you want to output
AGAIN:
    OUT  0
PORTNO EQU AGAIN+1
     INR M                 ; bump the port number
     JNZ   AGAIN       ; go for the next pass until the port wraps back to 0
    ...

This "peculiarity" comes back to bite the programmer when said programmer is trying to write a ROM monitor or other code where the I/O port numbers aren't known in advance. It's impossible to do this without executing code from RAM (i.e., create the appropriate IN or OUT instruction stored in RAM)
 
The port 0FFH is usually the lights on the front panel ( upper left ). It seems that the lights are inverted ( BrainFade ). Light is 0 and not is 1 ??
Easy enough to test. Out a 55 in A and write it to port 0FFH.
So now we have a way to see a value we wrote without using a scope or halting the processor.
Now, as Chuck noted, you can not write to a port sequential ports without using self modifying code ( at least with a 8080, the Z80 has a way ).
If you've booted to some BIOS, there is almost always a know location we can write to that place is the stack. This assumes that that code initialized the stack pointer.
We can move our push our self modifying code to the stack. We can see where the stack is pointed to by copying the stack pointer to a some register or we could pop our code back off the stack and modify it before pushing it back. Either way, we can then have a safe place to write our self modifying code ( mostly, I'll explain later ).
Now, even from EPROM, we have a place to write our self modifying code ( mostly ).
Now we can make a loop that will write to each port address and display that address. If we don't have a scope, we can use a volt meter but we'll need to add a delay so we can react to the delay and read the meter with the 0FFH port.
Another possible ways is that your only looking at the address comparitor and don't have a port that you can observe. We can then make a tight loop there we do a number of say 10 port outputs in a row before we do check the tight loop and then say 100 of these loops before we check the time loop. It might make seen to adjust these time loops to be our 1 second delay ( problem left to the OP ).
What if we don't have a volt meter. Hopefully we have a junk box with a LED and an appropriate resistor. We can put them, in series, from +5V, to the output of the comparitor ( being aware that there may be some tiny glitch
as the data bit are making changes ). To know what a real hit looks like we can use the 0FFH comparitor of the front panel, as a reference.
Now to the 'mostly' part. Some people don't like cluttering up memory space with ROM. Especially ROM or EPROM that is only use once at boot time. It would be nicer if we could remove it from the memory map and have RAM there for our larger BASIC program. We'd like to turn that piece off to recover that space, as RAM. A clever way to do that is to have a flop that when written to at a particular port disables or even can re-enable that ROM. If you stumble onto one of these locations, it can do unpredictable things. ( most sytems don't use this type of stuff but you never know ). Another possible problem is that some ports can cause DMA, like from a disk drive, and accidentally over write your program ( I have such a IMSAI setup. In fact I have no system ROM, on reset it DMAs the first sector into memory. After reset, I just start at RAM address 0 and it loads CP/M with my 100% RAM address. ).
These are all potential I gotchas but unlikely. Still if you are stepping your program through the port and some thing kills it, you may have such a problem.
 
The problem is that with the "push" method, you still have to have SP pointing to an area of usable RAM. If you don't have RAM or you don't know where it is, you're out of luck.
 
Well, you can write a routine that simulates the Z-80's "OUT (C), A" instruction on a RAM-less system, but you'd have to use almost 800 bytes of ROM, which is kind of ridiculous. Here's a 781-byte version. (It trashes the flags, B, HL, and SP, so all of your program state better fit in A, C, and DE.)

Code:
OUT_C_A:
    LXI SP, RETADDR
    LXI H, OUTS
    MVI B, 0
    DAD B
    DAD B
    DAD B
    PCHL
RETADDR:
    DW CONTINUE
OUTS:
    OUT 0
    RET
    OUT 1
    RET
    OUT 2
    RET
    ...
    OUT 253
    RET
    OUT 254
    RET
    OUT 255
CONTINUE:
 
Well, I suppose that could be an option, but at 3*256 bytes, in 1974, that was a lot of memory (2708 was 1KB); a 1702 was only 256 bytes, so the code wouldn't fit in one.

Some RAM is usually very desirable for implementing things such as multi-level subroutine calls. One thing I've always wondered about is why a JEDEC-pinout EPROM+RAM IC was never made, as far as I'm aware. It might have to be a multi-die chip, but that's no big deal even for 1974.
 
Last edited:
It sounds like you're trying to figure out a single machine. What hardware is serving the serial output? Or is this a general problem for a monitor you are writing (as I think Chuck and Dwight are considering)?

A program might not work if the hardware is something like the IMSAI SIO-2, since the Intel 8251's require reset, mode, and command bytes to initialize. Other cards, like the PTCO 3P+S, can be hard-wired and the port determined by inspection.
 
I have, in times past, winnowed down the list of ports by doing INs on all addresses and listing the ports that seem to be attached to something. Depending on your machine, unconnected ports might give some definite value such as 00 or FF.
 
Thank you all for responding. My Imsai does have a z80 processor in it. I didn't realize it had another output instruction. I took a look in the z80 manual on how to use it and I can now find my serial port address.
 
I definitely benefited from the ideas here. I had never thought about the lack of indirect addressing for 8080 I/O, nor did I realize that the Z80 had this feature.

Still curious what the serial I/O hardware is in this case.

Also curious about the IMSAI setup Dwight describes, but perhaps this is better suited to another thread...
 
"I have such a IMSAI setup. In fact I have no system ROM, on reset it DMAs the first sector into memory. After reset, I just start at RAM address 0 and it loads CP/M with my 100% RAM address."

I guess this sounds similar to the Tarbell 1011 controller.
 
Back
Top