Generating the pseudo-assembler is a useful suggestion, then you will see exactly what is happening.
Also, looking at the Cobol manuals should give you an understanding.
Your INITIALIZEs are pointless, as before you do anything with those fields, they are the target of MOVEs, so their previous value is entirely irrelevant.
The 9999 is the easiest. In the MOVE, Cobol treated the field as Zoned Decimal, and you get the 9999 in your comp-3. Unsigned, as your COMP-3 is unsigned, so you get the 9F in the last byte of your COMP-3.
Where you have put alphabetic characters, they will again be treated as Zoned Decimal, the Zone part is ignored for the MOVE, so you get something that turns up as a number, which if you look at it exactly matches the Number part of the EBCDIC code for the letters you have chosen.
If you want to get an Abend, S0C7, you have to be more creative with your data. Try with assorted symbols from your keyboard. You should be able to get S0C7 if you understand valid Zoned Decimal formats (for the move, the Zone is ignored, the Numeric part has to be 0-9 and the Sign has to be A-F. If you arrange differently, you should achieve your S0C7.
We're not going to get much further without you showing us the pseudo-assembler generated by the Cobol compiler.
Why? Well, with numeric stuff, the compiler options, especially NUMPROC, mean what is generated can be very different from one option to another.
On top of that, I can't say that I have ever moved a PIC X to a COMP-3.
One day, support or maintenance guys are going to be looking at your programs because of some problem or other. If you want to make things difficult for them, you will have used this sort of MOVE, so that they have to stop and wonder "what the heck does that do"? It might even be you doing the wondering.
If you want to know why there was no S0C7 before and a S0C7 now, post the generated code.
If you want my advice, don't ever do this "for real".
Did you take my advice about removing the intialises? Bad move. I've only now noticed that the cute little IF is using WS-G which, despite my assertion, is not getting set to anything.
That would get you a damn S0C7. My fault, if it is that. Sorry. Plus serves me right to continue thinking about it.
I'm trusting your output.
With the unsigned version, you are getting "correct" numeric values in your comp-3 fields.
I can think of no way, at all, that just changing the sign in this instance would cause a S0C7. All the "signs" are valid, all the "numerics" are valid in your examples.
The generated code, if we ever see it, is probably along the lines of PACK, OR the sign, AND the left-most byte for the 4-digit comp-3. Nothing there to S0C7 even if data bad enough, which it isn't. I think it could do it all "in place".
Would the DISPLAY bomb if you got bad-enough data? I don't think so, but maybe we'll see.
The IF (yes, that one) is the only genuine potential (I think) for S0C7.
Now, with your first example, it really does depend on NUMPROC. With NOPFD (normal default) you would see a CLC generated, as enrico surmised. No S0C7 there. With PFD, you would see a CP - Compare Packed, potential for S0C7.
Except, none of your examples would cause a S0C7.
So, you took my (sloppy) advice. WS-G has an indeterminate value (likely binary zeros). With NOPFD no abend on unsigned fields ("sign-fixing/-rectification" for unsigned fields, CLC generated for compare). With NOPFD for signed fields, CP generated and abend S0C7.
With PFD, no sign-fixing, CP for unsiged fields, abend S0C7. With signed fields, CLC generated, no abend. "Correct" route through IF taken by accident.
I suggest WS-G should have a VALUE ZERO added to the definition. If you want it later to be zero again, what is wrong with MOVE ZERO?
That's not the pseudo-assembler. Check the manual for how to list the code generated by the compiler. All you have here is the inline DMAP and references to the lines where the data-names are generated.
What your program demonstrates so far is that if you let bad data get into your system, it can hang around until you do something that requires the use of instruction which will fail on the packed data, will cause an S0C7 - plus, not all data that "looks" bad, is "bad" as far as 370 instructions are concerned.
A PACK instruction will not cause an S0C7, nor will an UNPACK. Even for the DISPLAY statements you are probably just getting an UNPACK to turn it back into something that gives you the output of the DISPLAY.
Even the IF can be unproblematic, but you have a better chance there. Try your funny characters in WS-E.
Any sort of calculation with WS-D, assuming you have chosen your funny characters correctly, will cause a S0C7. All your other values are just not bad enough even to make a calculation get a S0C7. The answer will be nonsense, because the starting-point is nonsense, but you will not get a S0C7.
If you have rubbish inputs from a file external to your system, they can get incorporated into your system and in cases not cause a S0C7, in other cases cause a S0C7. For every numeric field from an external system, use a NUMERIC test before relying on the content of the field, and do whatever the analyst decides you should do if not NUMERIC. Just using the data is not acceptable. If you have a GUARANTEE that the fields will always be numeric, test them anyway and "user" abend if not. Don't let bad data into your system. You have demonstrated what can happen (things just trundle along as "normal"), so don't let it happen to your systems from now on.
For the actual specifics to your question in this example we'd need to see the generated code, but it will still come down to the answer that the instructions used are either not capable of producing a S0C7, or, possibly in the case of the IF, the data you have provided to the field is not capable of producing a S0C7.
You can never just say "that field looks like crap, it will S0C7"(*), because there are many situations where "crap" just won't do that - but it is still crap, so you have to trap-the-crap yourself for all external numeric data.
(*) you can say this only when you know what will and won't cause a S0C7 with particular data and particular instructions (and particular compiler options, which can generate different instructions depending on the value of option chosen).
EDIT: enrico alluded to all this in his response to you initial post.