☕ Um Café no Bellacosa Mainframe
Gostou do conteúdo? Ajude a manter o café quente, o COBOL compilando e o mainframe acordado. 😄
☕ Pague um café ao Bellacosa

Translate

Mostrar mensagens com a etiqueta compilação COBOL. Mostrar todas as mensagens
Mostrar mensagens com a etiqueta compilação COBOL. Mostrar todas as mensagens

quinta-feira, 23 de julho de 2026

COMP-4 e COMP-5 sem Mistérios — Parte II : Laboratório Prático com TRUNC(STD), TRUNC(OPT), TRUNC(BIN), JCL, Hexadecimal, Testes e Pequenos Acidentes Controlados

Bellacosa Maifnrame com laboratorio pratico cobol comp-4  comp-5


☕ Um Café no Bellacosa Mainframe

COMP-4 e COMP-5 sem Mistérios — Parte II

Laboratório Prático com TRUNC(STD), TRUNC(OPT), TRUNC(BIN), JCL, Hexadecimal, Testes e Pequenos Acidentes Controlados

Na primeira parte, descobrimos que COMP-4 e COMP-5 guardam números em formato binário, mas não fazem exatamente o mesmo contrato com o compilador.

Agora chegou a hora de abandonar a segurança filosófica da teoria e entrar no laboratório.

Nesta segunda parte, faremos o seguinte:

  • criaremos um programa COBOL de testes;

  • compilaremos o mesmo fonte com TRUNC(STD), TRUNC(OPT) e TRUNC(BIN);

  • executaremos três load modules diferentes;

  • mostraremos o conteúdo decimal e hexadecimal dos campos;

  • compararemos COMP-4 com COMP-5;

  • testaremos valores acima do limite do PICTURE;

  • provocaremos truncamentos controlados;

  • analisaremos resultados estranhos;

  • trabalharemos com REDEFINES;

  • estudaremos ON SIZE ERROR;

  • construiremos exercícios para o programador padawan.

O objetivo não é decorar tabelas.

O objetivo é aprender a olhar para um campo COBOL e perguntar:

Quantos dígitos ele declara, quantos bytes ele ocupa e qual dessas duas verdades o compilador utilizará nesta operação?


1. Preparando o laboratório

Utilizaremos um programa chamado:

TRUNCLAB

O mesmo fonte será compilado três vezes.

Cada compilação produzirá um load module:

TRNSTD
TRNOPT
TRNBIN

As opções serão:

TRUNC(STD)
TRUNC(OPT)
TRUNC(BIN)

Depois executaremos os três módulos e compararemos o SYSOUT.

A opção TRUNC afeta a maneira como dados BINARY, COMP e COMP-4 são tratados em movimentos e operações aritméticas. Ela não altera o comportamento de itens COMP-5: para esses campos, o compilador sempre aplica a lógica equivalente a TRUNC(BIN). (IBM)


2. Recordando o tamanho dos campos binários

No Enterprise COBOL, o tamanho físico de um campo binário depende da quantidade de dígitos do PICTURE:

Quantidade de dígitosArmazenamento
1 a 42 bytes
5 a 94 bytes
10 a 188 bytes

Assim:

05 CAMPO-A PIC S9(4) COMP-4.

ocupa 2 bytes.

05 CAMPO-B PIC S9(5) COMP-4.

ocupa 4 bytes.

05 CAMPO-C PIC S9(10) COMP-4.

ocupa 8 bytes.

Os números negativos são representados em complemento de dois, e os dados binários no IBM Z são armazenados em ordem big-endian. (IBM)


3. A tabela que o padawan deve ter ao lado do terminal

Campos de 2 bytes com sinal

PIC S9(1) até PIC S9(4)

Capacidade física:

-32768 até +32767

Campos de 2 bytes sem sinal

PIC 9(1) até PIC 9(4)

Capacidade física:

0 até 65535

Campos de 4 bytes com sinal

PIC S9(5) até PIC S9(9)

Capacidade física:

-2147483648 até +2147483647

Campos de 4 bytes sem sinal

PIC 9(5) até PIC 9(9)

Capacidade física:

0 até 4294967295

Essas faixas representam a capacidade nativa utilizada por COMP-5. Em um campo COMP-4, a opção TRUNC poderá determinar se o programa considera a capacidade decimal do PICTURE ou a capacidade física dos bytes. (IBM)


4. Programa COBOL completo do laboratório

Grave o programa a seguir em um membro como:

USER.COBOL(TRUNCLAB)

