Page 2 of 3

Re: about Accept statement accept number

PostPosted: Wed Mar 30, 2011 1:19 pm
by Pumpkin
thanks for your help. and i do some tests about them.
first---------------------
num1 pic s9(5)
num2 pic s9(5)
---------------------
if i accept both num1 and num2 as 25, it will be S0C7, i think it because that it actually is F2F5404040,when computing ,it converts to 250004,if it is unsigned, it will be 25000F, so unsigned works, but signed needs last byte to be a number. for example:input 00025 and 00026, the result is 0005A( A for hex C1); input 00025 and 00025, the result is 0005:(: for C0 ? , i am not sure). and i also found ,if input "-" which hex is 60, it works like space.

second----------------------
num1 x(5) value "25"
num2 9(5)
num3 s9(5)
total-num2-num3 s9(5)
---------------------------------
move num1 to num2 num3
display num2 : 25<space><space>0
display num3: 25<space><space>:
add 1 to num2 : 25001
add 1 to num3: 2500A
compute num2+num3: 5000:
so ,it seems unlike accept statement, move statement works similar about signed and unsigned number.

and about your question "If you want a little exercise, try to work out how to make your existing program, unchanged, un-recompiled, get an S0C7 and tell us why."
i try some number ,it all works ,can you give some hints? thanks !

Re: about Accept statement accept number

PostPosted: Wed Mar 30, 2011 1:48 pm
by BillyBoyo
Pumpkin wrote:thanks for your help. and i do some tests about them.
first---------------------
num1 pic s9(5)
num2 pic s9(5)
---------------------
if i accept both num1 and num2 as 25, it will be S0C7, i think it because that it actually is F2F5404040,when computing ,it converts to 250004,if it is unsigned, it will be 25000F, so unsigned works, but signed needs last byte to be a number.


Yes, doing well. When you say last byte a number, the last byte (rightmost) has to be first half-byte valid sign, second half-byte number.

Pumpkin wrote:for example:input 00025 and 00026, the result is 0005A( A for hex C1); input 00025 and 00025, the result is 0005:(: for C0 ? , i am not sure). and i also found ,if input "-" which hex is 60, it works like space


Yes, if you use any editor which allows you to see the hex value when you have something "weird", you will see the C1 and C0. Good find with the "-". Yep, works like a space. The first part (the "zone") is irrelevent except in the sign byte, the second half-byte has to be numeric. So, with the last question, I can't give any more clues without answering it myself :-)

Pumpkin wrote:second----------------------
num1 x(5) value "25"
num2 9(5)
num3 s9(5)
total-num2-num3 s9(5)
---------------------------------
move num1 to num2 num3
display num2 : 25<space><space>0
display num3: 25<space><space>:
add 1 to num2 : 25001
add 1 to num3: 2500A
compute num2+num3: 5000:
so ,it seems unlike accept statement, move statement works similar about signed and unsigned number.


Again good. Now, in the future, when you see a field which has a value something like your display of num2/num3 you will know straight away how it got like that.

Pumpkin wrote:add 1 to num3: 2500A


This and your last statement confuse me. It is obviously like that, but I wouldn't expect it. I would have expected S0C7. Can you post your compile options? Perhaps Robert, who is much more up-to-date on these things than I am, can help explain.
Or, you can compile again with the generated assmembler and post the bits for the ACCEPT and the MOVE. Maybe the compiler re-uses its own item when you do the MOVE to a multiple recipient fields?

Re: about Accept statement accept number

PostPosted: Wed Mar 30, 2011 3:01 pm
by Robert Sample
       77  NUM1                        PIC X(05) VALUE '25'.
       77  NUM2                        PIC 9(05).
       77  NUM3                        PIC S9(05).
       PROCEDURE DIVISION                  .
       PARA-1.
           DISPLAY 'NUM1 <' NUM1 '>'.
           MOVE NUM1                   TO  NUM2
                                           NUM3.
           DISPLAY 'NUM2 <' NUM2 '>'.
           DISPLAY 'NUM3 <' NUM3 '>'.
           DISPLAY ' '.
           ADD 1                       TO  NUM2.
           ADD 1                       TO  NUM3.
           DISPLAY 'NUM2 <' NUM2 '>'.
           DISPLAY 'NUM3 <' NUM3 '>'.
