Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

CRC in COBOL 5

Status
Not open for further replies.

FireStarter1

Programmer
Jun 6, 2003
40
US
Hi,
I am doing project that needs CRC calcualation, it is currently done with a C program that runs on Windows platform, I want to do the same on mainframe in cobol. Can anyone please help to convert the following C program.

typedef unsigned char Byte; /* Byte as unsigned char */
typedef unsigned short Word; /* Word as unsigned short */

Word wBuildCrc (Byte *pbBuf, unsigned wLen, Word wCrc)
{
Byte bCh;
Word j;
char i;


bCh=(Byte)(wCrc & 0x00FF);
wCrc=(wCrc>>8) + (unsigned short)bCh*0x100; /* " */


for (j = 0; j < wLen; j ++)
{
bCh = pbBuf[j];
wCrc=wCrc ^ ((unsigned short) bCh <<8);
for (i=0; i<8; i++)
{
if (wCrc & 0x8000)
wCrc = (wCrc << 1) ^ 0x1021;
else
wCrc = wCrc << 1;
}
}

bCh=(Byte)(wCrc & 0x00FF);
wCrc=(wCrc>>8) + (unsigned short)bCh*0x100; /* &quot; */

return(wCrc);
}


Word cdecl uiBuildCrc (Byte *pbBuf, unsigned wLen, Word wCrc)
{
return(wBuildCrc (pbBuf,wLen,wCrc));
}
 
Here is a working program that implements CRC-32. (Note that FireStarter was attempting to implement the far-less-often-used CRC-CCITT which is used on X.25 and SDLC.) There are two very long copybooks that initialize tables that contain fixed values. Copybooks are available from me at t.morrison -- find my domain name in my profile. Please refer to an excellent document that I used
which links to:
especially Chapter 17 that shows weak confirmation of the algorithm implementation (checking the message &quot;123456789&quot;). I also acknowledge the use of the CRC table from the Perl example found at:
which was very useful.
Code:
       identification division.
       program-id.  crc32.
       data division.
       working-storage section.

       01  message-buffer.
           02 pic x(9) value &quot;123456789&quot;.
       01  msg-length          pic 9(9) binary.
       01  i                   pic 9(9) binary.
       01  j                   pic 9(9) binary.
       01  k                   pic 9(9) binary.
       01  hex-display         pic x(16) value &quot;0123456789ABCDEF&quot;.

       01  crc32-accum.
           02  crc32-octet     pic x occurs 4
                               indexed by crc32-ix.

       01  xor32-a.
           02  xor-a-octet     pic x occurs 4
                               indexed by xora-ix.

       01  xor32-b.
           02  xor-b-octet     pic x occurs 4
                               indexed by xor6-ix.
       01  xor-ord-a           pic 9(4) binary.
       01  redefines xor-ord-a.
           02                  pic x.
           02 xor-octet-a      pic x.
       01  xor-ord-b           pic 9(4) binary.
       01  redefines xor-ord-b.
           02                  pic x.
           02 xor-octet-b      pic x.

       01  temp-c              pic x.    

       01  xor-table.
           copy &quot;xortable.cpy&quot;.
       01  redefines xor-table.
           02  occurs 256.  03  xor-result pic x occurs 256.

       01  crc32-table.
           copy &quot;crc32tab.cpy&quot;.
       01  redefines crc32-table.
           02  crc32-value         pic x(4) occurs 256.            

       procedure division.
       a.
           move X&quot;FFFFFFFF&quot; to crc32-accum. 
           move length of message-buffer to msg-length.
           perform varying i from 1 by 1 until i > msg-length
               move 0 to xor-ord-a, xor-ord-b
               move crc32-octet (4) to xor-octet-a
               move message-buffer (i:1) to xor-octet-b
               add 1 to xor-ord-a
               add 1 to xor-ord-b
               move xor-result (xor-ord-a, xor-ord-b) to temp-c
               move 0 to xor-ord-a
               move temp-c to xor-octet-a
               add 1 to xor-ord-a
               move crc32-value (xor-ord-a) to xor32-a
               move x&quot;00&quot; to xor-b-octet (1)
               move crc32-accum (1:3) to xor32-b (2:3)
               perform xor-4-octets
               move xor32-b to crc32-accum
           end-perform.
           move crc32-accum to xor32-a.
           move X&quot;FFFFFFFF&quot; to xor32-b.
           perform xor-4-octets.
           move xor32-b to crc32-accum.
           perform display-crc32.          
           stop run.

       xor-4-octets.
           perform varying j from 1 by 1 until j > 4
               move 0 to xor-ord-a, xor-ord-b
               move xor-a-octet (j) to xor-octet-a
               move xor-b-octet (j) to xor-octet-b
               add 1 to xor-ord-a
               add 1 to xor-ord-b
               move xor-result (xor-ord-a, xor-ord-b)
                 to xor-b-octet (j)
           end-perform.

       display-crc32.
           display &quot; CRC32 = &quot;.
           perform varying i from 1 by 1 until i > 4
               move 0 to xor-ord-a
               move crc32-octet (i) to xor-octet-a
               divide 16 into  xor-ord-a giving j remainder k
               add 1 to j
               add 1 to k
               display hex-display (j:1) position 0
                       hex-display (k:1) position 0
           end-perform.