O programa contém diferentes grupos de testes.

       IDENTIFICATION DIVISION.
       PROGRAM-ID. TRUNCLAB.

       ENVIRONMENT DIVISION.
       CONFIGURATION SECTION.
       SOURCE-COMPUTER. IBM-Z.
       OBJECT-COMPUTER. IBM-Z.

       DATA DIVISION.
       WORKING-STORAGE SECTION.

      *---------------------------------------------------------------*
      * IDENTIFICACAO DO LABORATORIO                                  *
      *---------------------------------------------------------------*

       01  WS-TITULO.
           05 FILLER PIC X(45)
              VALUE 'LABORATORIO COBOL - COMP-4, COMP-5 E TRUNC'.

       01  WS-SEPARADOR PIC X(70) VALUE ALL '-'.

      *---------------------------------------------------------------*
      * CAMPOS DE EDICAO                                              *
      *---------------------------------------------------------------*

       01  WS-EDIT-SIGNED    PIC -ZZZ,ZZZ,ZZZ,ZZZ,ZZZ,ZZ9.
       01  WS-EDIT-UNSIGNED  PIC ZZZ,ZZZ,ZZZ,ZZZ,ZZZ,ZZ9.

      *---------------------------------------------------------------*
      * TESTE 1 - HALFWORD COM SINAL                                  *
      *---------------------------------------------------------------*

       01  WS-T1-ENTRADA        PIC S9(9) COMP-5 VALUE ZERO.

       01  WS-T1-COMP4.
           05 WS-T1-C4          PIC S9(4) COMP-4 VALUE ZERO.

       01  WS-T1-COMP4-RAW REDEFINES WS-T1-COMP4.
           05 WS-T1-C4-BYTES    PIC X(2).

       01  WS-T1-COMP5.
           05 WS-T1-C5          PIC S9(4) COMP-5 VALUE ZERO.

       01  WS-T1-COMP5-RAW REDEFINES WS-T1-COMP5.
           05 WS-T1-C5-BYTES    PIC X(2).

      *---------------------------------------------------------------*
      * TESTE 2 - HALFWORD SEM SINAL                                  *
      *---------------------------------------------------------------*

       01  WS-T2-ENTRADA        PIC 9(9) COMP-5 VALUE ZERO.

       01  WS-T2-COMP4.
           05 WS-T2-C4          PIC 9(4) COMP-4 VALUE ZERO.

       01  WS-T2-COMP4-RAW REDEFINES WS-T2-COMP4.
           05 WS-T2-C4-BYTES    PIC X(2).

       01  WS-T2-COMP5.
           05 WS-T2-C5          PIC 9(4) COMP-5 VALUE ZERO.

       01  WS-T2-COMP5-RAW REDEFINES WS-T2-COMP5.
           05 WS-T2-C5-BYTES    PIC X(2).

      *---------------------------------------------------------------*
      * TESTE 3 - EXEMPLO CLASSICO IBM                                *
      *---------------------------------------------------------------*

       01  WS-T3-ENTRADA        PIC S9(9) COMP-5 VALUE ZERO.

       01  WS-T3-COMP4.
           05 WS-T3-C4          PIC S99 COMP-4 VALUE ZERO.

       01  WS-T3-COMP4-RAW REDEFINES WS-T3-COMP4.
           05 WS-T3-C4-BYTES    PIC X(2).

       01  WS-T3-COMP5.
           05 WS-T3-C5          PIC S99 COMP-5 VALUE ZERO.

       01  WS-T3-COMP5-RAW REDEFINES WS-T3-COMP5.
           05 WS-T3-C5-BYTES    PIC X(2).

      *---------------------------------------------------------------*
      * TESTE 4 - FULLWORD                                            *
      *---------------------------------------------------------------*

       01  WS-T4-ENTRADA        PIC 9(10) COMP-5 VALUE ZERO.

       01  WS-T4-COMP4.
           05 WS-T4-C4          PIC 9(6) COMP-4 VALUE ZERO.

       01  WS-T4-COMP4-RAW REDEFINES WS-T4-COMP4.
           05 WS-T4-C4-BYTES    PIC X(4).

       01  WS-T4-COMP5.
           05 WS-T4-C5          PIC 9(6) COMP-5 VALUE ZERO.

       01  WS-T4-COMP5-RAW REDEFINES WS-T4-COMP5.
           05 WS-T4-C5-BYTES    PIC X(4).

      *---------------------------------------------------------------*
      * TESTE 5 - ARITMETICA                                          *
      *---------------------------------------------------------------*

       01  WS-T5-COMP4.
           05 WS-T5-C4          PIC 9(4) COMP-4 VALUE ZERO.

       01  WS-T5-COMP4-RAW REDEFINES WS-T5-COMP4.
           05 WS-T5-C4-BYTES    PIC X(2).

       01  WS-T5-COMP5.
           05 WS-T5-C5          PIC 9(4) COMP-5 VALUE ZERO.

       01  WS-T5-COMP5-RAW REDEFINES WS-T5-COMP5.
           05 WS-T5-C5-BYTES    PIC X(2).

      *---------------------------------------------------------------*
      * TESTE 6 - SIZE ERROR                                          *
      *---------------------------------------------------------------*

       01  WS-T6-COMP4          PIC 9(4) COMP-4 VALUE ZERO.
       01  WS-T6-COMP5          PIC 9(4) COMP-5 VALUE ZERO.
       01  WS-T6-STATUS         PIC X(20) VALUE SPACES.

      *---------------------------------------------------------------*
      * PROCEDURE DIVISION                                            *
      *---------------------------------------------------------------*

       PROCEDURE DIVISION.

       0000-MAIN.

           DISPLAY WS-SEPARADOR
           DISPLAY WS-TITULO
           DISPLAY WS-SEPARADOR

           PERFORM 1000-TESTE-HALFWORD-SIGNED
           PERFORM 2000-TESTE-HALFWORD-UNSIGNED
           PERFORM 3000-TESTE-IBM-HALFWORD
           PERFORM 4000-TESTE-IBM-FULLWORD
           PERFORM 5000-TESTE-ARITMETICA
           PERFORM 6000-TESTE-SIZE-ERROR

           DISPLAY WS-SEPARADOR
           DISPLAY 'FIM DO LABORATORIO'
           DISPLAY WS-SEPARADOR

           GOBACK.

      *---------------------------------------------------------------*
      * TESTE 1                                                       *
      *---------------------------------------------------------------*

       1000-TESTE-HALFWORD-SIGNED.

           DISPLAY SPACE
           DISPLAY 'TESTE 1 - PIC S9(4), VALOR 30000'
           DISPLAY WS-SEPARADOR

           MOVE 30000 TO WS-T1-ENTRADA
           MOVE WS-T1-ENTRADA TO WS-T1-C4
           MOVE WS-T1-ENTRADA TO WS-T1-C5

           MOVE WS-T1-C4 TO WS-EDIT-SIGNED
           DISPLAY 'COMP-4 DECIMAL : ' WS-EDIT-SIGNED
           DISPLAY 'COMP-4 HEX     : '
                   FUNCTION HEX-OF(WS-T1-C4-BYTES)

           MOVE WS-T1-C5 TO WS-EDIT-SIGNED
           DISPLAY 'COMP-5 DECIMAL : ' WS-EDIT-SIGNED
           DISPLAY 'COMP-5 HEX     : '
                   FUNCTION HEX-OF(WS-T1-C5-BYTES).

      *---------------------------------------------------------------*
      * TESTE 2                                                       *
      *---------------------------------------------------------------*

       2000-TESTE-HALFWORD-UNSIGNED.

           DISPLAY SPACE
           DISPLAY 'TESTE 2 - PIC 9(4), VALOR 60000'
           DISPLAY WS-SEPARADOR

           MOVE 60000 TO WS-T2-ENTRADA
           MOVE WS-T2-ENTRADA TO WS-T2-C4
           MOVE WS-T2-ENTRADA TO WS-T2-C5

           MOVE WS-T2-C4 TO WS-EDIT-UNSIGNED
           DISPLAY 'COMP-4 DECIMAL : ' WS-EDIT-UNSIGNED
           DISPLAY 'COMP-4 HEX     : '
                   FUNCTION HEX-OF(WS-T2-C4-BYTES)

           MOVE WS-T2-C5 TO WS-EDIT-UNSIGNED
           DISPLAY 'COMP-5 DECIMAL : ' WS-EDIT-UNSIGNED
           DISPLAY 'COMP-5 HEX     : '
                   FUNCTION HEX-OF(WS-T2-C5-BYTES).

      *---------------------------------------------------------------*
      * TESTE 3                                                       *
      *---------------------------------------------------------------*

       3000-TESTE-IBM-HALFWORD.

           DISPLAY SPACE
           DISPLAY 'TESTE 3 - PIC S99, VALOR 123451'
           DISPLAY WS-SEPARADOR

           MOVE 123451 TO WS-T3-ENTRADA
           MOVE WS-T3-ENTRADA TO WS-T3-C4
           MOVE WS-T3-ENTRADA TO WS-T3-C5

           MOVE WS-T3-C4 TO WS-EDIT-SIGNED
           DISPLAY 'COMP-4 DECIMAL : ' WS-EDIT-SIGNED
           DISPLAY 'COMP-4 HEX     : '
                   FUNCTION HEX-OF(WS-T3-C4-BYTES)

           MOVE WS-T3-C5 TO WS-EDIT-SIGNED
           DISPLAY 'COMP-5 DECIMAL : ' WS-EDIT-SIGNED
           DISPLAY 'COMP-5 HEX     : '
                   FUNCTION HEX-OF(WS-T3-C5-BYTES).

      *---------------------------------------------------------------*
      * TESTE 4                                                       *
      *---------------------------------------------------------------*

       4000-TESTE-IBM-FULLWORD.

           DISPLAY SPACE
           DISPLAY 'TESTE 4 - PIC 9(6), VALOR 1234567891'
           DISPLAY WS-SEPARADOR

           MOVE 1234567891 TO WS-T4-ENTRADA
           MOVE WS-T4-ENTRADA TO WS-T4-C4
           MOVE WS-T4-ENTRADA TO WS-T4-C5

           MOVE WS-T4-C4 TO WS-EDIT-UNSIGNED
           DISPLAY 'COMP-4 DECIMAL : ' WS-EDIT-UNSIGNED
           DISPLAY 'COMP-4 HEX     : '
                   FUNCTION HEX-OF(WS-T4-C4-BYTES)

           MOVE WS-T4-C5 TO WS-EDIT-UNSIGNED
           DISPLAY 'COMP-5 DECIMAL : ' WS-EDIT-UNSIGNED
           DISPLAY 'COMP-5 HEX     : '
                   FUNCTION HEX-OF(WS-T4-C5-BYTES).

      *---------------------------------------------------------------*
      * TESTE 5                                                       *
      *---------------------------------------------------------------*

       5000-TESTE-ARITMETICA.

           DISPLAY SPACE
           DISPLAY 'TESTE 5 - ARITMETICA 9000 + 5000'
           DISPLAY WS-SEPARADOR

           MOVE 9000 TO WS-T5-C4
           MOVE 9000 TO WS-T5-C5

           ADD 5000 TO WS-T5-C4
           ADD 5000 TO WS-T5-C5

           MOVE WS-T5-C4 TO WS-EDIT-UNSIGNED
           DISPLAY 'COMP-4 DECIMAL : ' WS-EDIT-UNSIGNED
           DISPLAY 'COMP-4 HEX     : '
                   FUNCTION HEX-OF(WS-T5-C4-BYTES)

           MOVE WS-T5-C5 TO WS-EDIT-UNSIGNED
           DISPLAY 'COMP-5 DECIMAL : ' WS-EDIT-UNSIGNED
           DISPLAY 'COMP-5 HEX     : '
                   FUNCTION HEX-OF(WS-T5-C5-BYTES).

      *---------------------------------------------------------------*
      * TESTE 6                                                       *
      *---------------------------------------------------------------*

       6000-TESTE-SIZE-ERROR.

           DISPLAY SPACE
           DISPLAY 'TESTE 6 - ON SIZE ERROR'
           DISPLAY WS-SEPARADOR

           MOVE ZERO TO WS-T6-C4 WS-T6-C5
           MOVE SPACES TO WS-T6-STATUS

           COMPUTE WS-T6-C4 =
                   9000 + 5000
               ON SIZE ERROR
                   MOVE 'SIZE ERROR COMP-4' TO WS-T6-STATUS
           END-COMPUTE

           DISPLAY 'STATUS COMP-4  : ' WS-T6-STATUS

           MOVE SPACES TO WS-T6-STATUS

           COMPUTE WS-T6-C5 =
                   9000 + 5000
               ON SIZE ERROR
                   MOVE 'SIZE ERROR COMP-5' TO WS-T6-STATUS
           END-COMPUTE

           DISPLAY 'STATUS COMP-5  : ' WS-T6-STATUS

           MOVE WS-T6-C4 TO WS-EDIT-UNSIGNED
           DISPLAY 'VALOR COMP-4   : ' WS-EDIT-UNSIGNED

           MOVE WS-T6-C5 TO WS-EDIT-UNSIGNED
           DISPLAY 'VALOR COMP-5   : ' WS-EDIT-UNSIGNED.

5. Por que usamos REDEFINES?

Observe:

01  WS-T1-COMP4.
    05 WS-T1-C4 PIC S9(4) COMP-4.

01  WS-T1-COMP4-RAW REDEFINES WS-T1-COMP4.
    05 WS-T1-C4-BYTES PIC X(2).

O REDEFINES não converte o campo.

Ele apenas permite enxergar os mesmos bytes como uma área alfanumérica.

Depois usamos:

FUNCTION HEX-OF(WS-T1-C4-BYTES)

Isso produz uma apresentação hexadecimal dos bytes.

Para o valor decimal 30000, o hexadecimal é:

7530

Em binário:

0111 0101 0011 0000

Como o bit mais significativo é zero, o número é positivo.


6. O hexadecimal que todo padawan deveria reconhecer

Valor decimal 1

Em halfword:

0001

Valor decimal 100

0064

Valor decimal 1000

03E8

Valor decimal 9999

270F

Valor decimal 14000

36B0

Valor decimal 30000

7530

Valor decimal 32767

7FFF

Valor decimal -1

FFFF

Valor decimal -32768

8000

Valor decimal 60000 sem sinal

EA60

O mesmo padrão EA60, se interpretado como um inteiro de 16 bits com sinal, representa um número negativo:

-5536

Aqui está uma das grandes lições do laboratório:

Os bytes não carregam uma pequena placa dizendo “sou signed” ou “sou unsigned”. A declaração COBOL determina como eles serão interpretados.


7. JCL completo usando a procedure IGYWCL

A IBM fornece procedures catalogadas para compilação e linkedição, embora os nomes, parâmetros e bibliotecas possam variar conforme a instalação.

A procedure IGYWCL normalmente executa duas etapas: compila o programa e depois utiliza o objeto gerado para criar o load module na biblioteca indicada por SYSLMOD. (IBM)

No exemplo abaixo, ajuste:

USER.COBOL
USER.LOAD

para os nomes utilizados em seu ambiente.

