IBM Mainframe Forum Index
Log In
IBM Mainframe Forum Index Mainframe: Search IBM Mainframe Forum: FAQ Register

Assembly Program - reading and writing using BSAM

IBM Mainframe Forums -> PL/I & Assembler
Post new topic   Reply to topic
View previous topic :: View next topic  
Author Message
Apurva Mehta

New User

Joined: 12 Nov 2014
Posts: 4
Location: USA

PostPosted: Wed Nov 12, 2014 9:37 pm
Reply with quote


I'm trying to write an Assembly Language program for reading and writing a sequential file, using Basic Sequential Access Method (BSAM).

My input file has the following attributes:
Record Length = 80 Bytes
Block Size = 4560 Bytes
Record Format = FB
File Organisation = PS

No. of Records in the Input File = 10,000.

Now, I'm using the below program to read from the input file and write to the output file.
BSAMFIL  START                       
         STM   R14,R12,12(R13)       
         LR    R12,R15               
         USING BSAMFIL,R12           
         LA    R14,SAVEAREA         
         ST    R13,4(R14)           
         ST    R14,8(R13)           
         LR    R13,R14               
         OPEN  (INPUTF,INPUT)       
         OPEN  (OUTPUTF,OUTPUT)     
         CHECK DECB1                 
         CHECK DECB2                 
         B     LOOP                 
         CLOSE INPUTF               
         CLOSE OUTPUTF               
         L     R13,4(R13)                                               
         LM    R14,R12,12(R13)                                         
         SR    R15,R15                                                 
         BR    R14                                                     
INPUTF   DCB   DDNAME=INPUTFL,                                        X
               MACRF=(R),                                                          X
               DSORG=PS,                                                          X
               LRECL=80,                                                            X
               BLKSIZE=4560,                                                     X
               RECFM=FB,                                                           X
               EODAD=NOMORE,                                                 X
OUTPUTF  DCB   DDNAME=OUTPUTFL,                                   X
               MACRF=(W),                                                        X
               DSORG=PS,                                                          X
               LRECL=80,                                                           X
               BLKSIZE=4560,                                                    X



My problem is that the OUTPUT file contains 10,032 records in stead of 10,000 records.

I calculated the following:
In one read, i'm reading 4560 Bytes
-> since one record is of 80 Bytes, in one read I'm reading 57 records
-> in 175 Reads, i'm reading 9,975 records.
-> in the 176th read, there are only 25 records remaining in the file to read. However, I'm not re-initialized CARD, which is why, it already contains 57 records and only 25 of these records are re-written.

But during the write process, all 57 records are written to the file again and hence, i have 9,975 + 57 = 10,032 records in my output file, with a repetition of the 32 records.

I do not understand how to resolve this issue, in general.
I can make changes in this particular case - but the no. of records may vary from file to file.

Can someone help me, in resolving this issue.
Even if someone can tell me, where to find the no. of bytes that were read, after the READ statement - it would help me tremendously.

Thank You.

Back to top
View user's profile Send private message

Active Member

Joined: 30 Nov 2013
Posts: 888
Location: The Universe

PostPosted: Thu Nov 13, 2014 2:07 am
Reply with quote

You're pretty close. Where you went wrong is you have to compute, after every input I/O, the actual number of bytes you read. This computation depends on a couple of obscure data areas: the IOB (Input/Output Block) and a data area in the IOB, IOBCSW. The CSW (Channel Status Word) is a System/360 data area; it represents data left behind by an I/O interrupt. The BSAM I/O driver constructs a CSW from equivalent data in z/OS. We are only interested in the last two bytes of the CSW, the residual byte count. This is just fancy talk for the number of bytes that were not read in the I/O operation. In other words, if you tried to read 160 bytes, and you only read 80 bytes, the residual byte count will be 80. 160-80 is the actual number of bytes you read. Now here's the complete working (and tested) program.
         USING *,12
         SAVE  (14,12),,*
         LR    12,15
         LA    15,SAVEAREA
         ST    13,4(,15)
         ST    15,8(,13)
         LR    13,15
         OPEN  (IDCB,INPUT)
         OPEN  (ODCB,OUTPUT)
         GETBUF IDCB,(2)
         ST    2,(DECAREA-DECB)+IDECB
         ST    2,(DECAREA-DECB)+ODECB
         CHECK IDECB
         L     15,(DECIOBPT-DECB)+IDECB
         LH    0,14(,15)
         SR    1,0
         WRITE ODECB,SF,ODCB,*-*,'S'
         CHECK ODECB
         B     LOOP
         L     13,4(,13)
         RETURN (14,12),T,RC=0
         PUSH  PRINT
         PRINT NOGEN
         POP   PRINT
         END   BSAMRW
There are several differences between my program and your program.
  • My program copies the RECFM, LRECL, and BLKSIZE DCB attributes from the input DCB to the output DCB. My program does not depend on known DCB attributes.
  • My program directs OPEN to allocate a buffer pool for the input DCB, and it uses the GETBUF macro to obtain an I/O buffer from the buffer pool and stores the buffer address in the DECBs. This way I do not have to supply an I/O buffer in the program.
  • It computes the number of bytes read after every READ/CHECK. Not every data block has to be a full data block, and, as you have already discovered, the last data block is seldom full.
  • It frees the buffer pool after the CLOSE macro. CLOSE does not free the buffer pool for reasons I won't try to list here; you have to do it.
This is the code to compute the actual bytes read.

         L     15,(DECIOBPT-DECB)+IDECB
         LH    0,14(,15)
         SR    1,0

First, the program loads the input BLKSIZE from the DCB. Next, it loads the address of the IOB from the DECB. This is not a "real" IOB; BSAM no longer uses them. BSAM just constructs parts of a fake IOB so programs, like this one, written for OS/360 will still work. The program loads the residual byte count from the fake CSW in the fake IOB, and subtracts the real residual byte count from the real BLKSIZE. Finally, it updates DCBBLKSI in the output DCB so the WRITE macro can write the correct number of bytes.

Two other notes.
  • The IHADECB macro is in SYS1.MODGEN, not SYS1.MACLIB, where, in my opinion, it should be.
  • IOBCSW is at offset 8 in the IOB, and the residual byte count is at offset 6 in the CSW. The 14 used in the LH 0,14(,15) instruction is just 8 + 6.
Back to top
View user's profile Send private message
Apurva Mehta

New User

Joined: 12 Nov 2014
Posts: 4
Location: USA

PostPosted: Mon Nov 17, 2014 9:58 pm
Reply with quote

Thanks a lot Steve. I modified my program and it worked perfectly.

I still have some questions on the method, but i would do my research before reaching out to you.

Thank again. :-)
Back to top
View user's profile Send private message
View previous topic :: :: View next topic  
Post new topic   Reply to topic View Bookmarks
All times are GMT + 6 Hours
Forum Index -> PL/I & Assembler


Similar Topics
Topic Forum Replies
No new posts Program level statistics CICS 6
No new posts Parameter description for Beta92 prog... Compuware & Other Tools 1
No new posts Reading subsequent rows in a query. DB2 12
No new posts How to Parameterize Eazytrive program All Other Mainframe Topics 2
No new posts linking an ALC program to a Relationa... PL/I & Assembler 1
Search our Forums:

Back to Top