HLASM Character Operations: MVC, MVZ, MVN, MVI, and TR
HLASM Character Operations: MVC, MVZ, MVN, MVI, and TR
Character operations move and transform bytes in memory. Unlike arithmetic instructions that work on registers, these SS (Storage-to-Storage) and SI (Storage-Immediate) instructions operate directly on memory fields. They are essential for data formatting, conversion, and manipulation.
MVC — Move Characters
MVC destination(length),source copies length bytes from source to destination:
MVC OUTPUT(80),INPUT Copy 80 bytes from INPUT to OUTPUT
MVC HEADING(10),=CL10'REPORT ' Move literal to fieldMVC copies from left to right, one byte at a time. This means overlapping moves work predictably:
* Propagate a single byte across a field (padding trick):
MVI FIELD,C' ' Move one space to byte 0
MVC FIELD+1(79),FIELD Copy byte 0 to bytes 1-79 (propagate)
* After: FIELD is 80 spaces
FIELD DS CL80The MVI+MVC propagation is a classic HLASM idiom for initialising a field.
MVC Length Limit
MVC can move up to 256 bytes in one instruction. For longer fields, use a loop or the MVCL instruction:
* Move a 500-byte field using two MVC instructions
MVC TARGET(256),SOURCE First 256 bytes
MVC TARGET+256(244),SOURCE+256 Remaining 244 bytesMVCL — Move Characters Long
MVCL moves up to 16MB using register pairs:
* Move 500 bytes with padding
LA 2,TARGET Destination address
LA 3,500 Destination length
LA 4,SOURCE Source address
LA 5,300 Source length (shorter than dest)
ICM 3,8,=X'40' Set pad character (space) in high byte of reg 3
MVCL 2,4 Move: pads with space if source shorter than destMVI — Move Immediate
MVI storage,immediate moves a single byte constant to storage:
MVI FLAG,X'01' Set flag byte to 1
MVI OUTPUT,C'*' Put asterisk in first byte of output
MVI SIGN,C'+' Set sign indicator
FLAG DS X
OUTPUT DS CL80
SIGN DS CMVZ — Move Zones
MVZ destination(length),source copies only the zone (high nibble) of each byte:
* Set zone bits of 5 bytes to EBCDIC zone (X'F')
MVZ NUMFIELD(5),=X'FFFFFFFFFFFFFFFF'
NUMFIELD DS ZL5MVZ is used with PACK/UNPK operations and sign manipulation.
MVN — Move Numerics
MVN destination(length),source copies only the numeric (low nibble) of each byte:
* Copy numeric portions only (useful for digit extraction)
MVN DEST(5),SOURCETR — Translate
TR field(length),table replaces each byte in the field with the byte at that position in the 256-byte translation table. This is the z/OS equivalent of a character-by-character lookup table:
* Convert lowercase EBCDIC to uppercase
UPRTAB DC 256X'00' Start: identity table would be better; use proper init
* (In practice, use a pre-built EBCDIC upper-case translation table)
TR INDATA(80),UPRTAB Translate 80 bytes using table
INDATA DS CL80Building a Translation Table
* EBCDIC to ASCII conversion table (256 bytes)
E2ATAB DS 0XL256
DC X'0001020304' ... first 5 bytes
* (full 256-byte table needed for complete conversion)TRT — Translate and Test
TRT field(length),table scans the field and stops at the first byte whose table entry is non-zero:
* Find first non-space character in a field
SCANTAB DC 256X'FF' All bytes signal "found"
ORG SCANTAB+X'40'
DC X'00' Space (X'40') = don't stop
ORG
*
LA 3,INDATA Point to input field
TRT INDATA(80),SCANTAB
BZ ALLSPACE Branch if no non-space found
* reg 1 = address of first non-space byte
* reg 2 = table value at that position
INDATA DS CL80TRT is commonly used for scanning records, finding delimiters, and parsing data.
Frequently Asked Questions
Q: Why does MVC copy left-to-right and why does this matter for overlapping moves?
MVC processes bytes sequentially from left (lowest address) to right. When the source and destination overlap and the source starts before the destination by exactly one byte, MVC propagates the first source byte across the entire destination — this is the classic initialisation idiom (MVI FIELD,C' ' followed by MVC FIELD+1(n-1),FIELD). If source and destination overlap with source starting after destination, some bytes might be overwritten before being read, giving unexpected results.
Q: What is the maximum length for SS instructions like MVC? Most SS instructions, including MVC, CLC, and TR, have a maximum length of 256 bytes (specified as a value from 1 to 256, encoded as 0 to 255 in the instruction). For fields longer than 256 bytes, use multiple instructions, the MVCL/CLCL long-form instructions, or a loop.
Q: When should I use TR vs a loop with CLI/MVI? TR is significantly faster than a byte-by-byte loop for translating long fields because the CPU can process multiple bytes per cycle. Use TR for format conversion (EBCDIC to ASCII, lowercase to uppercase), character class testing, and similar bulk byte transformations. Use CLI/MVI when translating single bytes or when the logic is too complex to fit in a 256-byte table.
Part of HLASM Mastery Course — Module 9 of 22.