//TRUNCLAB JOB (ACCT),'BELLACOSA LAB',
//             CLASS=A,
//             MSGCLASS=H,
//             MSGLEVEL=(1,1),
//             NOTIFY=&SYSUID
//*
//*********************************************************************
//* COMPILACAO 1 - TRUNC(STD)
//*********************************************************************
//CSTD     EXEC IGYWCL,
//         PARM.COBOL='LIB,OBJECT,LIST,MAP,XREF,OFFSET,
//         OPT(2),TRUNC(STD)'
//COBOL.SYSIN DD DISP=SHR,DSN=USER.COBOL(TRUNCLAB)
//COBOL.SYSLIB DD DISP=SHR,DSN=USER.COPYLIB
//LKED.SYSLMOD DD DISP=SHR,DSN=USER.LOAD(TRNSTD)
//*
//*********************************************************************
//* COMPILACAO 2 - TRUNC(OPT)
//*********************************************************************
//COPT     EXEC IGYWCL,
//         PARM.COBOL='LIB,OBJECT,LIST,MAP,XREF,OFFSET,
//         OPT(2),TRUNC(OPT)'
//COBOL.SYSIN DD DISP=SHR,DSN=USER.COBOL(TRUNCLAB)
//COBOL.SYSLIB DD DISP=SHR,DSN=USER.COPYLIB
//LKED.SYSLMOD DD DISP=SHR,DSN=USER.LOAD(TRNOPT)
//*
//*********************************************************************
//* COMPILACAO 3 - TRUNC(BIN)
//*********************************************************************
//CBIN     EXEC IGYWCL,
//         PARM.COBOL='LIB,OBJECT,LIST,MAP,XREF,OFFSET,
//         OPT(2),TRUNC(BIN)'
//COBOL.SYSIN DD DISP=SHR,DSN=USER.COBOL(TRUNCLAB)
//COBOL.SYSLIB DD DISP=SHR,DSN=USER.COPYLIB
//LKED.SYSLMOD DD DISP=SHR,DSN=USER.LOAD(TRNBIN)
//*
//*********************************************************************
//* EXECUCAO DO MODULO TRUNC(STD)
//*********************************************************************
//RUNSTD   EXEC PGM=TRNSTD,
//         COND=(4,LT)
//STEPLIB  DD DISP=SHR,DSN=USER.LOAD
//SYSOUT   DD SYSOUT=*
//CEEDUMP  DD SYSOUT=*
//SYSUDUMP DD SYSOUT=*
//*
//*********************************************************************
//* EXECUCAO DO MODULO TRUNC(OPT)
//*********************************************************************
//RUNOPT   EXEC PGM=TRNOPT,
//         COND=(4,LT)
//STEPLIB  DD DISP=SHR,DSN=USER.LOAD
//SYSOUT   DD SYSOUT=*
//CEEDUMP  DD SYSOUT=*
//SYSUDUMP DD SYSOUT=*
//*
//*********************************************************************
//* EXECUCAO DO MODULO TRUNC(BIN)
//*********************************************************************
//RUNBIN   EXEC PGM=TRNBIN,
//         COND=(4,LT)
//STEPLIB  DD DISP=SHR,DSN=USER.LOAD
//SYSOUT   DD SYSOUT=*
//CEEDUMP  DD SYSOUT=*
//SYSUDUMP DD SYSOUT=*
//

Atenção ao PARM

Algumas procedures aceitam:

PARM.COBOL='...'

Outras instalações utilizam parâmetros diferentes ou possuem uma procedure corporativa própria, como:

COBCL
COBOLCL
IGYWCLG
COB6CL

O esqueleto conceitual permanece:

  1. executar o compilador IGYCRCTL;

  2. gerar o objeto em SYSLIN;

  3. executar o binder;

  4. gravar o load module em SYSLMOD;

  5. executar o programa usando STEPLIB.

A IBM documenta IGYCRCTL como o programa compilador e mostra SYSPRINT, SYSLIN, SYSIN e os arquivos SYSUT entre os DDs principais da compilação. (IBM)


8. Versão do JCL sem COPYLIB

Caso o programa não use nenhum COPY, a linha abaixo poderá ser retirada:

//COBOL.SYSLIB DD DISP=SHR,DSN=USER.COPYLIB

Ela foi incluída porque todo laboratório COBOL sério deve estar preparado para o momento em que alguém acrescentará um copybook de 8.000 linhas chamado:

CPYCOMUM

No qual existirão 147 campos, 23 níveis 88 e um comentário de 1996 dizendo:

* NAO ALTERAR - PROVISORIO

9. O comportamento de TRUNC(STD)

TRUNC(STD) aplica-se aos campos receptores BINARY, COMP e COMP-4 em operações como MOVE e expressões aritméticas.

O resultado é ajustado para o número de dígitos declarado no PICTURE do receptor. (IBM)

Considere:

05 WS-DESTINO PIC 9(4) COMP-4.

E:

MOVE 60000 TO WS-DESTINO

O campo físico possui 2 bytes e poderia comportar 60000 sem sinal.

Entretanto, PIC 9(4) descreve apenas quatro dígitos.

Sob TRUNC(STD), a intenção é corrigir o resultado para essa precisão decimal.

Conceitualmente:

60000

será limitado aos quatro dígitos de baixa ordem:

0000

Outro exemplo:

12345

poderá resultar em:

2345

Por que “poderá”?

Porque é necessário considerar exatamente:

  • a declaração do emissor;

  • a declaração do receptor;

  • se o campo é signed ou unsigned;

  • se a operação é MOVE, ADD, COMPUTE ou outra;

  • se existem intermediários;

  • se há otimizações;

  • se foi usado ON SIZE ERROR;

  • a versão do compilador.

Nos casos documentados pela IBM, entretanto, TRUNC(STD) possui comportamento definido de correção à precisão decimal do PICTURE.


10. O comportamento de TRUNC(OPT)

TRUNC(OPT) é uma opção de desempenho.

O compilador assume que os valores enviados aos campos binários obedecem ao PICTURE.

A partir dessa premissa, ele escolhe a sequência de código mais eficiente. Essa sequência poderá corrigir o resultado para os dígitos do PICTURE ou apenas para o tamanho físico de 2, 4 ou 8 bytes. (IBM)

Por isso, não existe uma resposta universal para isto:

05 WS-DESTINO PIC 9(4) COMP-4.

MOVE 60000 TO WS-DESTINO

quando compilado com:

TRUNC(OPT)

O programa está violando a premissa da opção.

60000 não cabe na precisão de PIC 9(4).

A própria IBM afirma que, nessas condições, o resultado pode ser imprevisível e depender da sequência específica de código gerada. (IBM)

Imprevisível aqui não significa que o processador invocará um demônio.

Significa que o programador não deve escrever uma regra funcional contando com determinado resultado.

Uma mudança aparentemente inocente poderá alterar o código gerado:

MOVE WS-ORIGEM TO WS-DESTINO

pode não produzir a mesma sequência interna que:

COMPUTE WS-DESTINO = WS-ORIGEM

Ou:

ADD ZERO TO WS-ORIGEM
    GIVING WS-DESTINO

O compilador otimiza cada construção.


11. O comportamento de TRUNC(BIN)

Com TRUNC(BIN), todos os campos:

BINARY
COMP
COMP-4

são tratados como se fossem COMP-5.

Os receptores são truncados somente no limite físico de:

2 bytes
4 bytes
8 bytes

O conteúdo binário inteiro do campo torna-se significativo. (IBM)

Considere:

05 WS-DESTINO PIC 9(4) COMP-4.

Sob TRUNC(BIN), o campo é tratado como um inteiro binário nativo de 2 bytes sem sinal.

Assim, poderá conter:

60000

porque 60000 cabe no intervalo físico:

0 a 65535

O PICTURE 9(4) continua escrito no programa, mas a magnitude operacional considerada passa a ser a capacidade física do halfword.


12. COMP-5 nos três programas

Este campo:

05 WS-DESTINO PIC 9(4) COMP-5.

terá comportamento nativo independentemente da compilação usar:

TRUNC(STD)
TRUNC(OPT)
TRUNC(BIN)

A opção TRUNC não afeta itens COMP-5. Eles são tratados como se TRUNC(BIN) estivesse em vigor para aquele campo específico. (IBM)

Por isso, no teste:

MOVE 60000 TO WS-T2-C5

esperamos que o conteúdo binário seja:

EA60

E o valor sem sinal seja:

60000

nos três load modules.


13. Análise do teste clássico de halfword

A IBM utiliza um exemplo semelhante a:

01 BIN-VAR PIC S99 USAGE BINARY.

MOVE 123451 TO BIN-VAR

O receptor ocupa 2 bytes porque possui apenas dois dígitos no PICTURE.

O valor decimal 123451 em hexadecimal de quatro bytes é:

0001E23B

Quando apenas a metade inferior é movida para o halfword, permanecem:

E23B

Como o bit de sinal está ligado, o halfword é interpretado como:

-7621

A IBM documenta os seguintes resultados para esse exemplo:

OpçãoValor resultanteHexadecimal
TRUNC(STD)510033
TRUNC(OPT)-7621E23B
TRUNC(BIN)-7621E23B

Com TRUNC(STD), o valor é corrigido para os dois dígitos do PICTURE, resultando em 51.

Com TRUNC(BIN), são preservados os 16 bits inferiores, resultando em E23B, que representa -7621 em complemento de dois.

Nesse caso específico, TRUNC(OPT) escolhe uma sequência eficiente semelhante ao resultado físico de TRUNC(BIN). (IBM)

Aqui está o coração do laboratório.

O valor não “virou negativo por erro”.

Ele virou negativo porque:

  1. o receptor só comportava 16 bits;

  2. ficaram os 16 bits inferiores de 123451;

  3. o padrão resultante foi E23B;

  4. o campo era assinado;

  5. E23B possui o bit de sinal ligado.

O hardware apenas obedeceu.

Como sempre, a máquina é inocente e o copybook possui bons advogados.


14. Análise do teste clássico de fullword

Outro exemplo documentado pela IBM utiliza:

01 BIN-VAR PIC 9(6) USAGE BINARY.

MOVE 1234567891 TO BIN-VAR

PIC 9(6) ocupa quatro bytes.

O valor 1234567891 também cabe fisicamente nos quatro bytes:

499602D3

Os resultados documentados são:

OpçãoValor
TRUNC(STD)567891
TRUNC(OPT)567891
TRUNC(BIN)1234567891

Com TRUNC(STD), são mantidos os seis dígitos definidos pelo PICTURE.

Com TRUNC(OPT), nesse código específico, o compilador escolhe uma sequência que também produz a correção decimal.

Com TRUNC(BIN), o valor completo permanece porque cabe no fullword. (IBM)

Nosso teste 4 reproduz essa situação.


15. O teste aritmético 9000 + 5000

