1. O que são macros em Assembler

Uma macro é um nome que o assembler substitui por um bloco de instruções durante a montagem. Macros permitem usar serviços complexos do sistema operacional com uma única linha de código.

🦕 Analogia — macros como atalhos de teclado

Imagine que para abrir um arquivo você precisaria fazer 20 passos. Uma macro como OPEN encapsula esses 20 passos em uma chamada. O assembler "expande" a macro durante a montagem, gerando o código real. Você escreve OPEN (ENTRADA,(INPUT)) e o assembler gera as dezenas de instruções necessárias para montar o SVC call ao z/OS.

As macros padrão do z/OS estão nas bibliotecas SYS1.MACLIB e SYS1.MODGEN — por isso essas bibliotecas aparecem no JCL de compilação como SYSLIB.

2. A DCB — Data Control Block

A DCB é uma estrutura de dados que descreve um dataset: seu formato, tamanho de registro, organização e a DD do JCL que o representa. É declarada como um bloco de dados no programa:

Sintaxe geral da DCB: nome DCB DSORG=PS, Organização: PS=sequential, PO=partitioned MACRF=(GM), Macro form: G=GET/P=PUT, M=Move/L=Locate DDNAME=ddname, Nome da DD no JCL RECFM=FB, Formato: F=fixed, B=blocked, V=variable LRECL=80, Logical record length BLKSIZE=800, Block size EODAD=nomefim Rotina chamada no fim do arquivo (para GET) Exemplo — DCB de entrada (leitura): ENTRADA DCB DSORG=PS,MACRF=(GM),DDNAME=SYSIN, RECFM=FB,LRECL=80,BLKSIZE=800, EODAD=FIMFILE Exemplo — DCB de saída (escrita): SAIDA DCB DSORG=PS,MACRF=(PM),DDNAME=SYSPRINT, RECFM=FBA,LRECL=133,BLKSIZE=1330

O MACRF define como a macro acessa o dataset. GM = GET Move (copia o registro para um buffer), PM = PUT Move (copia do buffer para o dataset). Existe também GL/PL (Locate) que retorna o endereço do registro em vez de copiar — mais eficiente para registros grandes.

3. OPEN e CLOSE

Antes de usar um dataset, é preciso abri-lo com OPEN. Ao final, fechar com CLOSE:

Abrir para leitura e escrita: OPEN (ENTRADA,(INPUT),SAIDA,(OUTPUT)) Verificar se o OPEN foi bem-sucedido: TM ENTRADA+48,X'10' Testa bit DCBOPEN da DCB BZ ERROPEN Se zero, OPEN falhou Fechar os datasets: CLOSE (ENTRADA,,SAIDA)

O campo ENTRADA+48 é o offset do byte de status na DCB (DCBOPEN). Se o bit 0x10 estiver setado, o arquivo foi aberto com sucesso. Esse teste é importante em código de produção — um OPEN falhado e ignorado causará ABEND na primeira leitura.

4. GET e PUT

O GET lê um registro do dataset para um buffer; o PUT escreve do buffer para o dataset:

GET — ler próximo registro para buffer: GET ENTRADA,INREC Lê um registro de ENTRADA para INREC (se fim do arquivo, desvia para EODAD=FIMFILE) PUT — escrever registro do buffer para dataset: PUT SAIDA,OUTREC Escreve OUTREC no dataset SAIDA Buffers declarados com DS, tamanho = LRECL: INREC DS CL80 Buffer de entrada (LRECL=80) OUTREC DS CL133 Buffer de saída (LRECL=133)

5. Programa completo de I/O

Um programa que lê registros de SYSIN e copia para SYSPRINT com um prefixo:

COPYREC CSECT STM R14,R12,12(R13) BALR R12,0 USING *,R12 ST R13,SAVAREA+4 LA R13,SAVAREA * Abrir arquivos OPEN (ENTRADA,(INPUT),SAIDA,(OUTPUT)) * Loop de leitura LOOP GET ENTRADA,INREC Lê próximo registro * Montar linha de saída MVI OUTREC,C' ' ASA: espaço = avançar 1 linha MVC OUTREC+1(6),=CL6'DADO: ' Prefixo MVC OUTREC+7(80),INREC Copia registro de entrada PUT SAIDA,OUTREC Escreve na saída B LOOP Próximo registro * Fim do arquivo (EODAD) FIMFILE CLOSE (ENTRADA,,SAIDA) * Retorno L R13,SAVAREA+4 LM R14,R12,12(R13) SR R15,R15 BR R14 * DCBs ENTRADA DCB DSORG=PS,MACRF=(GM),DDNAME=SYSIN, RECFM=FB,LRECL=80,BLKSIZE=800, EODAD=FIMFILE SAIDA DCB DSORG=PS,MACRF=(PM),DDNAME=SYSPRINT, RECFM=FBA,LRECL=133,BLKSIZE=1330 * Dados SAVAREA DS 18F INREC DS CL80 OUTREC DS CL133 END COPYREC

6. Outras macros úteis

WTO — Write To Operator (console):

WTO 'PROGRAMA INICIADO' Mensagem literal WTO TEXT=MENSAGEM,MF=E Mensagem em área de trabalho MENSAGEM WTO 'PROCESSAMENTO CONCLUIDO',MF=L Lista form (pré-montada)

ABEND — finalizar com código de abend:

ABEND 100,DUMP Abend U0100 com dump de memória ABEND 200 Abend U0200 sem dump

GETMAIN / FREEMAIN — alocar e liberar memória dinâmica:

GETMAIN R,LV=4096 Aloca 4096 bytes; R1 ← endereço FREEMAIN R,LV=4096,A=(R1) Libera a memória

TIME — obter data e hora do sistema:

TIME DEC,TIMEWORK,LINKAGE=SYSTEM R0 ← hora em packed decimal (HHMMSSth) R1 ← data em packed decimal (0CYYDDDF) TIMEWORK DS 2F