First Steps

by Mark Hutchinson


Issue 31

Jan/Feb 88

Next Article >>

<< Prev Article



IOCB's - easier than you think!

This issue, as promised, we will delve into the working of the IOCB block. This block is controlled by certain locations in memory and if these locations are POKEd correctly then some great things can be achieved.

When you connect the tape or disk lead into the input/output socket of your computer you have given yourself a choice of eight communication channels, 0 7 (remember OPEN #1, etc.?). Each channel has sixteen bytes of memory reserved for it in ROM, from locations 832 to 959. You will be told by various handbooks that you can use all channels for your own use except channel 0 because this is reserved for the screen editor. This is not true, as the 'Forced Read Mode' demonstrated in my last column showed.

Channels 1 to 5 can be used at will. Number 6 is mainly used by the PRINT statement to input characters to GRAPHICS 1 and 2 (for example, PRINT #6; "TEXT"), but can be used as an I/O channel in GRAPHICS mode 0. Due to public demand, I once wrote a column of PEEKs and POKEs in which I mentioned location 703 which would amend GRAPHICS 0. A window would be placed in this mode, normally a full sized screen, and PRINT #6; would have to be used if printing was required on the screen, while PRINT would display to the window.

The last channel, channel 7, is another complicated channel. If you use this channel as your own and try to send something to the printer, an error will occur. LIST (to or from a device) will use this channel, even if it is already open. When finished, LIST will close it. LIST, LOAD, LPRINT, RUN, and SAVE all use channel 7. LOAD and DOS commands close all channels except 0.


Now we know about the IOCB, let us see how we can use it to our advantage.

Firstly we must let the computer know that we require to use a channel. This is done by


where A = the channel number you wish to use, B = a command to be implemented, C = an auxiliary code, normally zero, and D = filename (e.g. D:FILESPEC.EXT or C:FILESPEC.EXT).

Although only C: and not the filename is used by the computer to open the cassette, it is handy for future reference to use this approach with cassette based files. Do not worry for the moment about variable B, I will explain this in a later article.

If we go back to the last column regarding storing screens, we can now use a channel to transfer all our stored screen data to or from cassette or disk. Let's assume we have opened channel #1. We can PUT a single byte that had been stored in the variable Z through to our peripheral by PUT #1, Z or we could transfer a string by PRINT #1, A$. The opposite of these commands are GET #1, Z and INPUT #1, A$ respectively. When we have finished transferring data the computer will add an END-OF-FILE marker and the channel should then be closed by using CLOSE #1.

Listing 1 is a program that will open a file named `SCREEN' on the disk and place the contents of the screen into this file. The screen is then cleared and all the information is taken from the file and placed back onto the screen (note how slow it is). The program can be easily amended for cassette users, but do not forget to reset the tape to the start of the file.


All this can take some time if we use Basic. What we need is a handy machine language routine to speed things up. Fortunately, within the operating system of the ATARI there is such a routine which we can access and let it do all the work for us. No need to panic about Assemblers just yet! This routine is the Central Input/Output which calls the Serial Input/Output to drive the serial bus and peripherals. That sounds like deep computer philosophy and I am sure that you have visions of a program with yards of illegible DATA statements, a USR command that does work but you have no idea how, and you may think that this is just another mystery that will be relegated to the realms of 'Life, the Universe and Everything'. Would I confuse you? The USR call has only half a dozen op codes and they are explained fully in Table 1. All that we need to do is to let the CIO know what IOCB we will want to use and the computer will do the rest!

You will note that I am using the PUT variable statement. The reason for this is a limitation to the PUT string statement. Although the string can be dimensioned to the full extent of spare RAM if needs be (leaving no workspace of course!), the INPUT statement does not generally read strings greater than about 110 characters. This necessitates a FOR/NEXT loop similar to GET. As CIO handles only one byte at a time, it is easier to use PUT/GET routines for fast access times.


And now, finally, the long awaited explanation of fast I/O access! As you will notice in Listing 2, line 10120, the code is very short. Listing 2 is the save routine and Listing 3 is the retrieval. Both are very similar in nature and need few changes (aren't I kind?). The graphic mode and screen colours are noted, as is the amount of bytes to move, and the screen memory position to start from. Both of these programs can be used as a basis for any transfer of large amounts of data, such as fonts.

The USR call lets the program be controlled by the CIO routine at location 58454 ($E456). You must tell the routine what IOCB block you will be using (RD in the programs), then use the offset to set the IOCB details. The offsets are detailed in Table 2 and the line workings are explained in Listing 2. The listings will work just as well with the cassette if the device designation is changed from D: to C:.

One last point should be noted. While running the program, the computer is always updating the screen. If the screen was turned off, the computer would operate faster. In fact up to 30% faster in some cases, so use this little code.

P = PEEK (559):POKE 559,0 This will turn off the screen.
POKE 559,P Turn on the screen.


During the summer months I have received very little correspondence. Does this mean that there are no more beginners reading this column? Or has everybody suddenly become shy? S.A.E.'s as usual to me at 1, Hollymount, Finaghy, Belfast BT10 OGL



Table 1

V 86 $56 LOW BYTE

The stack is like a column of pop up plates that you would find in a self service restaurant. The last to go on top is the first to come off. When a subroutine is called (via USR) the computer places two bytes of information for its own use on the stack. These we do not need and they are taken off by PLA. The third is the IOCB number (I0) and this is transferred to the X register. The program is sent (jumped) to an inbuilt routine in the Operating System at location 58454 (228*256 + 86). This routine will do all the work for us.

Table 2


This consists of eight channels (0-7) each of 16 bytes, from locations 832 to 959. The byte offset (that which is added to the IOCB location) is given below.


0 1 Index to device name for current OPEN file.
1 1 Device number (1 for D1, 2 for D2).
2 1 Action to be taken during open command, in our case 11 for PUT, 7 for GET.
3 1 Most recent status.
4,5 2 Buffer address for data transfer or the address of the OPEN file. In our case the Display List pointer.
6,7 2 Address of device's PUT one byte routine.
8,9 2 Buffer length for PUT/GET routines. In our case the number of PUT's and GET's.
10 1 Used to specify file access.
11 1 Used by device driver.
12,13 2 Disk sector number for NOTE and POINT.
14 1 Byte within sector for NOTE and POINT.
15 1 Spare.



  Listing 1

AtariLister - requires Java


Listing 2

AtariLister - requires Java

Explanation of Listing 2

Line 10000 opens a file called "PICSAVE" to disk.
Line 10010 places the GRAPHICS mode, held in location 87, and all the colours from locations 704-712 into the file.
Line 10020 finds the top of RAM and the screen pointer for the graphics mode you are using. This will change with different modes as each mode uses a differing amount of memory.
Line 10030 sets two variables for use later on.
Line 10040 changes I0 to 16 and adds to IOCB. Channel 0 is at location 832. Channel 1 (our opened channel) is 16 bytes further on. Set the offset for PUT.

Line 10050 works out the high byte of the address.
Line 10060 works out the low byte of the address.
Line 10070 Places the two bytes in the relative IOCB offsets.
Line 10080 works out the number of bytes used by the screen. This is the same as the number of PUT's we will use.
Line 10090 places the number of PUT's in the relative IOCB offset.
Line 10100 Activates the machine code routine, held at an address known to the computer.


  Listing 3

AtariLister - requires Java