Temos:

05 WS-T5-C4 PIC 9(4) COMP-4.
05 WS-T5-C5 PIC 9(4) COMP-5.

Inicializamos:

MOVE 9000 TO WS-T5-C4
MOVE 9000 TO WS-T5-C5

Depois:

ADD 5000 TO WS-T5-C4
ADD 5000 TO WS-T5-C5

O resultado matemático é:

14000

Hexadecimal:

36B0

14000 cabe fisicamente em 2 bytes sem sinal.

Mas não cabe em PIC 9(4) segundo sua precisão decimal.

Resultado conceitual com TRUNC(STD)

O COMP-4 deverá ser corrigido para quatro dígitos:

4000

Hexadecimal:

0FA0

O COMP-5 poderá manter:

14000

Hexadecimal:

36B0

Resultado com TRUNC(BIN)

Tanto o COMP-4 quanto o COMP-5 deverão usar a capacidade física:

14000

Resultado com TRUNC(OPT)

Não construa uma regra funcional sobre esse teste.

Como os operandos produzem valor superior ao PICTURE, a premissa de TRUNC(OPT) foi violada.

O resultado deverá ser observado no listing e no SYSOUT da versão específica do compilador.

Essa incerteza é deliberada.

É justamente o que o laboratório pretende ensinar.


16. ON SIZE ERROR: a armadilha dentro da armadilha

Observe:

COMPUTE WS-T6-C5 =
        9000 + 5000
    ON SIZE ERROR
        MOVE 'SIZE ERROR COMP-5'
          TO WS-T6-STATUS
END-COMPUTE

O campo WS-T6-C5 é:

PIC 9(4) COMP-5

Fisicamente, ele poderia armazenar 14000.

Porém, existe uma particularidade importante.

Quando ON SIZE ERROR é utilizado em uma operação aritmética cujo receptor é COMP-5, o limite considerado para a condição de tamanho é o valor indicado pelo PICTURE, e não necessariamente toda a capacidade física do recipiente. A IBM documenta explicitamente essa regra. (IBM)

Assim, embora 14000 caiba em dois bytes, ele excede:

PIC 9(4)

Logo, ON SIZE ERROR poderá ser acionado.

Esta é uma das curiosidades mais traiçoeiras de COMP-5.

Sem ON SIZE ERROR:

ADD 5000 TO WS-T5-C5

o recipiente nativo poderá guardar 14000.

Com ON SIZE ERROR:

COMPUTE WS-T6-C5 = 9000 + 5000
    ON SIZE ERROR

o compilador considera a capacidade decimal descrita.

O padawan pergunta:

— Então o campo comporta 14000 ou não comporta?

A resposta mainframe é:

— Fisicamente, sim. Semanticamente, depende da instrução.

E é por isso que COBOL continua empregando analistas experientes.


17. Como analisar o listing de compilação

Depois de compilar, abra o SYSPRINT.

Procure pela seção de opções.

Você deverá encontrar algo semelhante a:

TRUNC=STD

ou:

TRUNC=OPT

ou:

TRUNC=BIN

Nunca confie apenas no JCL submetido.

Uma procedure corporativa pode:

  • acrescentar opções;

  • substituir opções;

  • usar defaults da instalação;

  • carregar parâmetros de outro membro;

  • invocar preprocessadores;

  • alterar a ordem de precedência.

O listing é a evidência final da compilação.

Procure também:

OPTIMIZE
ARCH
TUNE
NUMCHECK
SSRANGE
ARITH
NUMPROC

Essas opções não substituem TRUNC, mas podem ajudar a explicar diferenças de código gerado, diagnóstico e desempenho.


18. Como comparar os três SYSOUTs

Crie uma tabela manual:

TesteTRUNC(STD)TRUNC(OPT)TRUNC(BIN)
S9(4) COMP-4 = 30000AnotarAnotarAnotar
S9(4) COMP-5 = 30000300003000030000
9(4) COMP-4 = 60000AnotarAnotar60000
9(4) COMP-5 = 60000600006000060000
S99 COMP-4 = 12345151-7621*-7621
S99 COMP-5 = 123451-7621-7621-7621
9(6) COMP-4 = 1234567891567891567891*1234567891
9(6) COMP-5 = 1234567891123456789112345678911234567891

O asterisco indica resultados documentados para a sequência específica apresentada pela IBM. TRUNC(OPT) não deve ser tratado como promessa quando o valor não respeita o PICTURE.

A ideia é preencher a tabela com o resultado real de seu ambiente.


19. Exercício 1 — Descubra o tamanho

Sem executar o programa, determine o tamanho dos campos:

05 CAMPO-A PIC S9(3) COMP-4.
05 CAMPO-B PIC S9(4) COMP-5.
05 CAMPO-C PIC S9(5) COMP-4.
05 CAMPO-D PIC 9(9) COMP-5.
05 CAMPO-E PIC S9(10) COMP-4.
05 CAMPO-F PIC 9(18) COMP-5.

Resposta

CAMPO-A = 2 bytes
CAMPO-B = 2 bytes
CAMPO-C = 4 bytes
CAMPO-D = 4 bytes
CAMPO-E = 8 bytes
CAMPO-F = 8 bytes

20. Exercício 2 — Limite decimal ou limite físico?

Considere:

05 WS-NUMERO PIC 9(4) COMP-5.

Responda:

  1. Qual é o máximo sugerido pelo PICTURE?

  2. Qual é o máximo físico do campo?

  3. O valor 50000 cabe fisicamente?

  4. O valor 70000 cabe fisicamente?

Resposta

1. 9999
2. 65535
3. Sim
4. Não

70000 exigiria mais do que os 16 bits disponíveis.

Se armazenado sem diagnóstico adequado, ocorrerá perda de bits ou condição de tamanho, dependendo da operação.


21. Exercício 3 — Signed contra unsigned

Considere os bytes:

EA60

Interprete-os como:

PIC 9(4) COMP-5

e depois como:

PIC S9(4) COMP-5

Resposta

Sem sinal:

60000

Com sinal:

-5536

A diferença não está nos bytes.

A diferença está na interpretação.


22. Exercício 4 — Preveja o hexadecimal

Preencha:

DecimalHexadecimal de 2 bytes
1?
255?
256?
1000?
9999?
32767?
-1?

Resposta

DecimalHexadecimal
10001
25500FF
2560100
100003E8
9999270F
327677FFF
-1FFFF

23. Exercício 5 — Faça o programa falhar de maneira educativa

Acrescente:

01 WS-PEQUENO PIC S9(4) COMP-5 VALUE ZERO.

Depois execute:

COMPUTE WS-PEQUENO = 32767 + 1
    ON SIZE ERROR
       DISPLAY 'SIZE ERROR DETECTADO'
END-COMPUTE

Perguntas:

  1. 32768 cabe em um halfword com sinal?

  2. Qual seria o padrão hexadecimal de -32768?

  3. Por que o bit de sinal é importante?

Respostas

  1. Não. O máximo positivo é 32767.

  2. 8000.

  3. Em um campo com sinal, o bit mais significativo participa da representação do sinal. Ao ultrapassar 7FFF, o padrão seguinte é 8000, interpretado como -32768.


24. Exercício 6 — Troque COMP-4 por COMP-5

Pegue:

05 WS-CONTADOR PIC 9(4) COMP-4.

Altere para:

05 WS-CONTADOR PIC 9(4) COMP-5.

Execute com os valores:

9998
9999
10000
32767
32768
60000
65535
65536

Observe:

  • decimal exibido;

  • hexadecimal;

  • comportamento com ON SIZE ERROR;

  • comportamento sem ON SIZE ERROR;

  • diferença entre compiladores;

  • diferença entre operações MOVE, ADD e COMPUTE.

Este exercício mostra que trocar apenas o USAGE pode alterar o contrato do campo, mesmo que seu tamanho físico permaneça idêntico.


25. Exercício 7 — O campo corrompido pela interface

Simule um programa externo preenchendo bytes diretamente:

01 WS-AREA.
   05 WS-BIN PIC S9(4) COMP-4.

01 WS-AREA-RAW REDEFINES WS-AREA.
   05 WS-RAW PIC X(2).

Depois:

MOVE X'7530' TO WS-RAW

7530 representa:

30000

Agora exiba WS-BIN nos três programas.

Pergunte:

  • TRUNC(STD) alterará os bytes apenas porque o campo foi consultado?

  • DISPLAY utilizará o conteúdo completo?

  • O comportamento muda se fizermos uma operação aritmética?

  • O que acontece se movermos para um campo DISPLAY PIC S9(4)?

  • O que acontece se movermos para PIC S9(5)?

Este teste é valioso porque imita dados colocados por:

  • C;

  • PL/I;

  • Db2;

  • IMS;

  • uma API;

  • um subsystem;

  • uma estrutura compartilhada;

  • um copybook incompatível.

A IBM recomenda TRUNC(BIN) para programas que recebem valores binários definidos por outros produtos quando esses valores podem não respeitar o PICTURE. Alternativamente, pode-se usar COMP-5 apenas nos campos envolvidos na interface. (IBM)


26. Exercício 8 — Encontre o erro de projeto

Analise:

01 LK-PARAMETROS.
   05 LK-BUFFER-LENGTH PIC 9(4) COMP-4.
   05 LK-RETURN-CODE   PIC S9(4) COMP-4.

A interface em C utiliza:

unsigned short buffer_length;
short return_code;

Perguntas:

  1. buffer_length pode chegar a 65535?

  2. PIC 9(4) comunica corretamente essa faixa?

  3. TRUNC(OPT) é seguro caso o programa C envie 60000?

  4. Qual seria uma declaração mais apropriada?

Possível correção

01 LK-PARAMETROS.
   05 LK-BUFFER-LENGTH PIC 9(4) COMP-5.
   05 LK-RETURN-CODE   PIC S9(4) COMP-5.

Melhor ainda, quando a convenção do projeto permitir, documente a faixa:

01 LK-PARAMETROS.
   05 LK-BUFFER-LENGTH PIC 9(5) COMP-5.
   05 LK-RETURN-CODE   PIC S9(5) COMP-5.