produces pseudo assembler of
 000021  MOVE
    0003C0  D204 8008 8000          MVC   8(5,8),0(8)             NUM2
    0003C6  96F0 800C               OI    12(8),X'F0'             NUM2+4
    0003CA  D204 8010 8000          MVC   16(5,8),0(8)            NUM3
    0003D0  96F0 8014               OI    20(8),X'F0'             NUM3+4
    0003D4  94CF 8014               NI    20(8),X'CF'             NUM3+4

 000026  ADD
    0003F6  F224 D0F0 8008          PACK  240(3,13),8(5,8)        TS2=0
    0003FC  960F D0F2               OI    242(13),X'0F'           TS2=2
    000400  FA20 D0F0 A046          AP    240(3,13),70(1,10)      TS2=0
    000406  F342 8008 D0F0          UNPK  8(5,8),240(3,13)        NUM2
    00040C  96F0 800C               OI    12(8),X'F0'             NUM2+4
 000027  ADD
    000410  F224 D0F0 8010          PACK  240(3,13),16(5,8)       TS2=0
    000416  FA20 D0F0 A046          AP    240(3,13),70(1,10)      TS2=0
    00041C  F822 D0F0 D0F0          ZAP   240(3,13),240(3,13)     TS2=0
    000422  F342 8010 D0F0          UNPK  16(5,8),240(3,13)       NUM3
so after the move COBOL generates the code to force the NUM3 variable to have a positive sign (X'C?'). No S0C7 since the entire value is valid when packed. Output is
 NUM1 <25   >
 NUM2 <25  0>
 NUM3 <25  {>

 NUM2 <25001>
 NUM3 <2500A>

Re: about Accept statement accept number

PostPosted: Wed Mar 30, 2011 3:56 pm
by BillyBoyo
Robert Sample wrote:so after the move COBOL generates the code to force the NUM3 variable to have a positive sign (X'C?'). No S0C7 since the entire value is valid when packed.


Thanks Robert.

What I don't get is that this is not the "normal" behaviour - at least not as I was used to it. We know from before that some of the compile options affecting this have changed (from our NOTRUNC/TRUNC(OPT) discussion).

What it (Cobol compiler) used to do was to leave signed fields alone, but always generate code (except for when NOTRUNC) to keep unsigned fields unsigned. It would do this when a field's value gets changed. So, after a MOVE, for instance. Or a calculation of any sort.

What I don't, yet, understand is what seems to be (from Pumpkin's data) that it is 1) ensuring a positive sign if no valid sign for a signed number - I've never heard of that and 2) "correcting" (in the case of the ACCEPT, but I therefore assume all the time) before doing the COMPUTE - also never heard of that. Makes me suspect a compile option, because otherwise there was a huge loss of "backwards compatability" at some point. Which I seem to remember in the 80's some group of US users (like Chrysler, GM, GE etc) promising they would never let IBM do - and the somewhat hamstrung COBOL II was the result.

I'm only able to grab a couple of minutes now-and-then today, until maybe very late, but I'll get the little.... thing... from what Robert has posted and from the online Cobol manuals.

Re: about Accept statement accept number

PostPosted: Wed Mar 30, 2011 5:08 pm
by Robert Sample
I suspect the NUMPROC(NOPFD) compiler option is where the change came from. This is the option used for my code, and it tells COBOL to make no assumptions about the sign bits. Hence the MOVE to an unsigned numeric variable gets the sign bits set to F (unsigned) no matter what they were, while the MOVE to a signed numeric variable (from an alphanumeric, or unsigned, variable) forces the sign bits to F and then to C (positive). The behavior BillyBoyo is describing would be expected with NUMPROC(PFD), where COBOL assumes the sign bits are already correct and leaves them as is. NUMPROC goes back at least to VS COBOL II, so it's been around for quite a while. The compiler default is NOPFD, with options of PFD or MIG (for migration of OS/VS COBOL programs to Enterprise COBOL).

