CICS BMS Maps: Complete Guide to Basic Mapping Support (2026)

Introduction: Why BMS Is Still Essential for Mainframe CICS Developers
Long before web browsers, smartphones, and REST APIs, enterprise transactions happened on 3270 terminals — green-screen displays connected to mainframes. CICS still powers billions of transactions daily on these same 3270 sessions, and the technology that paints those screens and reads user input is called Basic Mapping Support (BMS). Even as modern CICS supports web services, RESTful APIs, and JSON, the overwhelming majority of existing CICS COBOL applications use BMS for their terminal interfaces — and those applications will be in production for decades.
This guide teaches BMS from the ground up: how to write mapset definitions, how the symbolic description map becomes a COBOL copybook, and how SEND MAP and RECEIVE MAP drive the screen I/O cycle in a pseudo-conversational program.
The Three BMS Macro Levels
BMS screens are defined using three nested assembler macros:
DFHMSD — Mapset definition (outermost). Defines the load module name, the terminal type (TYPE=MAP for the physical module, TYPE=DSECT for the COBOL copybook), and global attributes like screen size.
DFHMDI — Map definition. Defines one screen within the mapset: its position on the physical screen (LINE, COLUMN), its size, and its name.
DFHMDF — Field definition. Defines one field within a map: its position, length, initial value, and attributes (protected/unprotected, bright/normal/dark, numeric, etc.).
Here is a minimal example that defines a mapset named EMPIMAPS containing one map named EMPIMAP:
EMPIMAPS DFHMSD TYPE=MAP, X
LANG=COBOL, X
MODE=INOUT, X
TERM=3270-2, X
TIOAPFX=YES, X
STORAGE=AUTO
EMPIMAP DFHMDI SIZE=(24,80), X
LINE=1, X
COLUMN=1
*── Title line ──────────────────────────────────────────────────────
DFHMDF POS=(1,25), X
ATTRB=(PROT,NORM), X
LENGTH=30, X
INITIAL='EMPLOYEE INQUIRY SCREEN'
*── Employee number prompt ──────────────────────────────────────────
DFHMDF POS=(5,2), X
ATTRB=(PROT,NORM), X
LENGTH=16, X
INITIAL='EMPLOYEE NUMBER:'
EMPNO DFHMDF POS=(5,19), X
ATTRB=(UNPROT,NORM,IC), X
LENGTH=6
*── Name display (output only) ──────────────────────────────────────
DFHMDF POS=(7,2), X
ATTRB=(PROT,NORM), X
LENGTH=5, X
INITIAL='NAME:'
EMPNAME DFHMDF POS=(7,8), X
ATTRB=(PROT,BRT), X
LENGTH=30
*── Message line ─────────────────────────────────────────────────────
MSG DFHMDF POS=(23,2), X
ATTRB=(PROT,BRT), X
LENGTH=77
*── Instruction line ─────────────────────────────────────────────────
DFHMDF POS=(24,2), X
ATTRB=(PROT,NORM), X
LENGTH=45, X
INITIAL='PF3=RETURN ENTER=SEARCH CLEAR=RESET'
DFHMSD TYPE=FINAL
ENDAssembling the Mapset: Physical Map and Symbolic Map
The mapset source is assembled twice — once to produce the physical map (load module installed in CICS) and once to produce the symbolic description map (COBOL DSECT copybook used by your program).
//ASSEMBLE EXEC PGM=ASMA90,
// PARM='DECK,NOOBJECT'
//SYSLIB DD DSN=SYS1.MACLIB,DISP=SHR
// DD DSN=CICSTS56.CICS.SDFHMAC,DISP=SHR
//SYSIN DD DSN=your.BMS.SOURCE(EMPIMAPS),DISP=SHR
//SYSPRINT DD SYSOUT=*
//SYSPUNCH DD DSN=your.OBJ.LIBRARY(EMPIMAPS),DISP=SHRThe physical map load module is then link-edited and installed as a MAPSET resource in the CSD. The symbolic map DSECT is copied into a copybook library (e.g., your.COPYLIB(EMPIMAP)) and referenced in your COBOL program's WORKING-STORAGE.
The Symbolic Description Map: What Your COBOL Program Sees
When you assemble with TYPE=DSECT, BMS generates a COBOL level-01 structure for each map. For the EMPIMAP map above, the generated copybook looks approximately like this (names follow the BMS naming conventions):
01 EMPIMAPO. *> Output map (sending data to screen)
02 FILLER PIC X(12).
02 EMPNOL PIC S9(4) COMP.
02 EMPNOA PIC X. *> Attribute byte for EMPNO
02 EMPNOO PIC X(6). *> Output: EMPNO field data
02 EMPNAMEL PIC S9(4) COMP.
02 EMPNAMEA PIC X.
02 EMPNAMEO PIC X(30).
02 MSGL PIC S9(4) COMP.
02 MSGA PIC X.
02 MSGO PIC X(77).
01 EMPIMAPO REDEFINES EMPIMAPO. *> Input map (receiving data from screen)
02 FILLER PIC X(12).
02 EMPNOL PIC S9(4) COMP. *> Length of data typed
02 EMPNOF PIC X. *> Flag byte
02 EMPNOI PIC X(6). *> Input: data typed by user
02 EMPNAMEL PIC S9(4) COMP.
02 EMPNAMEF PIC X.
02 EMPNAMEI PIC X(30).
02 MSGL PIC S9(4) COMP.
02 MSGF PIC X.
02 MSGI PIC X(77).The naming convention uses suffixes:
- L — length of data received/sent for this field
- A — attribute byte (modify at runtime to change field characteristics)
- O — output field (you move data here before SEND MAP)
- I — input field (CICS populates this after RECEIVE MAP)
- F — flag byte on input map (contains the Modified Data Tag and cursor information)
In WORKING-STORAGE, you declare the map using the copybook name, and both EMPIMAPO (output) and EMPIMAPI (input, via REDEFINES) are available:
WORKING-STORAGE SECTION.
COPY DFHBMSCA. *> BMS attribute constants (DFHBMUNP, DFHBMPROT, etc.)
COPY DFHAID. *> AID key constants
COPY EMPIMAP. *> Your generated symbolic mapEXEC CICS SEND MAP — Writing to the Screen
SEND MAP transfers the contents of your symbolic output map to the 3270 terminal. You populate the output fields (the O-suffix fields) and then issue the command.
*── Populate output fields ──────────────────────────────────────
MOVE WS-EMPLOYEE-NUMBER TO EMPNOO
MOVE WS-EMPLOYEE-NAME TO EMPNAMEO
MOVE SPACES TO MSGO
*── Send the map to the terminal ────────────────────────────────
EXEC CICS SEND MAP('EMPIMAP')
MAPSET('EMPIMAPS')
FROM(EMPIMAPO)
DATAONLY
RESP(WS-RESP)
RESP2(WS-RESP2)
END-EXEC.Key SEND MAP options:
| Option | Meaning |
|---|---|
| MAP | Name of the map (4-8 chars) |
| MAPSET | Name of the mapset load module |
| FROM | The output area (symbolic output map) |
| ERASE | Erase entire screen before writing |
| DATAONLY | Send data only (do not re-send field attributes/labels) |
| MAPONLY | Send field attributes and labels only (no data) |
| CURSOR | Position cursor at a specific location |
| ALARM | Sound the terminal alarm |
For the first send (initial display), use ERASE to clear the screen and paint all labels and attributes. For subsequent re-sends (after user input), use DATAONLY to avoid re-transmitting the static labels — this reduces line traffic and improves performance.
*── First time: erase and paint everything ──────────────────────
EXEC CICS SEND MAP('EMPIMAP')
MAPSET('EMPIMAPS')
FROM(EMPIMAPO)
ERASE
CURSOR
RESP(WS-RESP)
END-EXEC.EXEC CICS RECEIVE MAP — Reading User Input
After the terminal user types data and presses an AID key (Enter, PF1-PF24, etc.), CICS holds the task. When the user returns to the program on the next pseudo-conversational invocation, RECEIVE MAP reads the modified fields from the terminal into the symbolic input map:
EXEC CICS RECEIVE MAP('EMPIMAP')
MAPSET('EMPIMAPS')
INTO(EMPIMAPI)
RESP(WS-RESP)
RESP2(WS-RESP2)
END-EXEC.
*── Now read what the user typed ────────────────────────────────
MOVE EMPNOI TO WS-SEARCH-KEY.
IF EMPNOL = ZERO
MOVE 'PLEASE ENTER AN EMPLOYEE NUMBER.' TO MSGO
PERFORM REDISPLAY-MAP
END-IF.Important: RECEIVE MAP only returns fields that were modified by the user (those with the MDT — Modified Data Tag — set). Fields the user did not type in will contain low-values. Always check the length field (e.g., EMPNOL) to determine whether the user entered data in a given field.
Modifying Field Attributes at Runtime
One of the most powerful BMS techniques is changing field attributes dynamically. You write to the attribute byte field (the A-suffix field) before SEND MAP. The DFHBMSCA copybook defines the attribute byte values:
COPY DFHBMSCA.
*> Key constants:
*> DFHBMUNP = Unprotected normal (user can type, normal intensity)
*> DFHBMPROT = Protected (user cannot type)
*> DFHBMBRY = Bright (highlighted)
*> DFHBMDAR = Dark (invisible — for passwords)
*> DFHBMFSE = Field Set (marks MDT so field is always sent)
*> DFHNEUTR = Neutral (unprotected, no MDT set)
*── Make EMPNO field bright to indicate an error ────────────────
MOVE DFHBMBRY TO EMPNOA.
*── Protect a field (make it output-only) ───────────────────────
MOVE DFHBMPROT TO EMPNAMEA.
*── Make a password field invisible ────────────────────────────
MOVE DFHBMDAR TO PASSWORDA.This technique lets a single map serve multiple display states — for example, highlighting fields that failed validation without requiring a separate map definition.
Cursor Positioning
The INSERT CURSOR (IC) attribute in the DFHMDF macro sets the default cursor position when the map is first sent. To move the cursor to a specific field at runtime, use the CURSOR option on SEND MAP with a numeric offset value, or use the symbolic approach: set the DFHBMFSE attribute and use CURSOR without a value (CICS will position the cursor at the field with IC set):
*── Move cursor to EMPNO field on re-send ───────────────────────
MOVE DFHBMUNP TO EMPNOA *> Unprotected, cursor will go here
EXEC CICS SEND MAP('EMPIMAP')
MAPSET('EMPIMAPS')
FROM(EMPIMAPO)
DATAONLY
CURSOR
END-EXEC.Alternatively, provide an absolute screen position to the CURSOR option:
EXEC CICS SEND MAP('EMPIMAP')
MAPSET('EMPIMAPS')
FROM(EMPIMAPO)
DATAONLY
CURSOR(338) *> Row 5, col 19 on an 80-column screen: (5-1)*80 + 19 = 338
END-EXEC.Common BMS Mistakes
Mistake 1: Sending DATAONLY on the first invocation. The first SEND MAP must use ERASE to paint the full screen. Using DATAONLY on the first send leaves garbage on the screen because the 3270 buffer is not initialised.
Mistake 2: Reading EMPNOI before checking EMPNOL. If the user did not modify a field, EMPNOI contains low-values (X'00'), not spaces. Always test EMPNOL > 0 before using input field data, or use INSPECT/MOVE to sanitise.
Mistake 3: Forgetting TIOAPFX=YES in DFHMSD. Without TIOAPFX=YES, the 12-byte TIOA prefix (the FILLER at the start of the symbolic map) is not generated, causing a 12-byte misalignment between physical and symbolic map data. Always include TIOAPFX=YES.
Mistake 4: Installing the wrong TYPE. The load module in CICS must be assembled with TYPE=MAP. The copybook must be assembled with TYPE=DSECT. Mixing these causes display corruption or ABEND.
Mistake 5: Not clearing output fields before SEND MAP. If a previous SEND MAP populated EMPNAMEO with a 30-character name and the next search returns a 15-character name, the rightmost 15 characters of the previous value remain on screen. Always MOVE SPACES to output fields before populating them.
Key Takeaways
BMS maps are the bridge between CICS COBOL programs and 3270 terminal users. DFHMSD defines the mapset container, DFHMDI defines each screen, and DFHMDF defines every field with its position, length, and initial attributes. At runtime, SEND MAP paints the screen and RECEIVE MAP captures user input. Dynamic attribute modification lets a single map serve multiple display states — error highlighting, protected fields, hidden passwords — without multiple map definitions.
To understand what happens after RECEIVE MAP (how to save state between pseudo-conversational invocations), see CICS COMMAREA. For the full CICS programming context, visit the CICS Mastery Course.