Embora aumentar os noves possa alterar o tamanho físico em algumas faixas, a declaração deve ser analisada em conjunto com o tamanho exigido pela interface.

Em interoperabilidade, não basta dizer “é um número”.

É necessário definir:

signed ou unsigned
16, 32 ou 64 bits
big-endian ou little-endian
por valor ou por referência
com ou sem escala decimal
faixa válida
tratamento de overflow

27. NUMCHECK(BIN) como aliado

Em modernizações, a opção NUMCHECK(BIN) pode ajudar a identificar campos binários que contêm valores incompatíveis com o PICTURE.

Ela é especialmente útil quando uma equipe pretende migrar de:

TRUNC(BIN)

para:

TRUNC(OPT)

ou:

TRUNC(STD)

Porém, ela deve ser utilizada conscientemente em testes, porque verificações adicionais podem afetar desempenho.

A documentação da IBM observa que, quando TRUNC(BIN) e NUMCHECK(BIN) são usados juntos, dados fora da precisão decimal podem gerar diagnóstico ou abend, especialmente quando a intenção é posteriormente mudar para TRUNC(STD) ou TRUNC(OPT). (IBM)

Exemplo de compilação para diagnóstico:

PARM.COBOL='LIST,MAP,XREF,TRUNC(BIN),NUMCHECK(BIN)'

Não implemente isso cegamente em produção.

Primeiro execute em ambiente de testes, avalie os diagnósticos e meça o custo.


28. Desempenho: TRUNC(BIN) não é botão de turbo

Pode parecer que TRUNC(BIN) sempre será mais rápido porque utiliza diretamente o tamanho físico.

Mas isso não é uma regra.

Quando todos os campos binários precisam ser tratados como possuindo até 2, 4 ou 8 bytes significativos, o compilador poderá precisar:

  • utilizar intermediários maiores;

  • gerar conversões adicionais;

  • chamar rotinas auxiliares;

  • preservar faixas maiores durante a aritmética.

A IBM mostra que, no Enterprise COBOL 6, TRUNC(OPT) continua sendo uma boa opção geral de desempenho quando os dados realmente obedecem ao PICTURE. Para itens muito grandes, especialmente acima de nove dígitos, TRUNC(BIN) pode exigir processamento adicional. (IBM)

A regra prática é:

Dados obedecem ao PICTURE:
    considere TRUNC(OPT)

Dados externos podem ultrapassar o PICTURE:
    considere COMP-5 nos campos específicos

Programa inteiro depende de binário nativo:
    avalie TRUNC(BIN)

Não escolha uma opção global para corrigir um único campo mal declarado.

Isso seria semelhante a aumentar a pressão de água da cidade porque a torneira da cozinha está entupida.


29. Checklist de investigação de um problema real

Quando encontrar um valor estranho em COMP-4 ou COMP-5, siga esta ordem.

Passo 1 — Veja a declaração

PIC
USAGE
Sinal
V decimal

Passo 2 — Calcule o tamanho físico

2, 4 ou 8 bytes

Passo 3 — Descubra a origem

O valor veio de:

MOVE
ADD
COMPUTE
arquivo
Db2
CICS
IMS
C
PL/I
API
COMMAREA
LINKAGE SECTION
REDEFINES

Passo 4 — Abra o listing

Confirme:

TRUNC(STD)
TRUNC(OPT)
TRUNC(BIN)

Passo 5 — Veja o hexadecimal

Use:

FUNCTION HEX-OF

ou o dump.

Passo 6 — Interprete o sinal

O campo é:

signed
unsigned

Passo 7 — Compare o receptor

O destino consegue representar todo o valor?

Passo 8 — Examine ON SIZE ERROR

A operação usa essa cláusula?

Passo 9 — Reproduza isoladamente

Crie um programa mínimo.

Passo 10 — Não “corrija” antes de entender

Trocar tudo para COMP-5 pode mascarar outro problema:

  • copybook incorreto;

  • interface incompatível;

  • tamanho errado;

  • endianness;

  • campo corrompido;

  • valor funcionalmente inválido.


30. Easter egg: o valor que mudou após a recompilação

Em algum lugar do planeta existe este código:

05 LK-LENGTH PIC 9(4) COMP.

Durante anos, um programa escrito em C colocou nele:

32000

O sistema funcionava.

Ninguém sabia exatamente por quê, mas funcionava, que é a certificação de qualidade mais respeitada em determinados ambientes legados.

Então chegou o projeto de modernização.

O programa foi recompilado com:

TRUNC(STD)

O valor passou a ser tratado de acordo com os quatro dígitos do PICTURE.

A aplicação começou a reservar buffers menores.

Os registros passaram a chegar truncados.

A sala de crise foi aberta.

O gerente perguntou:

— O COBOL 6 está com defeito?

O compilador, representado por seu advogado, respondeu:

— Eu apenas comecei a respeitar o contrato que vocês escreveram.

Depois de quatro horas, alguém alterou:

PIC 9(4) COMP

para:

PIC 9(4) COMP-5

O sistema voltou a funcionar.

O incidente foi encerrado como:

CAUSA RAIZ: COMPORTAMENTO INESPERADO DA PLATAFORMA

Porque escrever:

CAUSA RAIZ: NINGUEM LEU O COPYBOOK

poderia prejudicar o clima organizacional.


31. O que o padawan deve guardar desta prática

TRUNC(STD) prioriza a precisão decimal declarada no PICTURE.

TRUNC(BIN) prioriza a capacidade física de 2, 4 ou 8 bytes.

TRUNC(OPT) prioriza desempenho e pressupõe que o programa respeita o PICTURE.

COMP-5 aplica o comportamento binário nativo ao campo individual, independentemente da opção TRUNC.

REDEFINES não converte: apenas mostra os mesmos bytes por outra janela.

FUNCTION HEX-OF ajuda a enxergar o que realmente está na memória.

ON SIZE ERROR pode considerar o limite decimal do PICTURE, inclusive em determinadas operações com receptores COMP-5.

Valores externos exigem contratos explícitos de tamanho, sinal, ordem dos bytes e faixa.


Conclusão

O verdadeiro laboratório de COMP-4 e COMP-5 não acontece apenas na WORKING-STORAGE.

Ele acontece na fronteira entre três mundos:

O que o PICTURE declara
O que os bytes comportam
O que o compilador decidiu gerar

Em TRUNC(STD), o PICTURE senta-se na cadeira do diretor e exige que os números respeitem a quantidade de dígitos declarada.

Em TRUNC(BIN), o hardware invade a reunião, coloca os 2, 4 ou 8 bytes sobre a mesa e informa que todos os bits serão utilizados.

Em TRUNC(OPT), o compilador olha para o programador e diz:

— Estou assumindo que você sabe o que está fazendo.

Essa talvez seja a frase mais perigosa já pronunciada por uma ferramenta de desenvolvimento.

O programador COBOL padawan precisa aprender a não depender de acidentes históricos. Um programa não deve funcionar porque um determinado compilador gerou, por coincidência, uma sequência favorável.

Ele deve funcionar porque:

  • a declaração corresponde ao dado;

  • a opção de compilação corresponde ao contrato;

  • o tamanho físico é conhecido;

  • a faixa foi testada;

  • a interface foi documentada;

  • os limites foram verificados;

  • o listing foi lido;

  • o hexadecimal foi compreendido.

No mainframe, o número exibido na tela é apenas a superfície.

Nos bastidores existem bits, bytes, sinais, truncamentos, registradores e decisões tomadas pelo compilador em uma sala escura onde nenhum gerente de projeto jamais entrou.

Quando o padawan aprende a enxergar essa camada invisível, COMP-4 e COMP-5 deixam de ser cláusulas misteriosas.

Tornam-se ferramentas precisas.

E, mais importante, deixam de ser o motivo daquela ligação às três da manhã perguntando por que o valor 60000 voltou como 0000, -5536 ou alguma outra manifestação hexadecimal do caos.

O JCL usa nomes genéricos de datasets e uma IGYWCL típica; os parâmetros exatos da procedure devem ser ajustados ao padrão instalado no ambiente z/OS.

☕ Um Café no Bellacosa Mainframe

Viagem ao Fundo do Mar dos Formatos Numéricos COBOL

Uma expedição pelas profundezas de COMP-1, COMP-2, COMP-3, COMP-4 e COMP-5, onde cada byte pode esconder uma criatura binária.

COMP-4 e COMP-5 sem Mistérios Abrir artigo ↗

Descendo aos arquivos do mainframe...

quinta-feira, 29 de maio de 2025

COMP-4 e COMP-5 : Quando um Programador Cobol Padawan Descobre que um Número Pode Parecer Pequeno no PICTURE... Mas Ocupar um Universo Inteiro de Bits nos Bastidores

Bellacosa Mainframe apresenta o comp-4 e comp-5 no cobol

☕ Um Café no Bellacosa Mainframe

COMP-4 e COMP-5 sem Mistérios para Programadores COBOL

Quando um Programador Padawan Descobre que um Número Pode Parecer Pequeno no PICTURE... Mas Ocupar um Universo Inteiro de Bits nos Bastidores

Existe um momento inevitável na formação de todo programador COBOL.

Ele aprende PIC 9(5), entende COMP-3, consegue ler um arquivo sequencial sem provocar um SOC7 e começa a acreditar que finalmente domina o reino numérico do mainframe.

Então aparece isto:

05 WS-CONTADOR       PIC S9(9) COMP-4.
05 WS-CODIGO-RETORNO PIC S9(4) COMP-5.

O padawan olha para a tela verde e pergunta:

— Mestre, qual é a diferença entre COMP-4 e COMP-5?

O mestre COBOL respira fundo, olha para o teto do data center e responde:

— A diferença está em quem manda no número: o PICTURE ou o recipiente binário.

E desaparece misteriosamente para uma reunião de mudança emergencial.

Neste artigo, entraremos no interior dessas duas representações numéricas, entenderemos sua origem, formato interno, funcionamento, vantagens, riscos, opções de compilação e usos práticos. Também veremos por que dois campos aparentemente iguais podem reagir de maneira diferente ao receber o mesmo valor.


Bellacosa Mainframe e uma visão sobre numericos comp

1. Antes de tudo: o que significa COMP?