Re: about Accept statement accept number

PostPosted: Wed Mar 30, 2011 5:53 pm
by BillyBoyo
Thanks, I think you're right Robert. Just got there myself. Didn't take long, looked in the "Tuning" publication.

"NUMPROC - NOPFD, MIG, or PFD
Using the NUMPROC(PFD) compiler option generates significantly more efficient code for numeric
comparisons. It also avoids the generation of extra code that NUMPROC(NOPFD) or NUMPROC(MIG)
generates for most references to COMP-3 (PACKED-DECIMAL) and DISPLAY numeric data items to
ensure a correct sign is being used. With NUMPROC(NOPFD), sign fix-up processing is done for all
references to these numeric data items. With NUMPROC(MIG), sign fix-up processing is done only for
receiving fields (and not for sending fields) of arithmetic and MOVE statements. With NUMPROC(PFD),
the compiler assumes that the data has the correct sign and bypasses this sign fix-up processing.
NUMPROC(MIG) generates code that is similar to that of OS/VS COBOL. Using NUMPROC(NOPFD)
or NUMPROC(MIG) may also inhibit some other types of optimization. However, not all external data
files contain the proper sign for COMP-3 or DISPLAY signed numeric data, and hence, using
NUMPROC(PFD) may not be applicable for all application programs. For performance sensitive
applications, NUMPROC(PFD) is recommended when possible

| On the average, NUMPROC(PFD) was 1% faster than NUMPROC(NOPFD), with a range of 21%
| faster to equivalent.
| On the average, NUMPROC(PFD) was 1% faster than NUMPROC(MIG), with a range of 5% faster
| to equivalent.
| On the average, NUMPROC(MIG) was equivalent to NUMPROC(NOPFD), with a range of 17%
| faster to equivalent.
| (COB PG: pp 55-57, 333-334, 673)"

In the compilers I used such things were part of NOTRUNC (non-Standard Truncation), bizarrely, because it is not really to do with truncation. "sign fix-up" was only done for unsigned fields if you used Standard Truncation (TRUNC).

I think these days I would prefer PFD. As can be seen from Pumkin's examples, some funny things can happen. For me a dump is preferable to an unknown multiplication by 1000, or whatever :-)

Re: about Accept statement accept number

PostPosted: Thu Mar 31, 2011 3:50 am
by BillyBoyo
So, Pumpkin. Robert and I predict that you have the compile option NUMPROC(NOPFD). What this is doing is "fixing" your signs on any numeric fields, signed or not, every time you make a reference to them, and not just when they receive data.

Can we still make it S0C7 without a re-compile? Yes, that still stands. That is another hint. The "sign fixing" will not save the program.

It will help if you can look at EBCDIC codes for characters on your keyboard.

There is more than one character that will cause the abend. Think about what you already found out with the "-", but don't think like that one.

Now, another way to make your program S0C7 is to re-compile it with NUMPROC(PFD). Then run your original test. It will fail. You can also try compiling with NUMPROC(MIG). It will fail.

If you use your other example program, using the alpha-numeric "25" & "26", it will fail if compiled with NUMPROC(PFD) and "work" with NUMPROC(MIG).

So, we have learned three lessons from your ACCEPT example. One not very important, one standard, and the other with potentially far-reaching consequences.

The first, and not very important, is that ACCEPT will put a value into a numeric display item, but will treat it as alphanumeric while doing it. Since you are not too likely ever to use ACCEPT in a real situation on a mainframe, the most you can get out of this is that if ACCEPT is like that, something else might also be like that. When using something you haven't used before, it is good to check it out, even if you see it for the first time in a piece of "working" code.

