........................................................................
; >>>>> Please put the title here <<<<<
laser
topmargin 1"
margin 1"
bottommargin 1"
hlt bold
; pick one of the fonts, and comment out or erase the one you don't want
;font helvetica
font times
point 9.4285
leading 1
symbol on
bl |
; The following rulers work for Times-Roman and Helvetica
; Three columns per page (2 1/16")
.................................<
AAA
by SDH
_Simple File I/O on a Random File_
Hello assembler junkies! This is
the second session of the AAA that
deals with file I/O. This month we
will discuss a simple program that
reads in a random file that was
just made via the _.CREATE_ command
and clears each block of the file.
This program is quite handy if you
want to make sure each block of
your (new) random file does not
contain any extraineous (sp?) data.
Before we look at the program for
this month, let's take a closer
look at the DDB and discover a new
feature of the DDB that has not
been covered. This feature involves
the D.WRK area of the DDB. This
area is where AMOS loads in the
following upon a LOOKUP: the _number
of blocks_ of the file (the word at
D.WRK+2), the _active bytes of the
last block_ (the word at D.WRK+6),
and the _first block number_ of the
file (the word at D.WRK+12). Time
for a closer look.
The first word at D.WRK+2
contains the number of blocks in
the file. We will use this number
as our counter when we clear each
block of our random file. The
second piece of data, the _active
bytes_, has two different formats
depending on if the file is
sequential or random. If it is a
sequential file, then this value
contains the "pointer" to the last
used byte in the last block of the
file, also known as the end-of-file
(eof). If it is a random file, then
this value will contain a -1,
represented as 177777 octal, FFFF
hex. Finally, the last word at
D.WRK+12 (octal) always contains
the first block of the file whether
it is random or sequential in type.
Notice that if you want to decide
whether or not a file is random or
not, all you need to do is examine
the word at D.WRK+6. If it is the
-1, then by golly, the file is
random. If it is not, then it must
be sequential. Notice that if the
file type is random, then we may
easily find out how many blocks the
file occupies by reading in the
word at D.WRK+2. Finally, to gain
access to the first block of any
file type, we simply read in the
word at D.WRK+12 (you may also
access the block number at D.REC+2
if you so desire).
One more note before we look at
the program. When reading and
writing to random files, the
procedure is as follows: read in a
block into memory, perform work on
the block, and then write this
block back out to disk in the same
location when the block was read.
_CLRAND Byte-by-Byte_
Let's examine a program called
CLRAND that will clear each block
of a random file. Many of the
instructions contained in this file
have been covered in earlier
sessions, so if you are a little
lost, please refer to the previous
AAA submissions for details.
_PHDR-1,0,PH$REE!PH$REU!PH$OPR_
Here is the same old program
header but with a new added twist.
Notice that there is a new flag
contained in the header - the
_PH$OPR_ flag. This will indicate to
AMOS that the user of this program
_must_ be logged into the OPR:
account before the program will
run, similar to the DSKANA, DSKDDT,
and other OPR: AMOS programs.
_.OFINI
.OFDEF IDDB,D.DDB
.OFSIZ IMPSIZ_
This is where we reserve space
for our Dataset Driver Block (DDB)
by defining a variable called IDDB
and giving this variable a size of
D.DDB. D.DDB is equal to 150 octal
bytes. It is these bytes that allow
space for all the information
necessary to perform file I/O. The
variable IDDB will exist in the
user memory partition of the user
executing CLRAND.
_BYP_
This monitor call will bypass all
"whitespace" on the input line.
Whitespace consists of all spaces
following the CLRAND command up to
the first non-blank character (a CR
or a LF is a non-blank character,
by the way). This has the effect of
incrementing the input line pointer
address register A2 to the first
non-blank character following the
program name.
_LIN_
_BNE INOK_
After passing by the whitespace,
we now check and see if we are at a
line termination character like a
CR or a LF. The LIN monitor call
will cause the zero flag of the
status register to be set if the
character pointed to by A2 is a
line termination character. The BNE
to the label INOK will happen only
if A2 does not point to a line
termination character.
_LEA A1,IDDB(A3)
FSPEC @A1
INIT @A1
LOOKUP @A1
BNE NOFILE_
LEA A1,IDDB(A3) will Load the
Effective Address into the address
register A1 the memory location
pointed to by IDDB(A3). A1 now
points to the DDB for the file.
FSPEC @A1,DAT will take the ascii
data pointed to by A2 (our input
pointer) and place the "filespec"
entered in by the user into the DDB
pointed to by A1 at the proper
offsets (D.FIL, D.EXT, etc. - see
last months submission). If the
user did not provide an extension,
the extension default is .DAT. If
the user enters in a faulty
filespec on the input line, FSPEC
will "catch" the error, report it
to your screen, and return you to
the dot.
INIT @A1 will cause AMOS to
locate a buffer space in user
memory (512 bytes) for block I/O.
The pointer to this block memory
buffer will be placed in the DDB at
the offset D.BUF. The actual size
(512 bytes in this case) is
calculated by AMOS upon an INIT
call by consultation of the device
driver.
After the INIT call, the LOOKUP
@A1 commands AMOS to see if the
file located in the DDB pointed to
by A1 exists. If it does exists,
then the zero flag of the status
register will be set, and the file
information at D.WRK will be moved
into the DDB pointed to by A1.
BNE NOFILE will only be executed if
the file does not exist.
_CMPW IDDB+D.WRK+6(A3), #-1
BEQ AOK_
If the file exists and there was
no file specification error
produced by the FSPEC call, the
next step of the program will
determine if the file entered at
the command line is indeed random.
It does this by examining the word
value at offset D.WRK+6. If it is a
-1, then the file is random, and
the program then branches to the
label AOK.
_TYPE <?>
PFILE @A1
TYPECR < is not a random file.>
EXIT_
If the file is not a random file,
then the program continues with the
lines contained above. First, a "?"
is printed to the screen, then the
PFILE monitor call is employed to
type out the filespec to the
terminal. The PFILE monitor call
expects a pointer to a file DDB
following the call. A1 is the
pointer in this case. We then
finish the message to the user with
the TYPECR <. . . >, and then
finally EXIT back to the dot.
_CRLF
JNE END_
This small portion of code is
self explainatory. These lines just
make sure that the user knows what
they are about to do. They must
confirm execution of the program by
entering in a "Y" before
continuing. Since this program will
wipe out any data contained in the
blocks on the file, CLRAND double
checks the user's intensions.
_MOVW IDDB+D.WRK+2(A3),D2_
Here is where we get the number
of blocks of the random file into a
counter register using D2 as our
counter. We will consult D2 and
clear each block until D2 is equal
to zero.
_OPENR @A1
READ @A1
MOV #128,D3_
Next, CLRAND will open the file
for random input/output with the
OPENR monitor call. The address
following the OPENR command should
be a pointer to a random file DDB.
Once the file has been opened,
the READ @A1 will read in a block
from the file. The block number
actually read is contained in the
DDB at an offset of D.REC+2. The
data contained on the disk block is
placed into your user memory at the
address contained in D.BUF.
After the block has been read in,
we place another counter into the
data register D3. This counter is
#128. Since CLRAND will be clearing
the block, and each block contains
128 longwords, D3 acts as a
longword counter.
_MOV IDDB+D.BUF(A3),A4_
This instruction will move the
block pointer that the INIT call
created into the address register
A4. A4 now points to the first byte
of the block just read in from the
READ call.
_CLR (A4)+
DEC D3
BNE 10$_
This is where the actual block
clearing occurs. For each longword
(totaling 128), the CLR (A4)+ will
not only clear the longword pointed
to by A4, but the "+" after the
instruction will cause A4 to point
to the next longword in memory.
After 128 passes of this procedure,
D3 will be zero, and the program
falls through to the next
set instruction below.
_WRITE @A1
DECW D2
BEQ END_
After the block has been cleared
in memory, CLRAND then writes this
block back out to the disk with the
WRITE monitor call. Notice that A1
is again employed as our pointer to
the DDB of the file we are
manipulating. The block modified in
memory is written back out to the
disk in the exact location before
the modification.
DEC D2 will cause our block
counter data register to be one
less than before, and if D2
contains a zero, the program
branches to the label END.
_INCW IDDB+D.REC+2(A3)
BR READIT_
If the data register D2 is not
zero, this means that all the
blocks have not been cleared. The
program must then increment the
block number by one by incrementing
the word value (the actual block
number) at D.REC+2. Since random
files occupy contiguous disk
blocks, this has the effect of
pointing to the next block of the
random file. Once this has been
done, the program branches back to
the READIT label, which causes
CLRAND to read in the next block of
the file and proceed to clear this
block.
_EXIT
END_
Once all blocks have been
cleared, we then EXIT back to the
dot. Upon exit, notice that the
file is automatically closed. END
marks the end of the code to the
assembler program.
_A Wrap_
I know this is a lot of
instructions and theory piled on
you all at once. We will be
continuing our discussion of simple
file I/O - both random and
sequential - in the months to come.
Try this program out (it is located
on the Network in [100,51]). See
if you can follow the theory.
Remember, however, that this
program will clear out a random
file.
Don't practice this program on
any file you need! If you like,
create a new random file with the
_.CREATE_ command. For example, to
create a 2-block random file called
TEST.DAT, the format is _.CREATE_
_TEST.DAT,2_. _.DUMP_ the file after
you have created it and notice the
data contained in the file. There
is a good possibility that there is
some garbage. Now _.CLRAND TEST.DAT_
from the OPR: account and then
_.DUMP_ the file once again. Notice
that all the blocks of the file now
contain zeros. Just what "Doctor
Dave" ordered! Have fun, be
careful, and I'll see you next
month!