Em COBOL, a cláusula USAGE informa como um dado será representado internamente na memória.

Quando declaramos:

05 WS-IDADE PIC 9(3).

o uso padrão normalmente é DISPLAY. Isso significa que cada dígito é armazenado como um caractere.

O valor 123, em ambiente EBCDIC, poderá ocupar três bytes:

F1 F2 F3

Cada byte representa um caractere numérico.

Porém, computadores não realizam sua aritmética interna pensando em caracteres. O processador trabalha com bits, palavras, registradores e representações binárias.

As formas COMP, abreviação de COMPUTATIONAL, foram criadas justamente para permitir representações internas mais apropriadas ao processamento.

No universo IBM COBOL, encontramos tradicionalmente:

COMP ou COMP-4  = binário
COMP-1          = ponto flutuante de precisão simples
COMP-2          = ponto flutuante de precisão dupla
COMP-3          = decimal compactado
COMP-5          = binário nativo

No Enterprise COBOL para z/OS, BINARY, COMP e COMP-4 são sinônimos. Já COMP-5 representa o chamado native binary, ou binário nativo. (IBM)

Essa semelhança entre COMP-4 e COMP-5 é precisamente a origem de boa parte da confusão.

Ambos guardam números em formato binário.

Ambos podem ocupar 2, 4 ou 8 bytes.

Ambos podem ser usados em cálculos rápidos.

Mas eles não obedecem exatamente às mesmas regras de capacidade e truncamento.


Bellacosa Mainframe comp-4 versus comp-5

2. O que é COMP-4?

COMP-4, também escrito como COMPUTATIONAL-4, é sinônimo de BINARY no COBOL da IBM.

Estas declarações têm essencialmente o mesmo significado:

05 WS-VALOR PIC S9(9) BINARY.
05 WS-VALOR PIC S9(9) COMP.
05 WS-VALOR PIC S9(9) COMP-4.

No z/OS, os dados binários são armazenados em complemento de dois, com organização big-endian. O bit de sinal operacional fica associado ao lado mais significativo da representação. (IBM)

O tamanho físico do campo depende da quantidade de dígitos declarada no PICTURE:

Dígitos no PICTURETamanho
1 a 42 bytes
5 a 94 bytes
10 a 188 bytes

Portanto:

05 WS-A PIC S9(4) COMP-4.

ocupa 2 bytes.

05 WS-B PIC S9(9) COMP-4.

ocupa 4 bytes.

05 WS-C PIC S9(18) COMP-4.

ocupa 8 bytes. (IBM)

2.1 A grande característica do COMP-4

Embora o campo seja armazenado em binário, a cláusula PICTURE continua participando de sua semântica COBOL.

Veja:

05 WS-NUMERO PIC 9(4) COMP-4.

Fisicamente, o compilador reserva 2 bytes.

Dois bytes sem sinal poderiam representar valores de:

0 até 65535

Entretanto, o PICTURE 9(4) descreve formalmente um número de quatro dígitos:

0 até 9999

Aqui começa o drama.

O recipiente físico possui capacidade maior que a capacidade decimal descrita no PICTURE.

O que acontece quando tentamos armazenar 12345?

A resposta depende da operação realizada e, principalmente, da opção de compilação TRUNC.

É por isso que COMP-4 não deve ser entendido apenas como “um inteiro de 16 bits”. Ele é um item binário COBOL cujo comportamento também pode ser influenciado pela descrição decimal do PICTURE.


3. O que é COMP-5?

COMP-5 é o formato chamado pela IBM de native binary.

Exemplo:

05 WS-RETORNO PIC S9(4) COMP-5.

Fisicamente, esse campo também ocupa 2 bytes.

A diferença fundamental é que um item COMP-5 pode utilizar toda a capacidade de seu recipiente binário, em vez de ficar limitado à magnitude sugerida pela quantidade de noves do PICTURE.

A documentação da IBM explica que os itens COMP-5 podem armazenar valores até a capacidade da representação nativa de 2, 4 ou 8 bytes. Quando um valor é movido para um COMP-5, o truncamento ocorre conforme o tamanho físico binário, e não conforme o limite decimal indicado pelo PICTURE. (IBM)

Considere:

05 WS-NUMERO PIC 9(4) COMP-5.

O PICTURE tem quatro noves, mas o campo ocupa 2 bytes sem sinal.

Assim, sua capacidade binária é:

0 até 65535

E não apenas:

0 até 9999

Para um campo com sinal:

05 WS-NUMERO PIC S9(4) COMP-5.

os 2 bytes em complemento de dois permitem:

-32768 até +32767

O campo tornou-se, na prática, um inteiro binário de 16 bits.

O PICTURE ainda existe e continua sendo importante para regras sintáticas, edição, escalas decimais e operações COBOL, mas ele não limita a magnitude armazenável da mesma forma que ocorre com um binário comum submetido às regras tradicionais de truncamento.


4. A diferença em uma frase

Podemos resumir assim:

COMP-4 é um campo binário que normalmente respeita a semântica decimal definida pelo PICTURE; COMP-5 é um campo binário que utiliza a capacidade física inteira de seus 2, 4 ou 8 bytes.

Ou, no dialeto Bellacosa Mainframe:

No COMP-4, o gerente funcional chamado PICTURE ainda tenta controlar o orçamento. No COMP-5, o hardware assume a operação e utiliza todos os bits disponíveis.


5. Origem e história

O uso de representações computacionais acompanha o COBOL há décadas. Termos como COMPUTATIONAL, COMP-1, COMP-2, COMP-3 e COMP-4 surgiram em implementações históricas para representar dados em formatos adequados às arquiteturas dos computadores.

COMP-4 consolidou-se no COBOL IBM como sinônimo de BINARY.

COMP-5 surgiu posteriormente no COBOL de host IBM como uma forma explícita de representar um inteiro binário nativo, especialmente útil em interoperabilidade, interfaces de sistema e situações em que a capacidade completa da palavra binária deveria ser preservada.

A documentação de migração da IBM identifica COMP-5 como um tipo que foi novo no COBOL de host e as tabelas de palavras reservadas mostram COMP-5 e COMPUTATIONAL-5 como palavras reservadas a partir do COBOL for OS/390 & VM Version 2 Release 2, produto disponibilizado em 2000. (IBM)

Isso não significa que o conceito de inteiro nativo tenha nascido no ano 2000. Sistemas, linguagens e APIs já trabalhavam com inteiros binários muito antes disso.

O que aconteceu foi a formalização de uma maneira específica e explícita de declarar esse comportamento no COBOL de host IBM.

Antes disso, programadores dependiam mais fortemente de opções como NOTRUNC, comportamentos particulares de compiladores antigos ou convenções locais. Na migração para compiladores modernos, esses detalhes tornaram-se perigosos, pois códigos antigos às vezes armazenavam no campo binário valores maiores do que o PICTURE aparentemente permitia.

COMP-5 oferece uma declaração mais clara:

— Este campo não é apenas um número COBOL com representação binária. Ele é um recipiente binário nativo, e todos os seus bits importam.


6. Formato interno

6.1 Complemento de dois

Campos binários com sinal usam normalmente complemento de dois.

Em 16 bits:

0000 0000 0000 0001 = +1
0000 0000 0000 0010 = +2
0111 1111 1111 1111 = +32767
1000 0000 0000 0000 = -32768
1111 1111 1111 1111 = -1

A vantagem do complemento de dois é que o processador consegue realizar adições e subtrações com circuitos relativamente simples.

Não existe um caractere separado para o sinal. O sinal está incorporado ao próprio padrão binário.

6.2 Big-endian no IBM Z

O IBM Z utiliza organização big-endian para esses dados.

O byte mais significativo aparece primeiro.

Por exemplo, o valor decimal 1000 é hexadecimal:

03E8

Em dois bytes big-endian:

03 E8

Já em uma máquina little-endian, a memória poderia aparecer como:

E8 03

Essa diferença é importantíssima ao trocar estruturas binárias entre plataformas.

Enviar diretamente um campo binário de um mainframe para um servidor Intel sem definir corretamente formato, tamanho e ordem dos bytes é uma excelente forma de transformar o número 1000 em alguma criatura matemática não autorizada pelo Banco Central.


7. Tamanhos e faixas práticas

7.1 Campos com sinal

PICTURE aproximadoBytesFaixa física do COMP-5
S9(1) a S9(4)2-32.768 a 32.767
S9(5) a S9(9)4-2.147.483.648 a 2.147.483.647
S9(10) a S9(18)8-9.223.372.036.854.775.808 a 9.223.372.036.854.775.807

7.2 Campos sem sinal

PICTURE aproximadoBytesFaixa física do COMP-5
9(1) a 9(4)20 a 65.535
9(5) a 9(9)40 a 4.294.967.295
9(10) a 9(18)80 a 18.446.744.073.709.551.615

Versões modernas do COBOL IBM passaram a permitir que itens COMP-5 sem sinal utilizem todos os 16, 32 ou 64 bits. A IBM registra que esse suporte completo está disponível no COBOL for OS/390 & VM V2R2 e nos compiladores Enterprise COBOL posteriores. (IBM)

Contudo, existe um cuidado importante: nem toda operação COBOL, literal, função ou campo receptor conseguirá manipular confortavelmente toda a faixa de um inteiro de 64 bits sem sinal.

O campo pode possuir a capacidade física, mas o restante do programa também precisa estar preparado para ela.

Um hangar pode comportar um dragão. Isso não significa que a porta da cozinha também comporte.


8. Exemplo passo a passo

