EBCDIC, ASCII and sort order
Every byte on a z/OS mainframe is interpreted with EBCDIC (Extended
Binary Coded Decimal Interchange Code), not ASCII. Your COBOL source,
your datasets and your PIC X fields are all EBCDIC. The characters look
the same on screen, but the bytes underneath are different, and so is the
order they sort in.
| Character | EBCDIC (code page 037) | ASCII |
|---|---|---|
| space | X'40' |
X'20' |
a–i |
X'81'–X'89' |
X'61'–X'69' |
A–I |
X'C1'–X'C9' |
X'41'–X'49' |
J–R |
X'D1'–X'D9' |
X'4A'–X'52' |
S–Z |
X'E2'–X'E9' |
X'53'–X'5A' |
0–9 |
X'F0'–X'F9' |
X'30'–X'39' |
EBCDIC descends from punched cards, which is why the letters come in three blocks with gaps between them. Two consequences matter every day:
- Sort order. EBCDIC: space < lower case < upper case < digits. ASCII: space < digits < upper case < lower case. The same file sorts differently on the two platforms.
- Ranges.
IF WS-CHAR >= "A" AND <= "Z"is also true for some non-letter bytes in the EBCDIC gaps. Use the class testALPHABETICinstead.
Seeing the difference
This course runs GnuCOBOL on an ASCII machine. Run this:
IDENTIFICATION DIVISION.
PROGRAM-ID. COLLATE.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-CODE-1 PIC X(4) VALUE "A100".
01 WS-CODE-2 PIC X(4) VALUE "1000".
01 WS-CODE-3 PIC X(4) VALUE "a100".
PROCEDURE DIVISION.
IF WS-CODE-2 < WS-CODE-1
DISPLAY "DIGITS SORT BEFORE LETTERS"
ELSE
DISPLAY "LETTERS SORT BEFORE DIGITS"
END-IF
IF WS-CODE-1 < WS-CODE-3
DISPLAY "UPPER CASE SORTS BEFORE LOWER CASE"
ELSE
DISPLAY "LOWER CASE SORTS BEFORE UPPER CASE"
END-IF
DISPLAY "A IS X'" FUNCTION HEX-OF(WS-CODE-1(1:1)) "'"
STOP RUN.
DIGITS SORT BEFORE LETTERS
UPPER CASE SORTS BEFORE LOWER CASE
A IS X'41'
On z/OS the first two lines would be the opposite, and A would be
X'C1'. You can make GnuCOBOL compare the mainframe way by adding this
before the DATA DIVISION:
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
OBJECT-COMPUTER. IBM-Z
PROGRAM COLLATING SEQUENCE IS MAINFRAME.
SPECIAL-NAMES.
ALPHABET MAINFRAME IS EBCDIC.
Now it prints LETTERS SORT BEFORE DIGITS and LOWER CASE SORTS BEFORE
UPPER CASE. The bytes are still ASCII (X'41'); only comparisons change.
The job simulator's SORT compares ASCII bytes, so its results are the
ASCII order.
Where this bites
- Migrations and downloads. A report checked on a PC shows records in a different order from the mainframe original. Nothing is broken; the collating sequence changed.
- SEARCH ALL and control breaks assume the file is in key order. Sort on one platform and process on the other, and the order check fails.
- HIGH-VALUES / LOW-VALUES are
X'FF'andX'00'on both, so they still sort last and first. - File transfer. FTP in ASCII mode translates each byte. That is right for pure text and wrong for any record containing packed or binary fields, which must go in binary mode.
On the job
When a test comparison fails "for no reason" after data moved between
z/OS and a distributed system, check three things first: code page,
sort order, and whether numeric fields were translated as if they were
text. In ISPF, HEX ON shows you the real bytes in seconds.