The Question Mark Affair

Allan Palmer investigates and solves a mystery


Issue 32

Mar/Apr 88

Next Article >>

<< Prev Article



In the Letters page of issue 30 of PAGE 6, a method of getting rid of the question mark prompt when using the INPUT statement in Atari BASIC was given. The example was:


10 DIM A$(10)

30 ? A$

Although this solution works, the Editor stated "don't ask me why!". Well, I believe that I have traced down the cause of this undocumented feature (or is it a bug?) in good old Atari BASIC. So, if you bear with me, I will explain the some of the inner workings of the Atari.


First of all, let us take a look at the format of the INPUT statement. The command may appear as, e.g. INPUT NAME$, or INPUT #2,RECORD$. The #2 (or #16) is a channel number identifying the device from which the input is to be taken. Where the channel number is absent, #0 is assumed which is the screen editor. The channel number points to one of the Atari's eight Input/Output Control Blocks (IOCBs). At this point, you may say if there are only eight channels or IOCBs, which channel does an INPUT #16 statement use? From the fact that the example quoted at the top of this article works, it appears that channel 16 is treated as channel 0.


At this point I thought that all that was happening was that any channel number greater than 7 (the eight IOCBs are numbered 0 to 7) was being treated as 0. I then tried the example with INPUT #10 in place of INPUT #16. The result was Error 20, which when looked up in the back of Your Atari Computer is explained as "Bad Channel Number The program tried to use channel 0 or a channel number larger than 7". Confusion reigned 10 is larger than 7 and fails, but 16 works! Some further experimentation showed that channel number 32 works, but using channel 17, error 131 appears ("A GET or INPUT statement used a channel opened for output only").


At this point, I started looking through my collection of Atari-related books and magazine articles. The obvious place to find the key to this obscure mystery seemed to be one of Bill Wilkinson's 'Insight: Atari' articles in COMPUTE! magazine. After some delving I found the clue I needed in Bill's articles in the November 1981 and January 1985 issues. Both columns describe the use of IOCBs, particularly as used from assembly language. Bill explained that when undertaking input/output in assembly language via CIO, the program should specify which channel to use by passing the relevant IOCB number times 16 in the X-register. Each IOCB is 16 bytes long, so the X-register value is used as an offset to the start of the whole IOCB area.


Things began to fall in place now. When an INPUT command specifies channel n, the Atari operating system is actually using 16 times n. So, channel 0 is 0, but channel 1 is 16, channel 2 is 32 ... channel 10 is 160 ... channel 16 is 256, channel 17 is 272, etc. However, an eight-bit computer like the Atari stores values in bytes of memory where each byte consists of eight bits the maximum value in one byte is 255, thus any value greater than 255 must occupy two bytes. I now turned to COMPUTE! Books' Atari BASIC Source Book compiled by Bill Wilkinson (who else?) and began to peruse the listing of the original source code for Atari BASIC included in that publication.


After studying the source code for a while I managed to identify what was happening. There are in fact two areas to consider. Firstly, when processing an INPUT command, BASIC only prints a '?' prompt if the channel number supplied is 0 (zero). Thus for channels 1 to 7 (corresponding to the remaining IOCBs), no '?' is printed when an INPUT command is processed. Secondly, the input channel number is multiplied by 16 to be passed to the CIO system to specify the relevant IOCB. Logically, the channel number is not expected to be greater than 7. Unfortunately, BASIC uses a one-byte field to pass the channel number times 16 to the CIO system to initiate an INPUT command. However, this field is validated to see if it is not greater than 7 times 16 by checking if the field is negative by using a BMI instruction. In an eight-bit byte, the setting of the most significant (left-most) bit indicates a negative value. Take a look at the binary equivalents in Table 1.

In the right hand portion of the Binary equivalent column, values equivalent to channels 8 to 15 inclusive have their negative bit set and result in an Error 20 from BASIC. Channel 16 results in a binary equivalent setting the least significant bit in the left hand portion only, the right hand portion remains equivalent to zero. Consequently, BASIC can be fooled if a channel number which is a multiple of 16 is supplied in the INPUT statement because the byte being tested remains zero.

Channel Channel x 16 Binary equivalent
0 00000000 00000000
1 16  00000000 00010000
2 32 00000000 00100000
3 48 00000000 00110000
4 64 00000000 01000000
5 80 00000000 01010000
6 96 00000000 01100000
7 112 00000000 01110000
8 128 00000000 10000000
... ... ... ...
15 240 00000000 11110000
16  256 00000001 00000000
17 272 00000001 00010000
... ... ... ...
32 512 00000010 00000000


Referring back to the original example then, because the channel number specified in the INPUT command is a multiple of 16, it is acceptable as a valid parameter because it in turn is multiplied by 16 and the least significant byte remains at zero indicating channel 0 (the screen editor). However, because the value in the channel actually specified in the INPUT command is not zero, the '?' prompt does not appear.

Hopefully, this convoluted investigation will explain why there is a way to get rid of the '?' prompt when using the INPUT command and the screen editor.

My thanks must go to Bill Wilkinson for all the bits of information and insight (no pun intended) that he has provided to Atari enthusiasts over the years. Without the background data that he has published I am sure our understanding of the Atari would not be as great as it today.