Considere o programa:

       IDENTIFICATION DIVISION.
       PROGRAM-ID. TESTEC45.

       DATA DIVISION.
       WORKING-STORAGE SECTION.

       01  WS-COMP4-SIGNED       PIC S9(4) COMP-4 VALUE ZERO.
       01  WS-COMP5-SIGNED       PIC S9(4) COMP-5 VALUE ZERO.

       01  WS-COMP4-UNSIGNED     PIC 9(4) COMP-4 VALUE ZERO.
       01  WS-COMP5-UNSIGNED     PIC 9(4) COMP-5 VALUE ZERO.

       01  WS-VALOR-ENTRADA      PIC 9(5) VALUE 30000.

       01  WS-EDICAO             PIC -ZZ,ZZZ,ZZ9.

       PROCEDURE DIVISION.

           DISPLAY 'TESTE COMP-4 E COMP-5'.

           MOVE WS-VALOR-ENTRADA TO WS-COMP4-SIGNED
           MOVE WS-VALOR-ENTRADA TO WS-COMP5-SIGNED

           MOVE WS-COMP4-SIGNED TO WS-EDICAO
           DISPLAY 'COMP-4 SIGNED  : ' WS-EDICAO

           MOVE WS-COMP5-SIGNED TO WS-EDICAO
           DISPLAY 'COMP-5 SIGNED  : ' WS-EDICAO

           MOVE 60000 TO WS-COMP4-UNSIGNED
           MOVE 60000 TO WS-COMP5-UNSIGNED

           MOVE WS-COMP4-UNSIGNED TO WS-EDICAO
           DISPLAY 'COMP-4 UNSIGNED: ' WS-EDICAO

           MOVE WS-COMP5-UNSIGNED TO WS-EDICAO
           DISPLAY 'COMP-5 UNSIGNED: ' WS-EDICAO

           GOBACK.

Passo 1: observe o tamanho

Todos os quatro campos têm PIC 9(4) ou PIC S9(4).

Logo, todos ocupam 2 bytes.

Porém, sua interpretação não é idêntica.

Passo 2: campo com sinal

O valor 30000 cabe em um inteiro de 16 bits com sinal:

máximo = 32767

Ele também possui cinco dígitos decimais, apesar de o campo ter sido declarado como S9(4).

No COMP-5, o valor pode ser armazenado porque cabe nos 2 bytes.

No COMP-4, o comportamento poderá ser influenciado pela opção TRUNC porque o valor ultrapassa a magnitude de quatro dígitos descrita no PICTURE.

Passo 3: campo sem sinal

O valor 60000 cabe em 16 bits sem sinal:

máximo = 65535

Mas não cabe em PIC 9(4) se interpretarmos apenas a quantidade decimal de noves:

máximo decimal descrito = 9999

O COMP-5 utiliza a capacidade binária do campo e pode armazenar 60000.

O COMP-4 pode sofrer truncamento segundo a semântica COBOL e a opção de compilação utilizada.


9. O papel da opção TRUNC

A opção TRUNC é um dos pontos mais importantes para compreender campos binários no Enterprise COBOL.

As formas mais conhecidas são:

TRUNC(STD)
TRUNC(OPT)
TRUNC(BIN)

9.1 TRUNC(STD)

Procura preservar o comportamento definido pelo padrão COBOL, considerando a quantidade de dígitos do PICTURE.

Se um resultado armazenado em um campo binário ultrapassar a quantidade decimal descrita, poderá haver truncamento para aquela precisão.

Exemplo conceitual:

05 WS-NUM PIC 9(4) COMP-4.

Ao receber:

12345

o resultado poderá ser reduzido à capacidade decimal de quatro dígitos, dependendo da operação:

2345

9.2 TRUNC(OPT)

Permite otimizações, partindo da expectativa de que os valores usados pelo programa respeitam o PICTURE.

É normalmente uma boa escolha quando o código está corretamente definido e os campos não recebem valores maiores que os declarados.

Entretanto, não deve ser usado como desculpa para depender de conteúdo fora do contrato do campo.

9.3 TRUNC(BIN)

Faz com que itens binários sejam tratados de maneira mais próxima à sua capacidade física integral.

Um campo binário comum passa a se comportar, em diversos contextos, de forma semelhante a um COMP-5.

Porém, TRUNC(BIN) é uma opção global de compilação e pode gerar código adicional, afetando desempenho. A própria IBM recomenda, quando possível, manter TRUNC(OPT) e declarar especificamente como COMP-5 os campos que realmente precisam receber valores além da precisão decimal indicada no PICTURE. (IBM)

Essa é uma decisão arquitetural importante.

Compare:

TRUNC(BIN)

Pode alterar o tratamento dos itens binários do programa inteiro.

Enquanto:

05 WS-API-RETURN-CODE PIC S9(9) COMP-5.

declara explicitamente que apenas aquele campo precisa de semântica binária nativa.

É a diferença entre reforçar uma porta e transformar o prédio inteiro em um bunker.


10. Exemplo de compilação em JCL

Um JCL simplificado poderia ser:

//COBOL    EXEC PGM=IGYCRCTL,
// PARM='LIB,OBJECT,LIST,MAP,XREF,OPT(2),TRUNC(OPT)'
//STEPLIB  DD DISP=SHR,DSN=IGY.V6R5M0.SIGYCOMP
//SYSIN    DD DISP=SHR,DSN=USER.COBOL(TESTEC45)
//SYSLIN   DD DISP=SHR,DSN=&&OBJ,
//            UNIT=SYSDA,SPACE=(TRK,(1,1)),
//            DCB=(RECFM=FB,LRECL=80,BLKSIZE=0)
//SYSPRINT DD SYSOUT=*
//SYSUT1   DD UNIT=SYSDA,SPACE=(CYL,(1,1))
//SYSUT2   DD UNIT=SYSDA,SPACE=(CYL,(1,1))
//SYSUT3   DD UNIT=SYSDA,SPACE=(CYL,(1,1))
//SYSUT4   DD UNIT=SYSDA,SPACE=(CYL,(1,1))
//SYSUT5   DD UNIT=SYSDA,SPACE=(CYL,(1,1))
//SYSUT6   DD UNIT=SYSDA,SPACE=(CYL,(1,1))
//SYSUT7   DD UNIT=SYSDA,SPACE=(CYL,(1,1))

A opção relevante é:

TRUNC(OPT)

Se todos os campos binários precisassem utilizar a capacidade física integral, poderia ser usado:

TRUNC(BIN)

Entretanto, a prática recomendável é analisar o contrato dos dados.

Campos internos comuns, contadores e valores de negócio podem continuar como COMP, COMP-4 ou BINARY.

Campos provenientes de APIs, C, estruturas do sistema operacional ou interfaces externas podem ser declarados como COMP-5.


11. Onde COMP-4 costuma ser usado?

COMP-4 é útil em:

  • contadores;

  • índices auxiliares;

  • acumuladores inteiros;

  • cálculos sem casas decimais;

  • campos cuja faixa respeita claramente o PICTURE;

  • variáveis internas de desempenho;

  • estruturas legadas que já utilizam COMP ou BINARY.

Exemplo:

05 WS-CONTADOR-REGISTROS PIC 9(9) COMP-4 VALUE ZERO.

Incremento:

ADD 1 TO WS-CONTADOR-REGISTROS

Como o campo ocupa 4 bytes, o processador pode trabalhar eficientemente com operações binárias.


12. Onde COMP-5 costuma ser usado?

COMP-5 é especialmente útil em integração com:

  • programas escritos em C;

  • APIs do sistema operacional;

  • Language Environment;

  • CICS;

  • Db2;

  • estruturas binárias;

  • códigos de retorno;

  • tamanhos de buffers;

  • comprimentos;

  • ponteiros auxiliares;

  • interfaces entre linguagens;

  • copybooks gerados por ferramentas;

  • valores que utilizam toda a capacidade de 16, 32 ou 64 bits.

A documentação de interoperabilidade entre C e COBOL recomenda COMP-5 ou TRUNC(BIN) quando um parâmetro inteiro vindo de C puder conter um valor maior do que o permitido pela quantidade de dígitos do PICTURE COBOL. (IBM)

Exemplo:

01  LK-C-PARAMETERS.
    05 LK-BUFFER-LENGTH PIC 9(9) COMP-5.
    05 LK-RETURN-CODE   PIC S9(9) COMP-5.

Em C, campos equivalentes poderiam ser:

int buffer_length;
int return_code;

O objetivo é preservar a correspondência física com o inteiro utilizado pela outra linguagem.


13. COMP-4 e COMP-5 com casas decimais

É possível declarar:

05 WS-TAXA PIC S9(5)V99 COMP-4.

ou:

05 WS-TAXA PIC S9(5)V99 COMP-5.

Não existe ponto decimal armazenado.

O V é um ponto decimal implícito.

O valor:

123.45

é armazenado internamente como o inteiro escalado:

12345

O compilador sabe que existem duas casas decimais implícitas.

Entretanto, para valores monetários, COMP-3 costuma ser mais natural, previsível e compatível com a matemática decimal de negócios.

Exemplo:

05 WS-VALOR-MONETARIO PIC S9(9)V99 COMP-3.

Valores financeiros são expressos em base decimal. Usar decimal compactado reduz certas surpresas de conversão e preserva a precisão decimal esperada.

COMP-4 e COMP-5 brilham principalmente com inteiros, contadores, comprimentos, flags numéricas e interfaces de baixo nível.


14. Vantagens do COMP-4

Uso eficiente de memória

Um PIC S9(9) DISPLAY ocupa nove bytes.

Um PIC S9(9) COMP-4 ocupa quatro bytes.

Em milhões de registros ou grandes tabelas internas, essa diferença pode ser relevante.

Aritmética eficiente

Processadores trabalham naturalmente com valores binários. Contadores e cálculos inteiros podem ser executados eficientemente.

Compatibilidade histórica

COMP, COMP-4 e BINARY aparecem em uma enorme quantidade de sistemas COBOL existentes.

Intenção clara

A declaração mostra que o campo foi criado para processamento, e não para apresentação direta.


15. Desvantagens do COMP-4

Dependência das regras de truncamento

O campo físico pode armazenar um valor, mas o PICTURE pode declarar uma capacidade decimal menor.

Influência da opção TRUNC

Uma recompilação com opções diferentes pode revelar dependências escondidas no código legado.

Não é legível diretamente

Abrir um arquivo binário em um editor de texto não mostrará os dígitos de maneira compreensível.

Portabilidade

Tamanho, endianness e comportamento podem variar entre plataformas e implementações COBOL.

Risco em interfaces

Um programa externo pode preencher todos os bits, enquanto o programa COBOL espera um valor limitado pelo PICTURE.


16. Vantagens do COMP-5

Utiliza toda a capacidade binária