The output is:
Code:
RM/COBOL Runtime - Version 8.00.00 for 32-Bit Windows.
Copyright (c) 1985-2003 by Liant Software Corp.  All rights reserved.

 CRC32 = CBF43926

COBOL STOP RUN at line 4424 in program CRC32 (C:\Temp\crc32\CRC32.COB).


Tom Morrison
 
Hi,
The program given above is working well. My requirement is for CRC-16-CCITT.
Tom I tried the program you gave me on the mainframe and it is not calculating the CRC right. I tried all I can but I don't know what is going wrong with the calculation. Can you please help me fix this problem.
Thanks.
 
I also received an email from FireStarter about this. In my response I cited the fact that, unlike CRC-32, CRC-CCITT has some controversy in the 'internet literature'. I have been unable to find a citation anywhere that would be considered definitive. There is some personal irony in this since some decades ago I was a member of ANSI X3S34 which was charged with standardizing link level protocols, namely ADCCP (which is closely related to HDLC and X.25). These protocols all used CRC-CCITT which I, for my entire service on the ANSI task group, presumed was well-defined. Truly a case of line and learn, I guess.

So, what I suggested to ol' FireStarter is that we get a message or two and see what the C program computes for the 'CRC' and emulate that.

Tom Morrison
 
In my free time I do write poetry. But this is a time in which I can't find enough words to Thank Tom Morrison. He helped me to finish my project, he wrote the whole program by himself. He did not just finish this project he actually saved my career. Thanks a lot Tom.
Here is the actual program that eventually worked.
************************************************************
identification division.
program-id. crcshift.
data division.
working-storage section.

01 message-buffer.
02 pic x(16) value X&quot;03703030303030303030303030303030&quot;.
02 pic x(16) value X&quot;30303032303030303030303030303030&quot;.
02 pic x(16) value X&quot;30303030303030303030303030303030&quot;.
02 pic x(16) value X&quot;30303030303030303030303030303030&quot;.
02 pic x(16) value X&quot;3030303030303030413130323230324A&quot;.
02 pic x(16) value X&quot;5257454C49525250454E544F4E594331&quot;.
02 pic x(14) value X&quot;3131310000000000000000000000&quot;.

01 another-msg.
02 pic x(9) value &quot;123456789&quot;.
01 msg-length pic 9(9) binary.
01 i pic 9(9) binary.
01 j pic 9(9) binary.
01 k pic 9(9) binary.
01 hex-display pic x(16) value &quot;0123456789ABCDEF&quot;.

01 crc-accum-big pic 9(9) binary.
01 redefines crc-accum-big.
02 crc-top pic 9(4) binary.
02 crcshift-accum pic 9(4) binary.
02 crcshift-accum-group redefines crcshift-accum.
88 crc-accum-high-bit values x&quot;8000&quot; thru x&quot;ffff&quot;.
03 crcshift-octet pic x occurs 2.

01 xorshift-a.
02 xor-a-octet pic x occurs 2.

01 xorshift-b.
02 xor-b-octet pic x occurs 2.
01 xor-ord-a pic 9(4) binary.
01 redefines xor-ord-a.
02 pic x.
02 xor-octet-a pic x.
01 xor-ord-b pic 9(4) binary.
01 redefines xor-ord-b.
02 pic x.
02 xor-octet-b pic x.

01 temp-c pic x.

01 xor-table.
copy &quot;xortable.cpy&quot;.
01 redefines xor-table.
02 occurs 256. 03 xor-result pic x occurs 256.


