When I first started using machine code one of the
first problems I encountered was what program to write. To solve this
problem I looked through some back issues of computer magazines to see
what other people had written. One feature that seemed to crop up
fairly often was the use of IOCB's and in particular the section of
CIO's. As a result I learned all that I could and finally became
proficient in their use.
The name IOCB stands for Input Output Control Block
and CIO stands for Central Input Output utility. As the names suggest
they also allow the user to control the input from and output to
various devices. The devices that are normally controlled using CIO's
are cassette recorders, disk drives, printers, the screen and a few
others. By changing a few parameters it is possible to send any amount
of any sort of data to a device.
So what? Well if you have ever tried to do graphics
in machine code or access data files on a disk or cassette or dump a
screen to the printer then you will appreciate just how difficult it
can be.
Those of you who are familiar with the BASIC command
OPEN #n will have a head start because CIO's are exactly the same
thing. If you have never come across the OPEN command then look it up
in a users manual.
There are certain differences in the way CIO's are
used from machine code and the way they are used in BASIC but these
will become apparent as you use them. The main thing to remember is
that there is no automatic error checking in machine code so if you
make an error and don't check for it, all sorts of problems will
arise. The most common mistake is to try and access devices that are
not open or to try and open devices that are already open.
DEVICE NAMES:
These are the names used when you open a device.
E: |
Screen editor (see Basic Manual) |
S: |
Screen graphics for graphics
modes |
P: |
Printer (output only) |
K: |
Keyboard (input only) |
C: |
Cassette recorder |
D:*.* |
Disk directory |
D:filename.ext |
Disk files |
OPENING AN IOCB
Before you can open an IOCB it must first be closed.
This is to prevent errors occurring when you attempt to open an
already open IOCB.
To close an IOCB, you must first choose which one
you are going to work with. There are five possible choices here and
they correspond to the numbers 1,2,3,4 and 5 in BASIC. In machine
code, you choose the number by loading it into the `X' register. The
number you load is '#$10' for IOCB 1, '#$20' for IOCB 2 etc. When you
have decided, use Listing 1 to close that IOCB.
00010 |
LDX #$10 |
; IOCB #1 |
00020 |
LDA #$OC |
; COMMAND FOR CLOSE |
00030 |
STA $342,X |
; COMMAND LOCATION |
00040 |
JSR $E456 |
; CALL OS ROUTINE |
00050 |
LDA #$03 |
; COMMAND FOR OPEN |
00060 |
LDX#$10 |
; IOCB #1 |
00070 |
STA $342,X |
|
00080 |
LDA #LAB |
; LOW BYTE OF DEVICE NAME |
00090 |
STA $344,X |
; BUFFER ADDRESS (LOW) |
00100 |
LDA /LAB |
; HIGH BYTE OF DEVICE NAME |
00110 |
STA $345,X |
; BUFFER ADDRESS (HIGH) |
00120 |
LDA #$08 |
; OPEN FOR OUTPUT |
00130 |
STA $34A,X |
|
00140 |
LDA #$00 |
; JUST TO BE SAFE BUT NOT
NEEDED |
00150 |
STA$34B,X |
|
00160 |
JSR$E456 |
|
00170 |
LDA #$08 |
; GOING TO SEND STRING |
00180 |
LDX #$10 |
; IOCB #1 |
00190 |
STA $342,X |
|
00200 |
LDA #MES |
; LOW BYTE OF MESSAGE ADDRESS |
00210 |
STA#344,X |
|
00220 |
LDA /MES |
; HIGH BYTE OF MESSAGE ADDRESS |
00230 |
STA $345,X |
|
00240 |
LDA #$FF |
; MUST BE MORE THAN MESSAGE
LENGTH |
00250 |
STA $348,X |
; BUFFER LENGTH HELD HERE (LOW) |
00260 |
LDA #$00 |
; JUST TO BE SAFE |
00270 |
STA #349,X |
; BUFFER LENGTH HELD HERE
(HIGH) |
00280 |
JSR $E456 |
|
00290 |
LDA #$0C |
; CLOSE IOCB #1 |
00300 |
LDX#$10 |
|
00310 |
STA $342,X |
|
00320 |
JSR $E456 |
|
00330 |
BRK |
; END OF PROGRAM |
00340 LAB |
.AS "E:" |
; DEVICE NAME |
00350 MES |
.AS "ATARI COMPUTERS ARE
GREAT" |
|
00360
|
.HS 9B |
; END OF LINE CHARACTER
|
Line 10 tells the computer which IOCB to close. Line
20 loads the accumulator with the number #$0C. This is the number
which tells the routine you want to close the IOCB. Line 30 stores the
number #$0C in location $342 offset by X.
Because X has the value of $10 in it the number will be stored in
$352. The reason we have to use the 'X' register is because the
computer uses the value in the 'X' register to decide which one to
close. Line 40 calls the operating system routine that actually
performs the close operation.
Now that the IOCB is closed you want to open it for
a device. When you do this you need to declare the device name, which
is best done by storing it in an ASCII string. The conventions I will
use are those used by the SYNASSEMBLER but there are conversions at
the end of this article for the ATARI ASSEMBLER-EDITOR. Listing 2 will
open an IOCB.
The program opens IOCB 1 for the screen editor (E:).
Lines 50, 60 and 70 tell the computer you want to open up IOCB 1. Line
80 is loading the accumulator with the low byte value address of the
label 'LAB'. For example, if the address of the label 'LAB' was $1234
then the low byte value of the address would be #$34. Line 90 stores
this value in a location where the computer can find it for later use.
Lines 100 and 110 do the same thing as the two previous lines except
they are loading and storing the high byte value of the address (e.g.
#$12). The reason for these four lines is so that when the computer
comes to perform the open it can look in locations $348 and $349 to
find the address where the name of the device is located (E: is the
name of the device). Lines 120 and 130 put a #$08 into #34A,X. The
contents of location #34A,X tell the computer which direction the data
will be travelling (i.e. to or from the device). In this case the 8
means we will be sending data. Lines 140 and 150 are just to be tidy
because the 0 in the location has no effect on this particular IOCB.
Line 160 calls the routine to do the open.
LOCATION |
USED FOR |
POSSIBLE VALUES |
RESULT |
$E456 |
Calls the routine to act on IOCB |
None |
Execution of IOCB |
$342 |
Sets the way the IOCB will be
used |
3 |
open the IOCB |
|
|
12 |
Close the lOCB |
|
|
7 |
Get binary record |
|
|
11 |
Put binary record |
|
|
4 |
Input string |
|
|
8 |
Output string |
$344
|
Low byte value of buffer address |
0 - 255 |
Tells the computer the low byte
address of where to get or put data |
$345 |
High byte value of buffer address |
0 - 255 |
Same as above only High
address byte |
$348 |
Low byte value of buffer length |
0 - 255 |
Sets the amount of data to be moved
(low byte) |
$349 |
High byte value of buffer length
|
0 - 255 |
Same as above only high
length byte |
$34A |
Sets the direction of data 4
transfer |
4 |
Read data |
|
|
8 |
Write data |
|
|
12 |
Read and Write data |
|
|
6 |
Open for directory |
$34B |
Used mainly for graphics |
0 - 255 |
See graphics table |
USING THE IOCB
Now that the IOCB is open you want to do something
with it In this case because we put a #$08 into $34A,X we want to send
data. To send data to the device we use the routine in Listing 1.
The routine will print the message on the screen.
Lines 170 to 190 are putting a #$08 into command location ($342). The
#$08 tells the computer to expect an undetermined amount of data. This
is like printing a string in BASIC, because you don't need to know how
long the string is to print it The computer will stop printing data
when it reaches a #$9 B. Lines 200 to 230 are instructing the computer
how much data to send. Because we have used a #$08 in $342,X the
number in these two locations only has to be more than we want to
send. If you are sending a known amount of data then these two
locations should contain this number. $344,X is the low byte and $345
is the high byte. Line 280 executes the operation.
If you are not familiar with the low byte, high byte
notation it simply means the storing of numbers greater than 255 in
two consecutive locations. Because the maximum value in one location
is 255 we have to store numbers greater than this in a special way.
The high byte location contains the number of 256's in the number and
the low byte location contains the number of 1's in the number. If you
wanted to store the number 1027 you would place a 4 in the high byte
(4*256=1024) and a 3 in the low byte (3* 1=3). The result is
1024+3=1027. The same principle is used when storing an address.
When you have finished writing the program you must
close the IOCB by using the first part again.
Now the best thing to do is to practice sending or
receiving data from other devices such as the printer. You can have
more than one device open at a time so that you can read data from a
disk using one IOCB and print it to the screen using another. Have
fun!
Some conversions
SYN-ASSEMBLER |
ATARI ASSEMBLER-EDITOR |
#LAB |
LAB&255 |
/LAB |
LAB/256 |
.AS "ATARI etc." |
.BYTE "ATARI etc" |
.HS 9B |
.BYTE #$9B |
With the Atari Editor you will need a *=$4000 at the
start of the program.
GRAPHICS TABLE:
The following program will open the screen for
graphics mode 2 and print a message.
00010 |
|
; GRAPHICS
MODE 2 PROGRAM |
00020 |
|
; |
00030 |
LDX #$10 |
; CLOSE
IOCB # 1 |
00040 |
LDA #$OC |
|
00050 |
STA $342,X |
|
00060 |
JSR $E456 |
|
00070 |
LDA "$03 |
; PEN IOCB
a1 |
00080 |
LDX #$10 |
|
00090 |
STA $342,X |
|
00100 |
LDA #SNAME |
; DEVICE
NAME (LOW) |
00110 |
STA $344.X |
|
00120 |
LDA/SNAME |
; DEVICE
NAME (HIGH) |
00130 |
STA $345,X |
|
00140 |
LDA #$18 |
; SPLIT
SCREEN + OUTPUT |
00150 |
STA $34A,X |
|
00160 |
LDA #$02 |
; GRAPHICS
MODE |
00170 |
STA $34B.X |
|
00180 |
JSR $E456 |
|
00190 |
LDA #$11 |
; PUT
BINARY RECORD |
00200 |
LDX #$10 |
|
00210 |
STA $342,X |
|
00220 |
LDA "$06 |
; AMOUNT
OF DATA TO SEND (LOW) |
00230 |
STA $348,X |
|
00240 |
LDA #$00 |
; AMOUNT
OF DATA TO SEND (HIGH) |
00250 |
STA $349,X |
|
00260 |
LDA # WORD; |
; LOW BYTE
ADDRESS OF MESSAGE |
00270 |
STA #344,X |
|
00280 |
LDA/ WORD |
; HIGH
BYTE ADDRESS OF MESSAGE |
00290 |
STA #345,X |
|
00300 |
JSR $E456 |
|
00310 |
BRK |
; END OF
PROGRAM |
00320SNAME |
.AS "S:" |
;
DEVICE NAME |
00330WORD |
AS "MODE 2"* |
|
When the graphics screen is opened the mode number
goes into location $34B,X. Location $34A,X contains details of the type
of screen you want i. e. split screen configuration. The diagram below
shows how to obtain the different types of screen.
128 |
64 |
32 |
16 |
8 |
4 |
2 |
1 |
|
|
C |
S |
W |
R |
|
|
If bit 'C' is set (i. e. equal to 1) then when the
screen is opened the current display will not be cleared.
If bit 'S' is set then the screen will be set up for
a split screen arrangement. This is the same as if you opened a screen
in BASIC without putting the '+16' on the end.
If bit 'W' is set then this instructs the screen to
expect data to be sent to it This is set when you want to do 'PLOTS'
and 'DRAWTOs'.
If bit 'R' is set then the screen will be set up so
that you can get data from the screen. This is used when you wish to
do a 'LOCATE' statement.
top