É ideal quando 2, 4 ou 8 bytes devem ser tratados como um verdadeiro inteiro binário.

Excelente para interoperabilidade

Facilita o mapeamento com inteiros de C, APIs, estruturas de sistema e interfaces técnicas.

Intenção explícita

O programador que lê o código entende que aquele campo pode ultrapassar a magnitude decimal indicada pelos noves do PICTURE.

Evita o uso global de TRUNC(BIN)

É possível aplicar a semântica de binário nativo apenas aos campos necessários.

Preserva valores externos

Reduz o risco de perder dígitos de um valor recebido por interface.


17. Desvantagens do COMP-5

Pode surpreender quem confia apenas no PICTURE

Um campo declarado como:

PIC 9(4) COMP-5

pode conter 60000.

Para um iniciante, isso parece uma violação das leis naturais do COBOL.

Pode causar problemas ao mover para DISPLAY

Considere:

05 WS-NATIVO PIC 9(4) COMP-5.
05 WS-TEXTO  PIC 9(4).

Se WS-NATIVO contiver 60000:

MOVE WS-NATIVO TO WS-TEXTO

o receptor possui apenas quatro posições.

O problema não estava no COMP-5. Estava no contrato inadequado do campo receptor.

Pode esconder incompatibilidades

Duas plataformas podem usar tamanhos ou ordem de bytes diferentes.

Não é a escolha padrão para dinheiro

Valores monetários e cálculos decimais normalmente ficam mais claros em COMP-3.


18. Como visualizar o conteúdo hexadecimal

Um pequeno programa pode redefinir o campo:

01  WS-BINARIO.
    05 WS-VALOR PIC S9(4) COMP-5.

01  WS-BINARIO-X REDEFINES WS-BINARIO.
    05 WS-BYTES PIC X(2).

Em compiladores modernos, funções intrínsecas podem ajudar:

MOVE 1000 TO WS-VALOR

DISPLAY 'VALOR: ' WS-VALOR
DISPLAY 'HEX  : ' FUNCTION HEX-OF(WS-BYTES)

A representação esperada para 1000 em dois bytes big-endian é:

03E8

Para -1, em complemento de dois:

FFFF

Esse tipo de teste é excelente para compreender copybooks, dumps e integrações.


19. Cuidados ao usar REDEFINES

Nunca presuma que um campo binário pode ser interpretado como texto.

Isto:

01 WS-CAMPO.
   05 WS-NUMERO PIC S9(9) COMP-5.

01 WS-TEXTO REDEFINES WS-CAMPO.
   05 WS-CARACTERES PIC X(4).

não converte o número em texto.

Ele apenas oferece outra visão dos mesmos quatro bytes.

Se WS-NUMERO contém 123, WS-CARACTERES não conterá os caracteres:

"0123"

Ele conterá os bytes binários:

00 00 00 7B

REDEFINES não converte.

REDEFINES não formata.

REDEFINES não pergunta se você tem certeza.

Ele apenas remove a tampa do reator nuclear.


20. Boas práticas para o programador padawan

20.1 Escolha o tipo pela função

Use DISPLAY quando o dado for principalmente texto, entrada ou saída humana.

Use COMP-3 para dinheiro e cálculos decimais exatos.

Use COMP-4 ou BINARY para contadores e números inteiros que respeitam a faixa declarada.

Use COMP-5 para inteiros nativos e interfaces que exigem toda a capacidade binária.

20.2 Declare a faixa real quando possível

Embora isto seja permitido:

05 WS-LENGTH PIC 9(4) COMP-5.

pode ser mais claro declarar:

05 WS-LENGTH PIC 9(5) COMP-5.

se o valor esperado pode alcançar 65535.

A declaração deve comunicar a intenção humana, não apenas satisfazer o compilador.

20.3 Conheça a opção TRUNC

Nunca analise um programa com campos binários sem verificar as opções de compilação.

Procure no listing:

TRUNC(STD)
TRUNC(OPT)
TRUNC(BIN)

20.4 Não copie binário diretamente entre plataformas

Defina:

  • número de bytes;

  • presença de sinal;

  • ordem dos bytes;

  • escala decimal;

  • faixa permitida;

  • tratamento de overflow.

20.5 Use campos de edição no DISPLAY

Evite:

DISPLAY WS-COMP5

Prefira:

MOVE WS-COMP5 TO WS-EDITADO
DISPLAY WS-EDITADO

Exemplo:

05 WS-EDITADO PIC -ZZZ,ZZZ,ZZ9.

20.6 Teste os limites

Para 2 bytes com sinal, teste:

-32768
-32767
-1
0
1
32766
32767
32768

Para 2 bytes sem sinal, teste:

0
1
9999
10000
32767
32768
65535
65536

Os bugs mais interessantes não moram no valor médio.

Eles vivem na fronteira, fumando cigarro e esperando o batch de fechamento.


21. Curiosidades

COMP nem sempre significa binário em todas as plataformas

No Enterprise COBOL para z/OS, COMP é equivalente a BINARY.

Entretanto, em outras famílias e ambientes históricos, aliases podem variar. No IBM i, por exemplo, a documentação tradicional associa COMP-4 a BINARY, enquanto outros nomes computacionais podem refletir convenções específicas da plataforma. (IBM)

Portanto, nunca transporte conhecimento entre compiladores sem consultar a documentação daquele ambiente.

O PICTURE não determina sozinho o tamanho em bytes

Nos campos binários, faixas de dígitos são agrupadas:

1 a 4 dígitos  = 2 bytes
5 a 9 dígitos  = 4 bytes
10 a 18 dígitos = 8 bytes

Assim:

PIC 9(5) COMP-4

e:

PIC 9(9) COMP-4

ocupam ambos quatro bytes.

Um único nove pode custar dois bytes extras

Compare:

PIC 9(4) COMP-4

Dois bytes.

PIC 9(5) COMP-4

Quatro bytes.

Apenas um nove adicional fez o campo atravessar a fronteira entre halfword e fullword.

COMP-5 é comum em código gerado

Tradutores, preprocessadores e ferramentas de integração podem gerar campos COMP-5 porque precisam mapear tamanhos, comprimentos e códigos de retorno de maneira previsível.

A própria IBM informa que o coprocessador CICS usa tipos COMP-5 em situações nas quais o truncamento não deve ocorrer. (IBM)


22. Easter egg do data center

Diz a lenda que, em algum sistema bancário criado em 1997, existe a seguinte declaração:

05 WS-TAMANHO PIC 9(4) COMP.

Durante vinte anos, o campo recebeu valores menores que 9999.

Então uma modernização aumentou o buffer para 32000.

O programa continuou funcionando porque o compilador antigo, as opções históricas e os caminhos de execução permitiam que o valor sobrevivesse dentro dos 2 bytes.

Anos depois, alguém recompilou o programa com um compilador moderno e outra opção TRUNC.

O valor 32000 voltou da operação transformado em algo inesperado.

Sete reuniões foram marcadas.

Três fornecedores foram acusados.

Uma API REST foi criada sem necessidade.

Um arquiteto sugeriu Kubernetes.

Até que uma programadora júnior abriu o listing e perguntou:

— Por que este campo é PIC 9(4) se recebe 32000?

O silêncio que se seguiu foi registrado pelo SMF como consumo anormal de CPU emocional.


23. Comparação final

CaracterísticaCOMP-4COMP-5
Nome conceitualBinárioBinário nativo
Sinônimo de BINARYSimNão exatamente
RepresentaçãoComplemento de doisComplemento de dois
Tamanhos comuns2, 4 ou 8 bytes2, 4 ou 8 bytes
Capacidade ligada ao PICTURENormalmente, simCapacidade física do campo
Influência de TRUNCSimNão da mesma maneira
Bom para contadoresSimSim
Bom para integração com CPossível, com cuidadosRecomendado
Usa todos os bitsDepende das regras e opçõesSim
Clareza para valores nativosMenorMaior
Melhor escolha para dinheiroNormalmente nãoNormalmente não
Risco principalTruncamento inesperadoValor maior que o receptor espera

24. Conclusão

COMP-4 e COMP-5 não são apenas dois nomes misteriosos encontrados em copybooks antigos.

Eles representam dois contratos diferentes entre o programa COBOL e a memória.

COMP-4, equivalente a BINARY, armazena números em formato binário, mas continua ligado à descrição decimal do PICTURE e às regras de truncamento escolhidas na compilação.

COMP-5 declara que o campo deve ser tratado como um inteiro binário nativo, utilizando toda a capacidade física de seus 2, 4 ou 8 bytes.

O padawan precisa guardar cinco ensinamentos:

  1. COMP-4 é sinônimo de BINARY.

  2. COMP-5 utiliza a capacidade integral do recipiente binário.

  3. O tamanho depende da quantidade de dígitos do PICTURE.

  4. A opção TRUNC pode alterar o comportamento de campos binários comuns.

  5. Nunca escolha um tipo apenas porque ele “parece mais rápido”.

Escolha-o porque compreende o contrato, a origem do dado, sua faixa, seu destino e a forma como será processado.

No mainframe, um campo numérico nunca é apenas um campo numérico.

Ele é um acordo diplomático entre o COBOL, o compilador, o processador, o copybook, a plataforma externa e aquele programa de 1998 que ninguém recompila porque o último profissional que entendia o código se aposentou e agora cria orquídeas no interior de Minas Gerais.

E essa, jovem padawan, é a verdadeira diferença entre conhecer a sintaxe e compreender o sistema.


Vagner Renato Bellacosa, IBM Champion e especialista em IBM Mainframe
IBM Z17 SYSTEM ONLINE
Sobre o autor

Vagner Renato Bellacosa

IBM Champion 2026 • Especialista em IBM Mainframe

Vagner Renato Bellacosa trabalha com IBM Mainframe desde 1988 , é IBM Champion e especialista em COBOL, CICS, Db2, z/OS e IBM Z. Compartilha experiências profissionais, conhecimento técnico, história da computação e práticas do universo mainframe para aproximar novas gerações das tecnologias que sustentam empresas, bancos e governos ao redor do mundo.

IBM Champion IBM Z COBOL CICS Db2 z/OS Mainframe desde 1988
GitHub LinkedIn
Inicializando conteúdo...