procedure division.
a.
move X&quot;FFFF&quot; to crcshift-accum-group.
move crcshift-octet (1) to temp-c.
move crcshift-octet (2) to crcshift-octet (1).
move temp-c to crcshift-octet (2).
move length of message-buffer to msg-length.
perform varying i from 1 by 1 until i > msg-length
move crcshift-accum-group to xorshift-a
move message-buffer (i:1) to xor-b-octet (1)
move X&quot;00&quot; to xor-b-octet (2)
perform xor-2-octets
move xorshift-b to crcshift-accum-group

perform varying j from 1 by 1 until j > 8
move 0 to crc-top
add crc-accum-big to crc-accum-big
if crc-top not = 0
move crcshift-accum-group to xorshift-a
move x&quot;1021&quot; to xorshift-b
perform xor-2-octets
move xorshift-b to crcshift-accum-group
end-if
end-perform
end-perform.
move crcshift-octet (1) to temp-c.
move crcshift-octet (2) to crcshift-octet (1).
move temp-c to crcshift-octet (2).
perform display-crcshift.
stop run.

xor-2-octets.
perform varying k from 1 by 1 until k > 2
move 0 to xor-ord-a, xor-ord-b
move xor-a-octet (k) to xor-octet-a
move xor-b-octet (k) to xor-octet-b
add 1 to xor-ord-a
add 1 to xor-ord-b
move xor-result (xor-ord-a, xor-ord-b)
to xor-b-octet (k)
end-perform.

display-crcshift.
display &quot; CRC-shift = &quot;.
perform varying i from 1 by 1 until i > 2
move 0 to xor-ord-a
move crcshift-octet (i) to xor-octet-a
divide 16 into xor-ord-a giving j remainder k
add 1 to j
add 1 to k
display hex-display (j:1) position 0
hex-display (k:1) position 0
end-perform.
************************************************************
I think everyone should understand this fact that in my knowledge no one had ever attempted CRC calculation in COBOL. So this is the time to celebrate a great event in the history of COBOL.
Thanks for the all the others who contributed their opinions and suggestions which kept me and Tom going on and on with optimism.
As Tom said in one of his email to me that this topic deserves a good conclusion, I am really honoured to be part of it.
Thank You.
 
I will add my own notes to help conclude this thread.

The program that FireStarter has shown above implements the C program he showed earlier in the thread. It is important to understand that, at least in my opinion, this program is not a correct implementation of CRC-CCITT. As I stated earlier, there is some controversy about the correctness of several implementations of CRC-CCITT on the net, and this implementation (both C and COBOL) takes one of the controversial implementations and further compounds the possible error by introducing a finishing byte swap.

The CRC-32 implementation I exhibited earlier in the thread does seem correctly to implement CRC-32, and it uses the faster &quot;table lookup&quot; method of treating an entire byte (octet) of the message at one time. (Again, the tables for this algorithm are available from me. See my profile for email information. We might also post it on our web site.)

The pseudo-CRC-CCITT implementation illustrates the &quot;bit at a time&quot; approach which results in a simpler to code, but slower running, result.

I might also state that I cannot imagine this type of thread happening in the comp.lang.cobol newsgroup. This has been a month-log exercise with a successful conclusion for the original poster. Imagine the detritus that this thread would have attracted in the newsgroup!

Tom Morrison
 
Hi Tom,
I agree that there is a lot of controversy over the right CRC calculation. But I've had no other option but to do exactly what the C code is doing. I will be a very nice Idea to post the tables and the program in your website as that will help people to learn more about these sort of programming with cobol. Many people don't believe that this can be done in cobol. To and extent I myself was a skeptic. But it is you and your patience that helped me believe that it is possible to do it. Thanks a lot for that.
 
Hi Everybody

Tom has done a great job. I always found him helping everybody and more imporatantly providing soulutions on tough problems which go thru many iterations and he patiently keep on advising until the job get done.

Thanks TOM for all this value addition u r doing to this forum and you deserve a special star for this !!!

Keep it up

Devesh
 
Hi Tom,
Thanks a lot for adding the code in your company site. This is really helpful for anyone who want it.
I am kinda in long vacation. I mean out of job, but having fun playing around with couple of application which I am working on personally.
Thanks again.
 
Note to mainframe (EBCDIC) users. Change the message from:
Code:
01  message-buffer.
    02 pic x(9) value "123456789".
to
Code:
01  message-buffer.
    02 pic x(9) 
       value x"313233343536373839".

Tom Morrison
 
Could someone clarify? I was going through this thread and have some interest in it, since getting things like this going in COBOL is an interest of mine. Is this CRC-16 or CRC-32?
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top