The second, the standard one, is always validate human-entered data. I'd add, always validate any data as it enters your system, even from another computer system. It's your data, you'll have plenty of opportunities to mess it up yourself, don't let others do it for you.

The third thing is this. The NUMPROC compile option. Ideally, the correct default value for your site has been selected when the Cobol package was installed.

The value for the NUMPROC that you use should be the same as is used for all the members of the team you are working with. It should be the same for your team across all testing environments. And it should be the same for your team in production. If there is any mix of this among team members/environments/production it is just asking for trouble.

What is the correct value for NUMPROC? Well, it depends. I wouldn't go as far as to say that I know the "correct" for all circumstances, but, for me: for sites previously using Standard Truncation, I'd say MIG; For sites using Non-Standard Truncation, I'd say PFD; For sites not previously usings anything, I'd say PFD. NOPFD basically scares the hell out of me.

OK. I can calm myself down a bit, because of the second thing above. Always validate data coming in. If you do that, then NOPFD doesn't matter so much. Still can't make myself like it, but then I never liked Standard Truncation.

Re: about Accept statement accept number

PostPosted: Thu Mar 31, 2011 1:15 pm
by BillyBoyo
In doing the internal arithmetic, COBOL converts the space (hex '40') to a zero (hex 'F0') and that's why your 25 became 25000.


Now that we have the compile option under control we can get back to this.

The two 25's looked list this to start with, in hex, F2F5404040. Cobol, beacause of NUMPROC(NOPFD), clobbered... sorry "fixed" the sign part of the byte, changing it to F. So, F2F54040F0, in a Cobol storage area within the program. It will then use the CVP instruction to, as the instruction says, convert it to a packed field. The instruction will do this by stripping out the zones, keeping the number parts, keeping the sign but "swapping" its position so that it is the rightmost half-byte. This is my English description of the effect, not a technical or terminological one. The result will be HEX 25000F. Obviously it will do this for both input fields, it will then add them together (AP or Add Packed) giving a result of HEX 50000F - actually a much longer intermediate result which will be "truncated" to this value. This result will then be "unpacked" (UPK), a process which puts entirely new "F"s back into the zone part of each byte (so whatever was in the zone part originally is just lost forever), along with the number part. The sign part is again swapped to its correct position in a zoned representation from its correct position in a packed representation. So, now, F5F0F0F0F0 or 50000. All the intermediate values are in an area of the program set aside for this purpose, which you can locate, for instance in a dump, if necessary.

So, notice, the 25 never became 25000. Also, it is the CVP and UPK which are doing the "work", Cobol is just messing with the sign (depending on...). Nowhere is a HEX 40 zero being "converted". The three 40s in the example are treated in two different ways, and in both instances as if they were X0, where X is anything, value 0 to F.

I haven't checked this againt the generated code. I suppose I should, but I have "one of my heads" at the moment. Later, maybe. I'm sure if I'm wrong someone will point it out. But I really don't believe they could have changed this as well as the compile options. However, we live and learn.

Re: about Accept statement accept number

PostPosted: Thu Mar 31, 2011 4:37 pm
by Pumpkin
BillyBoyo and Robert, thanks a lot for explaining such detail. and it will take a while for me to absorb it.
and you mentioned about compiler option, is it set some parameters in JCL when compile a COBOL code, or it is for system adminstrator to set these things, ordinary user can't change it?

Re: about Accept statement accept number

PostPosted: Thu Mar 31, 2011 4:47 pm
by Robert Sample
Default compile parameters are set when COBOL is installed at the site. If the site uses Endevor, for example, other default compile parameters can be set up for use with batch and online compiles. You can always provide overrides, however, either through a JCL parameter or via the PROCESS (also known as CBL) compiler directive. See the COBOL Programming Guide manual for details -- search for "compiler directive" -- or look in section 2.1.5.1 for more information.