......................................................................... .; >>>>> 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!