Vous êtes sur la page 1sur 140

Basic IBM Mainframe Assembly Language Programming

by

Kevin C. Kane

Copyright 2011 by Kevin C. Kane. All rights reserved. The author may be contacted at: kc.okane@gmail.com Department of Computer Science The University of Northern Iowa Cedar Falls, Iowa 50614-0507 http://www.omahadave.com

Graphics and production design by the Threadsafe Publishing & Railway Maintenance Co. Hyannis, Nebraska

Revision: 1.01 June 20, 2011 Text formatted using Open Office 3.3.0

Table of Contents
1 Preface ................................................................................................................9 2 Basic Numbering Systems................................................................................11 2.1 Binary..............................................................................................................11 2.2 Hexadecimal....................................................................................................11 3 Assembly Language Overview........................................................................15 3.1 Instruction Set Architecture.............................................................................15 3.2 Assembler........................................................................................................16
3.2.1 Assembly Language Statements...........................................................................17

3.3 Line Format and Naming.................................................................................18 3.4 Program Structure............................................................................................18 4 Z390 Emulator and Hello World....................................................................21 4.1 The z390 Portable Mainframe Project.............................................................21 4.2 Running the Emulator......................................................................................21 4.3 Hello World.....................................................................................................22 4.4 Running Hello World......................................................................................23 4.5 Examining Hello.prn.......................................................................................24 4.6 More Basic Assembly Language Examples ...................................................25 5 Basic Instruction Formats...............................................................................27 5.1 Operands..........................................................................................................27 5.2 Operand Notation............................................................................................27 5.3 Operand Semantics..........................................................................................28 5.4 Operand Formats.............................................................................................28
5.4.1 RR Format............................................................................................................28 5.4.2 RX Format............................................................................................................28 5.4.3 RS Format............................................................................................................29 5.4.4 SI Format..............................................................................................................29 5.4.5 SS Format.............................................................................................................29 5.4.5.1 One 8 Bit Length Field..................................................................................29 5.4.5.2 Two 4 Bit Length Fields................................................................................30

6 Basic Addressing...............................................................................................31 6.1 Explicit Addressing.........................................................................................31 6.2 Symbolic Addressing.......................................................................................33 6.3 Machine Language Formats............................................................................35
6.3.1 RR Machine Language Format.............................................................................35 6.3.2 RX Machine Language Format.............................................................................36 6.3.3 RS Machine Language Format.............................................................................37 6.3.4 SI Machine Language Format...............................................................................38 6.3.5 SS Machine Language Format..............................................................................39

7 Program Status Word (PSW)..........................................................................41 7.1 Layout..............................................................................................................41 7.2 Addressing modes...........................................................................................41


3

7.3 Condition Code................................................................................................41 7.4 Program Mask.................................................................................................41 7.5 Problem / Supervisor State Bit........................................................................42 7.6 Instruction Addressing.....................................................................................42 8 Flow of Control & Branch Instructions.........................................................43 8.1 Conditional Branching (BC, BCR)..................................................................43 8.2 Branch and Link Instructions..........................................................................46
8.2.1 BAL and BALR - Branch and Link .....................................................................46 8.2.2 Branch and Save - BAS and BASR......................................................................47 8.2.3 Branch Relative and Save - BRAS, BRASL.........................................................47

8.3 Looping Branch Instructions...........................................................................47


8.3.1 Branch Index Low, Equal, High - BXLE, BXH....................................................47 8.3.2 Branch on Count - BCT (RX) and BCTR (RR)....................................................49

9 Data Types.........................................................................................................51 9.1 Arithmetic Data...............................................................................................51


9.1.1 Packed Decimal and Zoned Decimal Format Data................................................51 9.1.2 Binary Integers and 2s Complement.....................................................................52 9.1.3 Nomenclature.......................................................................................................55 9.1.4 Threshold Binary Values......................................................................................55

10 Data Declarations...........................................................................................57 10.1 Declare Constant and Declare Storage (DC and DS)...................................57 10.2 Literals ..........................................................................................................59 11 Linkage............................................................................................................61 11.1 Linkage Registers..........................................................................................61 11.2 Save Area.......................................................................................................61 12 Assist Macro Input/Output............................................................................65 12.1 Input / Output using XREAD and XPRNT...................................................65 12.2 XDUMP.........................................................................................................66 12.3 XDECO/XDECI............................................................................................66 12.4 XHEXO/XHEXI............................................................................................67 13 Integer Arithmetic .........................................................................................69 13.1 Program to Add Numbers..............................................................................69 13.2 Analyzing the PRN File.................................................................................72 13.3 Debugging (XDUMP)...................................................................................75 13.4 Data Addressing Alternatives........................................................................79 13.5 More Addressing Alternatives.......................................................................79 13.6 Using Extended Mnemonics..........................................................................80 14 Other Binary Arithmetic Instructions..........................................................83 14.1 Subtraction.....................................................................................................83 14.2 Halfword Instructions....................................................................................83 14.3 Condition Codes After Binary Operations....................................................83 14.4 Overflows......................................................................................................83 14.5 Unsigned Arithmetic (AL, ALR, SL, SLR)..................................................84 14.6 Multiply (M, MR)..........................................................................................84
4

14.7 Divide (D, DR)..............................................................................................85 15 Character Instructions...................................................................................87 15.1 Basic Character Instructions.........................................................................87
15.1.1 Moving Characters (MVC).................................................................................87 15.1.2 Move Immediate (MVI).....................................................................................87 15.1.3 Compare Logical Characters (CLC)...................................................................88 15.1.3.1 Compare Logical Immediate (CLI)..............................................................89

15.2 Character Long Instructions..........................................................................89


15.2.1 Compare Logical Character Long (CLCL).........................................................89 15.2.2 Move Character Long (MVCL)..........................................................................90

15.3 Translate (TR) and Translate and Test (TRT)...............................................90 16 Miscellaneous Register Operations...............................................................95 16.1 Load (L).........................................................................................................95 16.2 Load (LR)......................................................................................................95 16.3 Store (ST)......................................................................................................95 16.4 Load Multiple (LM)......................................................................................95 16.5 Store Multiple (STM)....................................................................................95 16.6 Load and Test (LTR).....................................................................................96 16.7 Load Positive (LPR)......................................................................................96 16.8 Load Negative (LNR)....................................................................................96 17 Bit Operations.................................................................................................97 17.1 Boolean Instructions......................................................................................97
17.1.1 AND (N, NR, NI, NC)........................................................................................97 17.1.2 OR (O, OR, OI, OC)...........................................................................................97 17.1.3 Exclusive OR (X, XR, XI, XC)..........................................................................98

17.2 Complement LCR .........................................................................................98 17.3 Shift...............................................................................................................99


17.3.1 Logical (SRL, SRDL, SLL, SLDL) ...................................................................99 17.3.2 Arithmetic (SRA, SRDA, SLA, SLDA) ...........................................................100

17.4 Test Under Mask (TM) ...............................................................................100 17.5 Test and Set (TS) ........................................................................................101 18 Decimal Arithmetic......................................................................................101 18.1 PACK..........................................................................................................101 18.2 Add, Subtract, Zero and Add Positive (AP, SP, ZAP)................................101 18.3 Multiply Packed (MP).................................................................................102 18.4 Divide Packed (DP).....................................................................................102 18.5 EDIT (ED)...................................................................................................102 18.6 Miscellaneous Decimal Related Instructions..............................................103
18.6.1 UNPACK (UNPK)...........................................................................................103 18.6.2 Move Numerics (MVN)....................................................................................103 18.6.3 Move Zones (MVZ)..........................................................................................103

19 Multiple Base Registers................................................................................105 19.1 Base Register Addressing ...........................................................................105 20 System Macro Input/Output ......................................................................109 21 Converting Between Zoned, Packed and Binary ......................................111
5

22 Programming Examples..............................................................................117 22.1 Console Input/Output..................................................................................117 22.2 Random Numbers........................................................................................118 22.3 Convert Infix to Suffix ...............................................................................120 22.4 Bubble Sort a Table of Numbers.................................................................122 22.5 Search for Prime Numbers..........................................................................125 22.6 Print a String in Hexadecimal......................................................................126 22.7 Word Count Program..................................................................................128 23 General Instruction Set................................................................................135

Index of Figures
Figure 1 - A Hollerith/IBM Punched Card................19 Figure 2 Hello World................................................23 Figure 3 Assemble and run Hello World...................24 Figure 4 Macro expansion........................................25 Figure 5 Example program.......................................26 Figure 6 - RR Examples............................................31 Figure 7 Memory operand........................................32 Figure 8 - Example memory addressing....................32 Figure 9 - Example symbolic addressing..................34 Figure 10 - Explicit addressing.................................35 Figure 11 RR Machine Language Format.................36 Figure 12 RX Machine Language Format.................36 Figure 13 RS Machine Language Format..................37 Figure 14 SI Machine Language Format...................38 Figure 15 SS Machine Language Format..................39 Figure 16 BC example..............................................44 Figure 17 BXLE loop example.................................49 Figure 18 BCT loop example....................................50 Figure 19 Example DS/DC statements......................58 Figure 20 Literals......................................................59 Figure 21 SUBENTRY code.....................................62 Figure 22 XREAD example......................................65 Figure 23 ADD.MLC Step 1.....................................69 Figure 24 ADD.MLC Step 2.....................................70 Figure 25 ADD.MLC Step 3.....................................70 Figure 26 ADD.MLC Step 4.....................................71 Figure 27 ADD.MLC Step 5.....................................71 Figure 28 ADD.MLC Step 5.....................................72 Figure 29 ADD.MLC Step 5.....................................72 Figure 30 ADD.PRN................................................73 Figure 31 Add program exposed...............................76 Figure 32 - Dump format..........................................77 Figure 33 ADD1.MLC - Alternative 1......................80 Figure 34 ADD2.MLC - Alternative 2......................81 Figure 35 Loop example...........................................81 Figure 36 MVC Examples........................................87 Figure 37 MVI Examples..........................................88 Figure 38 CLC Examples .........................................88 Figure 39 TRT Table with ORG...............................91 Figure 40 TRT Example...........................................92 Figure 41 TRT Verifying Input................................93 Figure 42 Multiple Base Registers..........................106 Figure 43 QSAM Input/Output...............................111 Figure 44 Decimal Arithmetic................................113 Figure 45 Negative Decimal Arithmetic.................115 Figure 46 Example Execution.................................116 Figure 47 Console I/O using WTO/WTOR.............118 Figure 48 Random Numbers in C...........................119 Figure 49 Random Number Generator....................119 Figure 50 Convert Infix to Suffix............................122 Figure 51 Bubble Sort.............................................124 Figure 52 Search for Prime Numbers......................126 Figure 53 Print Hex Equivalent...............................129 Figure 54 Dictionary Program................................132 Figure 55 Over-Extended Instructions (humor).......137

Index of Tables
Table 1 Numbering Systems...........................................11 Table 2 Hex to Decimal Conversion................................12 Table 3 Conversion from Hex to Decimal.......................13 Table 4 Decimal to Hex Conversion................................13 Table 5 Condition Code after signed Add.......................44 Table 6 Mask settings after a signed add.........................44 Table 7 Decimal mask settings........................................45 Table 8 Decimal mask equivalents..................................45 Table 9 Extended mnemonics.........................................46 Table 10 Numeric data types...........................................51 Table 11 Example packed decimal numbers....................52 Table 12 Powers of two...................................................53 Table 13 Decimal value of a binary number....................53 Table 14 Binary nomenclature........................................56 Table 15 DS/DC Data Types...........................................58 Table 16 Linkage registers..............................................61 Table 17 Save area..........................................................62 Table 18 Conditions Codes.............................................83 Table 19 CC after logical add/subtract............................84 Table 20 General Instructions........................................135

1 Preface
The purposes of this book are:
1. 2.

to give the reader a basic understanding of the IBM mainframe architecture from the perspective of the instruction set architecture and to serve as an assembly language text for introductory college courses in computer organization.

Many computer architectures have come and gone in the past 50 years and only a few designs remain to this day. While most computer users are familiar with the ubiquitous Intel microprocessor line, few are aware of the other widely used architecture, the IBM mainframe. In recent years, as mainframe sales have grown rapidly and it is being increasingly deployed in large, mission critical applications, cloud computing, Linux and virtual hosting applications. Simultaneously, however, as the programmers who wrote the billions of lines of mainframe assembly code since the introduction of the 360 in 1964 begin to retire, the demand for programmers to maintain and develop new code is growing. This text seeks to address this need by giving the reader a basic understanding of the underlying mainframe architecture from the level of the instruction set. Similarly, as the x86 architecture has become an increasingly more complex collection of exceptions and special cases, the question of which assembly language architecture to teach in an introductory course in computer organization has arisen. In many cases this is solved by the use of simulators for non-existent, abstract RISC based architectures. This text, however, along with the portable, open sourced, Java based z390 emulator, seeks to provide a real world alternative. The current series of IBM mainframes (System z10) had its origins in the 1964 with the introduction of the IBM 360 Series of machines. This was a family of computers designed to meet a wide range of applications both scientific and commercial. The system was conceived as a series of compatible machines ranging from small basic machines to large, enterprise level configurations. The original architecture was based on a 24 bit address (16 MB address space) and 32 bit data. In its latest models, both 64 bit addressing and 64 bit data are supported. All models of the IBM mainframe, even the most recent, are fully backward compatible with the earliest of the 360 series. However, with each new generation, additional facilities and instructions were added. These are referred to as architecture levels. At present, there are three architecture levels named: ARCHLVL1 (ESA 390 systems), ARCHLVL2 (zSeries and System z9 machines), and ARCHLVL3 (System z10 machines). These reflect the additions to the original design which are, for the most part, consistent with the original intent. This book will deal mainly with the basic architecture for simplicity concentrating mainly on the original instruction formats.
9

The z/Architecture was introduced in 2000 and is represented by machines in the z9 and z10 families. It is a 64 bit CISC (complex instruction set computer) architecture with sixteen 64/32 bit general purpose registers, sixteen 64 bit floating point registers, sixteen bit access registers, and sixteen 64/32 bit control registers. Memory addressing is implemented as either 24, 31 or 64 bits although much legacy programming is in 24 bit mode. In this book will deal mainly with 31 bit addressing and the z390 framework in order to be compatible with the free z390 emulator and assembler:
http://www.z390.org/

Which corresponds to the definition as found in the IBM z/Architecture Principles of Operation, Document Number: SA22-7832-03 (05/04/04) presently to be found at:
http://publibz.boulder.ibm.com/cgi-bin/ bookmgr_OS390/BOOKS/DZ9ZR003/CCONTENTS

10

2 Basic Numbering Systems


2.1 Binary The IBM mainframe, as is the case with all other modern digital computers, uses an internal binary representation for numbers, characters, instructions, pointers and so forth. Binary numbering consist of only two digits: 0 and 1. When writing a number, each position, reading from right to left, represents a higher power of two as shown in Table 1. This table shows the equivalence between the first 16 binary, decimal, hexadecimal (base 16 - see below) numbers and the corresponding sum of the powers of 2. Any decimal integer can be represented exactly by a corresponding binary number. Each binary number is a sum of a series of values of powers of two. For example, the binary series which is equivalent to the decimal number 10 is:
1*23 (810) + 0*22 (410) + 1*21 (210) + 0*20 (110)

or, stated as a single number,


10102 Binary 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111 Decimal 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Hexadecimal 0 1 2 3 4 5 6 7 8 9 A B C D E F
3 3 2

Power of 2

20 21 21+20 22 22+20 22+21 2 +21+20 23 2 +20 23+21 23+21+20 23+22 23+22+20 23+22+21 2 +22+21+20

Table 1 Numbering Systems

2.2 Hexadecimal Internally, most modern computer memories are organized as a collection of 8 bit bytes. Representing the contents of bytes as binary numbers yields
11

inconveniently long sequences of 1s and 0s. However, noting that a byte consists of two 4 bit fields, we can represent the content of a byte in base 16. Since 16 is itself a power of two, conversion between base 16 and base 2 and vice versa is trivial. In base 16 we need 16 symbols to represent the digits of the numbering system (the equivalent of 010 through 1510). For the first 10 digits, we use the same symbols as the decimal numbering system (0 through 9). For digits above nine, representing the values 1010 through 1510, we use the upper (or lower) case letters A, B, C, D, E, and F.
Hex 0 1 2 3 4 5 6 7 8 9 A B C D E F Decimal Equivalent by Digit Position 0 268435456 536870912 805306368 1073741824 1342177280 1610612736 1879048192 2147483648 2415919104 2684354560 2952790016 3221225472 3489660928 3758096384 4026531840 8 0 16777216 33554432 50331648 67108864 83886080 100663296 117440512 134217728 150994944 167772160 184549376 201326592 218103808 234881024 251658240 7 0 1048576 2097152 3145728 4194304 5242880 6291456 7340032 8388608 9437184 10485760 11534336 12582912 13631488 14680064 15728640 6 0 65536 131072 196608 262144 327680 393216 458752 524288 589824 655360 720896 786432 851968 917504 983040 5 0 4096 8192 12288 16384 20480 24576 28672 32768 36864 40960 45056 49152 53248 57344 61440 4 0 256 512 768 1024 1280 1536 1792 2048 2304 2560 2816 3072 3328 3584 3840 3 0 16 32 48 64 80 96 112 128 144 160 176 192 208 224 240 2 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 1

Position

Table 2 Hex to Decimal Conversion

Each four bit binary number can be immediately converted to its hexadecimal equivalent by simple substitution. Thus, if you have a binary number such as:
000 0001 1010 1011 0010 0011 0111 1000

Using the values from Table 1, it can be represented in hex as:


000 0001 1010 1011 0010 0011 0111 1000 0 1 A B 2 3 7 8

Conversion from a hexadecimal (hex) number to its equivalent decimal notation, however, requires more work because there is a fundamental change in base. When you want the decimal equivalent of a hex number, you need to add the contribution of each hex digit. To do this, a table such as that in Table 2 is useful. It gives, for each hex digit position (up to an eight digit hex number), the contribution of that digit as expressed in decimal. So, if you have the hexadecimal number such as: 01 AB 23 78, it can be converted to decimal by adding the decimal equivalent contributions of each of the hex digits as shown in Table 3.
12

Conversion from decimal to hex can be done in several ways. The easiest, if you have Table 2, is to successively find the largest decimal value in the table and subtract it from your decimal number. The corresponding hex digit is retained as part of the answer. If you skip a hex position in the process, insert a zero in the skipped position. For example, if you have the decimal number: 123456789, this can be rendered in hex as shown in Table 4.
0 1 A B 2 3 7 8 0 16777216 10485760 720896 8192 768 112 8 27992184 Position 8 Position 7 Position 6 Position 5 Position 4 Position 3 Position 2 Position 1 Decimal equivalent of 01AB2378

Table 3 Conversion from Hex to Decimal

Of course, another method to convert between binary, decimal and hexadecimal is to use the programming mode of a calculator such as that which comes with Ubuntu.
123456789 6016277 773397 52501 3349 21 5 Subtract 117440512 hex digit 7 position 7 Subtract 5242880 hex digit 5 position 6 Subtract 720896 hex digit B position 5 Subtract 49152 hex digit C position 4 Subtract 3328 Hex digit D position 3 Subtract 16 hex digit 1 position 2 Subtract 5 hex digit 5 position 1 Result: 07 5B CD 15 Table 4 Decimal to Hex Conversion

13

14

3 Assembly Language Overview


3.1 Instruction Set Architecture In the original IBM S/360 architecture, there were six basic instruction formats and these are still the basis of many of the instructions in use today as well as the model for many of the newer formats. A program in memory consists of a series of instructions coded in binary. Each instruction consists of an opcode (operation code) which tells the CPU which instruction to execute followed by one or more operands which tell the CPU what data the instruction works upon. In the basic architecture, each instruction is either 2, 4 or 6 bytes long. The first byte is always the opcode. The opcode is a numeric value that indicates which instruction is to be executed. As a result, since there are 8 bits in a byte, the maximum number of unique opcodes is 256 (2 raised to the eighth power). In actual practice, not all possible codes were originally used. However, in newer implementations, two bytes are used for some opcodes and the total number of permissible opcodes is now very much larger than the original 256. Following the opcode is one or more (usually two) operand specifications. Each operand specification indicates if the operand is in memory, in a register or a constant. Registers are very high speed memory locations located in the CPU. There are two classes of registers: general purpose registers and floating point registers. The floating point registers are used to perform floating point calculations and are not discussed in this book. There are 16 general purpose registers. These are used mainly for integer calculations and for addressing. Originally, they were 32 bits in length but on more recent machines they are 64 bits long. Some instructions work only on the lower 32 of these bits while others work on all 64. For the most part, we will work only with 32 bits. The general purpose registers are addressed by a number between 0 and 15. These are the binary codes between 00002 (010) and 11112 (1510). In all instructions, a register operand is always specified in field of 4 bits. If an operand is in memory, the basic architecture uses an addressing scheme known as base/displacement addressing. In base/displacement addressing, the address of the operand in memory is calculated by adding the contents of a register with a constant called a displacement. Originally, displacements were always 12 bit unsigned numbers (in newer systems, 20 bit signed displacements are possible). The 12 bit displacements are always treated as positive numbers. They can range from 010 (0000 0000 00002 or 00016) to 409510 (1111 1111 11112 or FFF16).
15

The purpose of base/displacement addressing is to achieve program relocatability. That is, the ability to place a program anywhere in memory. If a program used actual memory address constants to specify operand addresses, it would always need to be loaded at the same place in memory. This would make it very difficult for a computer to run multiple programs at the same time because programs might compete for the same memory locations. Base/displacement addressing makes it possible to load a program anywhere in memory. Memory addresses are all calculated relative to the contents of the base register. Thus, when a program is loaded into memory, the base register is loaded with an absolute memory address usually near the starting point of the program. Since operand addresses are calculated relative to the base register, they will be correct if the base register is correct. If the program is placed somewhere else in memory, a different value will be loaded into the base register and the operands will be likewise relocated. Any register can be used as a base register except register zero. In addition to base/displacement, some instructions have what is called an index register. The contents of the index register are added along with the contents of the base register and the displacement to calculate an address. Index registers are useful for array manipulation where the base/displacement points to the start of an array and the index register is used to give an offset from this point into the array. However, if register zero is specified as an index register, it means there is no index register. Register zero never participates in address arithmetic. 3.2 Assembler It is technically possible (although very tedious) to write programs in binary or hexadecimal. In the very earliest days of computing, however, this was normally the case. To improve productivity, people soon developed a class of programs known as assemblers whose purpose it was to allow programmers to write in a symbolic language and leave the job of translating the symbolic code into binary to the assembler. Thus, when we write a program in assembly language, we use symbols for the instructions. Instead of coding an Add instruction as 5A16 we use the mnemonic symbol A. The assembler translates our symbolic representation into binary. Instead of coding a base and displacement, we use labels attached to data areas in our program. The assembler calculates and inserts the correct base and displacement. The end result is a binary coding of our program but with a lot less effort on our part. When we write in assembly language, each line usually consists of a single instruction to be executed. Compare this to a line of code written in a language such as C or C++ where a single line of code may require many instructions to be executed. For this reason, we say that assembly language is a low level language and C/C++ is a high level language. When we write in a high level language the compiler selects the instructions to execute. However, in many cases, we might be able to specify a more efficient
16

sequence of instructions. On the other hand, the number of lines of code a programmer does per day is invariant with regard to language used. So, a programmer working in a high level language will probably accomplish more per day than someone working in a low level language. Thus, generally speaking, high level languages increase programmer productivity but low level languages can increase program efficiency. The output of the assembler (or a compiler, for that matter) is a binary object module consisting of instructions and data. This module is nearly executable lacking only library routines and internal address linkages (for example, resolution of subroutine call addresses). To build a final executable module we employ a program known as the link editor or loader which resolves these and either creates an executable on disk or loads the executable into memory. (Note: an executable module on disk usually still requires some final adjustments as it is loaded into memory for execution.) 3.2.1 Assembly Language Statements There are basically four classes of statements in an assembly language program:
1.

Instruction statements. These are statements, one per line, which will be translated into machine language for execution at run time. All instructions have one or more operands, usually designating data in memory or registers upon which the instruction operates (for example, add the contents of one register to another). Each instruction statement results in machine code being generated in the run time module. Data Allocation statements (DS/DC). These are statements that tell the assembler to reserve memory in the run time module for data. The data may be uninitialized (DS statement - declare storage) or initialized (DC statement - declare constant). For the most part, each data allocation statement results in data areas being incorporated into the run time module Note: it is possible, in rare cases, that a DS or DC statement may, in fact, not generate any data as we will see in Figure 54 on page 132. This is not common, however. Assembler directives. These are statements that inform or direct the assembler. While these statements affect the way in which your machine language program is generated, they do not normally result the generation of code or data. The main assembler directive we will use are:
A. B. C. D. E. F. G. USING END EQU LTORG CSECT ORG PRINT - designate a base register. end of the source module. define one symbol to be the equivalent of another. - placement of literal pool. - start or continue control section. adjust location counter. - assembler print options.

2.

3.

4.

Macros statements. Macros are small, disk resident code modules that contain segments of frequently used code. Rather than write the code new each time, we insert the macros containing the code into our programs.
17

From the program level, macros look very much like instructions. Internally, macros may be a combination of instructions, data allocation statements and assembler directives but they may also contain statements in the macro language itself. Before your program is processed by the assembler, it is first read by the macro preprocessor. The macro preprocessor inserts the macros into your program and executes and macro commands written in the macro preprocessor language. 3.3 Line Format and Naming Historically, assembly language programs were punched on 80 column cards and followed a format consistent with that media. Although there may have been some relaxation in the format in recent years, most assembly programmers follow the original format to this day:
1. 2.

Labels begin in column one and are from one to eight characters in length The first character of a label is either a letter in the range A through Z, $, # or @. Characters after the first character may be any of the above as well as digits in the range 0 through 9. The mnemonic (short abbreviation) for the operation code or assembly directive begins in column ten. Operands, if any, begin in column sixteen and may not include embedded blanks except within quoted strings. After the operands and one blank, comments may be written. Comments may not extend beyond column 71. If column 1 one is an asterisk, the remainder of the line is a comment. If an operand is so long that it would extend beyond column 71, place a character (usually an X) in column 72 and continue the operand on column sixteen of the next line. There may be at most two continuation cards. Blank lines are ignored but are part of the overall line count.

3.

4.

5.

6. 7. 8. 9.

10.

3.4 Program Structure The basic structure of a program will be:


1.

Introductory assembler directives and register renaming macros such as:


PRINT NOGEN EQUREGS

The assembler directive (PRINT) determines what information the


18

assembler will show in its printout of your program. The EQUREGS is the name of a macro on disk whose contents will be inserted at this point. This macro tells the assembler that if you use symbols such as R0, R1, R3, ... that you mean 0, 1, 2, 3, ... Most programmers prefer to use R1, R2, etc. when specifying registers. Unless you specifically tell the assembler that R1 means 1, you can't do this. Macros are small, frequently used segments of code stored on disk for re-use.
2.

An entry linkage macro:


SUBENTRY

This macro establishes your base register and linkage to the calling program and performs a number of tedious housekeeping functions.
3.

The program code appears at this point followed by the exit macro
SUBEXIT

which returns to the calling program. Your program may have more than one instance of SUBEXIT.
4.

The data area. In an assembly language program you tell the assembler how much data to reserve for program use. Usually the data area consists of multiple labeled statements declaring what would be called variables in a high level languages. These can include binary variable, character strings, pointers, and others. Each of these statements causes the assembler to reserve a specific number of bytes in the run-time module. You may also specify initial values for data areas as well.

Figure 1 - A Hollerith/IBM Punched Card

19

20

4 Z390 Emulator and Hello World


4.1 The z390 Portable Mainframe Project The z390 portable mainframe macro assembler and emulator project is a Java based, GPL project to "...Enable z390 and zcobol users to compile, assemble, link, and execute mainframe COBOL and assembler problem state programs with minimum source code changes using Windows, Linux, and other platforms supporting the J2SE runtime...." (from the web site):
http://www.z390.org/

where the Java code for the project can be found. The examples in this text were developed using this package. To install the software, download the most recent setup.zip, unzip and execute the setup.exe file contained therein. The emulator can be run either in a graphical user window or from a command prompt. The results are the same but the examples used in this book were done in command prompt mode. 4.2 Running the Emulator There are several ways to run the emulator. You should consult the documentation for details. In this section we show how to run the emulator in a command prompt window. First, you need to add some information to your systems program search path. The purpose of this is so you can execute the emulator from any directory, not just the one containing the actual code. Go to:
Start | Settings | System | Advanced Settings

and click on the Environment Variables button. In the lower window, scroll down to the Path line, click it, then click the Edit button. You will see the current contents of the Path environment variable. Be careful, it may be all highlighted and this means that if you type something, you will be replacing the entire contents - do not do this. If you do, quickly hit cancel and start again. At the end of the values for the Path variable, add the following:
;C:\"Program Files"\"Automated Software Tools"\z390;

This assumes that you have installed the z390 emulator in the directory noted. Click OK and close the windows. Note: if you have a 64 bit version of Windows, the emulator may have been installed in
"Program Files (x86)" 21

and you will need to add (x86) to the "Program Files" in the above. Be careful that you type it exactly, including blanks. Close does not count. Next, locate your system's command prompt icon. This can usually be found in
Start | Programs | Accessories | Command Prompt

Alternatively, type cmd into the run box. A command window should appear. You will probably want to tailor this window so it is larger than its default size. Right click the top bar and the click Properties. In Properties, click Layout and adjust the window size, width and position. The Screen Buffer Size Height is the number of lines to remember at any given time. You probably want this to be at least double the screen height. The buffer width should be the same as the screen width. You may also want to adjust the colors if you prefer something other than white text on a black background. When finished, click OK. The prompt in the command window should identify the directory path to your default user directory. You will probably want to create a directory in which you will place your assembly language programs. To create a directory, type:
mkdir asmdir

where asmdir is the name you chose. Enter the directory with the command:
cd asmdir

4.3 Hello World Now it's time to write the usual Hello World program as shown in Figure 2. In the command window, start notepad with the command:
notepad hello.mlc

A window will open in which you can type your program and save it when done. You may want to leave this window open in the event you need to make corrections. Structurally, the first few lines of an assembly program deal with assembler directives and linkage: connecting your program with the program that called it. This involves saving the calling program's registers so they can be restored at exit, establishing a base register for your program and creating a save area. Normally this is done with macros. Macros are code segments stored on a system library designed to perform common, repetitive tasks and to simplify program development. Macros look like machine instructions but are directives to the assembler to insert and process code elements into you program. A typical macro can be from 3 to hundreds of lines long. As the macro is inserted into your program,
22

it may be tailored or altered by the macro preprocessor. The resulting code is referred to as the macro expansion. The z390 emulator provides a macro called SUBENTRY that establishes your program's linkage, save area and sets register 13 to be your initial base register. The directive PRINT NOGEN is a note to the assembler. It tells the assembler to display the names of the macros but not show the macro expansion itself. If omitted, the assembler will show the contents of the of the macro expansion (usually not very interesting).
1 2 HELLO 3 4 5 6 MSG 7 PRINT NOGEN SUBENTRY EQUREGS XPRNT MSG,L'MSG SUBEXIT DC C'Hello World!' END Figure 2 Hello World

Another macro, EQUREGS, causes the assembler to accept notation such as R1, R2, R3 and so forth as the equivalent of 1, 2, 3 and so forth. Most programmers prefer to refer to the general purpose registers as a number preceded by the letter R however this notation is not accepted by the assembler. The purpose of EQUREGS is to make codes such as R1 and so forth the equivalent of their number part. The program in Figure 2 writes the phrase Hello World returns to the operating system. Return is accomplished by the macro SUBEXIT. The program's output is done by the macro XPRNT, part of the Assist package of macros originally developed by Dr. John R. Mashey at the Computer Science Department of The Pennsylvania State University. We will use several of these in the examples in this text. They provide simplified access to common tasks and are useful for novice programmers. XPRNT prints data to the default output device (the screen for most users). It takes two arguments: the address of the data field to be printed and its length. In Figure 2, the address of the field to be printed is given as MSG and the length as L'MSG. L'MSG is assembler short hand that evaluates to the value of the length attribute of the label after the L' figure which, in this case, is 12 (note: all labels have a length attribute, usually the length of the memory reserved in the case of DS and DC statements). The assembler calculates the base and displacement necessary to address the label MSG. 4.4 Running Hello World Once you have typed and saved the program, assemble and execute it by typing the command:
assist hello.mlc

23

in the command prompt window. The assist command is the name of a Windows batch file in the emulator directory which runs the emulator with the Assist macro support feature enabled and then executes the result if the assembly was successful. The result should be several messages and the line Hello World! as shown in Figure 3 (note: some extraneous material at the end of longer lines has been cut). The assembler will create several files in your directory all with the file name hello but with different extensions. The file hello.prn (examined below) is the main assembler listing of your program. It contains error messages and a description of the machine language program created. Now modify the program and remove the PRINT NOGEN line and repeat the assist command. This will cause the macro expansions to appear. You will see the same messages in the command prompt window but there are other files.
C:\user>rem assemble, link, and exec ASSIST prgram hello.mlc.MLC C:\user>echo off 18:13:22 hello MZ390 START USING z390 V1.5.01b ON J2SE 1.6.0_18 18:13:22 hello MZ390 ENDED RC= 0 SEC= 0 MEM(MB)= 42 IO=681 18:13:22 hello LZ390 START USING z390 V1.5.01b ON J2SE 1.6.0_18 18:13:22 hello LZ390 ENDED RC= 0 SEC= 0 MEM(MB)= 15 IO=32 18:13:22 hello EZ390 START USING z390 V1.5.01b ON J2SE 1.6.0_18 Hello World! 18:13:22 hello EZ390 ENDED RC= 0 SEC= 0 MEM(MB)= 19 IO=21 INS=12 Figure 3 Assemble and run Hello World

4.5 Examining Hello.prn Look in the file hello.prn with the command:
more hello.prn

This is one of the output files from the assembler. It shows many things but for now, examine the area in the center of the display which will look something like Figure 4. In this figure, extraneous text to the left has been removed. What remains is the assembler's listing of your code and the expansion of the macros. The number is the line number as determined by the assembler. For each macro, you see it's invocation followed by it's expansion. The code in the macro expansion sections is preceded by plus signs. Lines 2 through 12 are the expansion of the SUBENTRY macro (when a macro is inserted into our program, the result is referred to as the macro expansion), lines 15 through 30 are due to the EQUREGS macro and lines 34 through 38 are the result of the SUBEXIT macro. Further details on the meaning of this code will be covered below. The left hand portion of the .prn file (usually referred to as the listing), contains the translation of the program into binary and other information about the
24

executable module. The left hand side is entirely in hexadecimal. The right hand side is normally in decimal notation with some exceptions. Normally, we suppress macro expansion with the PRINT NOGEN directive as the contents of the expansion are not ordinarily very interesting.
1 HELLO SUBENTRY 2+HELLO CSECT 3+ STM 14,12,12(13) 4+ BAL 15,104(15) 5+ DC 18F'0' 6+ DC CL8'HELLO' 7+ DC CL8'09/06/10' 8+ DC CL8'19.02' 9+ ST 15,8(13) 10+ ST 13,4(15) 11+ LR 13,15 12+ USING HELLO+8,13 14 EQUREGS 15+R0 EQU 0 16+R1 EQU 1 17+R2 EQU 2 18+R3 EQU 3 19+R4 EQU 4 20+R5 EQU 5 21+R6 EQU 6 22+R7 EQU 7 23+R8 EQU 8 24+R9 EQU 9 25+R10 EQU 10 26+R11 EQU 11 27+R12 EQU 12 28+R13 EQU 13 29+R14 EQU 14 30+R15 EQU 15 33 SUBEXIT 34+ LA 15,0 35+ L 13,4(,13) 36+ L 14,12(,13) 37+ LM 2,12,28(13) 38+ BR 14 40 MSG DC C'Hello World!' 41 END Figure 4 Macro expansion

4.6 More Basic Assembly Language Examples The hello world program isn't very interesting. It doesn't actually do any calculations and mainly relies on system macros rather than actual instructions. In Figure 5 we see a program to add two numbers. It has all the basic components of any assembly language program:
1. 2.

On line 1 we tell the assembler not to show macro expansion. Normally, we aren't interested in this code as it is always the same. On line 2 we include the macro which allows us to use R1, R2, etc. The commands in EQUREGS are assembly directives and generate no code. The merely tell the assembler that when it sees a symbol such as R5 it really means 5.
25

3.

4.

5.

6. 7.

8. 9. 10.

11.

12.

On line 3 we establish linkage and a base register. Linkage involves saving the contents of the calling programs registers so they can be restored on exit. A base register needs to be setup and the assembler informed of this if program labels are to be used. On line 4 we load the 4 byte binary value from label ONE into register 2. We use the symbolic label ONE and the assembler calculates the base and displacement for us and inserts the correct values into the instruction. On line 5 we add the 4 byte binary value at label TWO to the contents of register 2. Again, we use a symbolic label and the assembler calculates the base and displacement address. The result of the addition remains in register 2. One line 6 we write a title. The XPRNT macro needs to know where the beginning of the message is and its length. On line 7 we convert the binary value in R2 to printable characters stored in the 12 byte character string at label OUT. The contents of R2 are in pure binary and cannot be printed directly. The XDECO converts the binary into printable decimal characters. On line 8 we print the contents of OUT. On line 9 we exit and return to the operating system. The SUBEXIT macro restores the registers that were saved by the SUBENTRY macro. Lines 11 and 12 reserve storage for two full word (4 byte) binary values and initialize them to 1 and 2 respectively. Normally, we will use 32 bit binary numbers although there are instructions to use 64 bit binary as well. Line 13 reserves but does not initialize, a character string of length 12. A DS differs from a DC in that a DS only reserves memory, it does not initialize it. Line 14 tells the assembler there is no more code. This is not a return statement - it merely marks the end of our assembly language program. Return is made by the SUBEXIT macro.
PRINT NOGEN EQUREGS SUBENTRY L R2,ONE A R2,TWO XPRNT MSG,L'MSG XDECO R2,OUT XPRNT OUT,L'OUT SUBEXIT DC C'Adding Numbers' DC F'1' DC F'2' DS CL12 END Figure 5 Example program

1 2 3 4 5 6 7 8 9 10 11 12 13 14

ADD

MSG ONE TWO OUT

26

5 Basic Instruction Formats


5.1 Operands In the basic IBM architecture, operands can be in registers or memory. When an operand is in a register, the operand is specified by giving the register number (0 through 15). Often, however, you will see the registers designated as R0, R1, R2 and so forth. This is permitted so long as you include the EQUREGS macro (or equivalent) at the beginning of your program. When an operand is in memory, the memory address is specified as a combination of a base register and a displacement and, in some instructions, an optional index register. The address of a memory resident operand is calculated by adding the contents of the base register, the displacement and, if specified, the contents of the index register. The resulting number is the address of the operand in memory. The terms base register and index register do not refer to another class of registers. They are selected from the set of 16 general purpose registers. For most of this text, we will assume that SUBENTRY has been used and that the default base register is thus set to R13. The only oddity concerning registers selected to be base or index registers is that if you specify register zero as either the base or index register, it means no register. That is, the contents of register zero will not be used in the address calculation. General purpose register 0 is not used for addressing. It may, however, be used for other purposes. In most cases, the displacement and base register will be automatically filled in by the assembler as is the case when we specify an operand as a symbolic label attached to a data declaration statement as we saw in Figure 5. The index register is not often used but when it is, it is used in array-like operations where the base and displacement identify the start of an array and the index register gives an offset into it. In most cases, unless we tell the assembler to the contrary, the assembler will set the index register to 0 meaning no register. 5.2 Operand Notation In the documentation for each instruction, code letters are used to indicate what operands of instruction are. Instructions may have from one to three operands. Most have two. Operands can be registers, immediate data or memory addresses. When specifying operands the letters R, I, B, X, M, L and D are used to indicate the nature of the operand. For example, the 32 bit binary Add instruction is shown in its explicit definition as:
A R1,D2(X2,B2)

27

The letters tell us what the operand or operand component is and the numbers tell us which operand we are looking at (first, second, third). In the above, the first operand consists of only an R while the second operand is composed of D, X, and B.
R I B D X M L means means means means means means means a general purpose register an immediate byte a base register a displacement an index register a mask a length

Thus, the Add instruction shown above has a first operand that is a register and a second operand that is composed of a displacement, base and index register. 5.3 Operand Semantics When the contents of a register are the operand, R is used. When the operand is a byte contained as part of the instruction, I is used. When the operand is a mask, M is used. L is used in instructions where the operands are of varying length. When the operand is in memory, the operand will be composed of a base and displacement or an index, base and displacement. The address of the operand in memory is computed by taking the sum of the displacement and the contents of the base register and the index register, if any. 5.4 Operand Formats The basic, original instruction formats are RR (register-register), RX (registerindexed storage), RS (register-storage), SI (storage-immediate) and SS (storagestorage): 5.4.1 RR Format In RR format instructions there are normally two operands both of which reside in the general purpose registers (GPR). An RR instruction consists of an 8 bit opcode and two register designations, each in 4 bits. The instruction, therefore, is 16 bits long. RR format instructions are also called register/register instructions. RR instructions are specified as:
OpCode R1,R2 OpCode M1,R2

The R1 tells us that the first operand is a register and the R2 tells us that the second operand is a register. M1 tells us that the first operand is a 4 bit mask. 5.4.2 RX Format In RX format instructions there are normally two operands. The opcode is always the first byte. The first operand is a register (shown as R1) or a mask
28

(shown as M1). The second operand (shown as D2(X2,B2) ) is the address of the operand in memory. The R1 is specified in a 4 bit field, Registers are always specified with 4 bit numbers. The second operand is a base register, displacement and index register. The displacement is a 12 bit field containing a constant between 0 and 4095. If the index register is specified as register zero (normally the case), it means there is no index register. The address of the operand in memory is calculated by adding the contents of the base, the value of the displacement and the contents of the index (unless it is 0). The result is an absolute memory address. RX instructions are always four bytes long. RX instructions are specified as:
OpCode R1,D2(X2,B2) OpCode M1,D2(X2,B2)

5.4.3 RS Format In RS format instructions there are three operands, two are registers and one is a base/displacement. There is no index register. The first and third operands are registers and the second operand is base/displacement. RS instructions are four bytes long. RS instructions are also called register/storage instructions. RS instructions are specified as:
OpCode R1,R3,D2(B2)

5.4.4 SI Format SI Format. In SI format instructions the first operand is a base/displacement value and the second operand is a one byte constant called the immediate operand. SI instructions are 4 bytes long and are also called storage/immediate instructions. SI instructions are specified as:
OpCode D1(B1),I2 OpCode D1(B1)

5.4.5 SS Format 5.4.5.1 One 8 Bit Length Field In SS instructions, both operands are in memory and specified with base/displacement addresses. In addition, there is a one byte field that gives the length of the target operand. The byte is a positive integer in the range 0 to 255. In actual execution, the value is interpreted as one greater that what is stored so a 0 is interpreted as meaning 1 and 255 is interpreted as 256 and so forth. SS instructions are six bytes in length and also called storage/storage instructions. SS-8 instructions are specified as:
OpCode D1(L,B1),D2(B2)

29

where L is the 8 bit length code. 5.4.5.2 Two 4 Bit Length Fields This is really the same format as above except the length byte is viewed as two four bit fields. This the instruction has two lengths. As before, the value is interpreted as one greater than what is actually in the instruction so a 0 means 1 and 15 means 16. Because of the 4 bit length fields, the maximum length is 16. The first length field applies to the first operand and the second to the second. As before, this is a 6 byte instruction. SS-4 instructions are designated as:
OpCode D1(L1,B1),D2(L2,B2)

where L1 and L2 are 4 bit length codes.

30

6 Basic Addressing
Operands in memory are addressed either by a single register which contains the absolute address of the operand or by means of a combination of base register, displacement and, in RX instructions, an optional index register. When using base, displacement, index addressing, you may specify the memory resident operand either (1) symbolically such that the assembler calculates the base and displacement, or (2) explicitly where you specify the base, displacement and index or (3) as a mixture of symbolic and explicit. 6.1 Explicit Addressing This simplest form of addressing is register addressing. In an instruction, if an operand is in a register, you simply specify the register number. For example, consider the examples in Figure 6. Here you see three examples of RR instructions RR instruction mnemonics always end in the letter R. A mnemonic is a short code to make information easier to memorize. In the case of instructions the mnemonics are usually one to 4 character abbreviations of the name of the instruction. The first example involves the add register instruction, AR. The instruction adds the contents of the register specified as the second operand tho the contents of the register specified as the first operand and leaves the result in the first operand. In the example, you can see that register 2 is the first operand and register 3 is the second operand so the value (contents) of register 3 will be added to the value (contents) in register 2 and the answer (result) will be left in register 2. Note: technically, the assemblers require you to use numbers only to the example should not have the letter R. However, in most cases, a system macro is invoked at the beginning of each program which makes the more easily read R form possible. More on this later. In the second example we see the subtract register instruction. As with the AR instruction, the SR instruction subtracts the contents of register 4 from the contents of register 3 and the result is placed in register 3. In the final example we see the LR or load register instruction. This instruction copies the contents of the second operand to the first.
AR R2,R3 *Contents of R3 added to R2, result remains in R2 SR R3,R4 *Contents of R4 subtracted from R3, result in R3 LR R4,R5 *Contents of R5 copied to R4 Figure 6 - RR Examples

If, on the other hand, an operand is in memory, you must specify it's location by means of a base, displacement and, possibly (in RX instructions only), an index register. In the most fully explicit way to express a memory operand, you fill-in each of the fields. So, for an operand with base and displacement only, this means you fill in
31

the value of the displacement and the register number. In general, the format as it appears on the so-called green card looks like those in the examples in Figure 7. In Figure 7, D2 is the place where you put the displacement, B2 is the place where you put the base register and X2 is the place where you put the index register. The number following each indicates if this is the first, second or third operand. In the example, 2 is used as most memory operands are second operands. In the basic instruction set, third operands are never of the base displacement variety.
D2(B2) D2(X2,B2) base and displacement base, index and displacement Figure 7 Memory operand

Index registers are only used in RX instructions. Often they are specified as 0. If 0 is used in an addressing context it means no register. That is, if you put 0 into a B or X position, no register will be used for that position. Note: register 0 can be used for arithmetic and other things but it has this special meaning when used for addressing. Since the index register is seldom used, 0 is often seen in this position and the operand, in effect, is base, displacement only. Figure 8 gives a few examples. In each, the value of the displacement is 1234, the base is R5 and the index is either R6 or R0. If R5 has 1000 in it and R6 has 100 in it, the effective addresses (the result of the address arithmetic calculations) are 2234, 1334 and 2234, respectively. The contents for R0 are unimportant. They will not be used.
1234(R5) 1234(R6,R5) 1234(R0,R5) base and displacement base, index and displacement base, no index, displacement

Figure 8 - Example memory addressing

Another way to specify an operand is called immediate addressing. In this case, the operand is actually part of the instruction itself and not in a register or memory. In the basic instruction set, immediate operands are always one byte in length. In all but one case, immediate operands are the second operand and thus designated as I2 in the instruction format tables. There are several ways to code an immediate operand but it is often specified either as a character constant such as C'A' (The letter A) or as a hexadecimal constant such as X'FF' (a byte all of whose bits are ones). In some instructions, in particular, the shift instructions, the second operand is used to calculate the number of bits by which to shift the register(s). Note that although the shift instructions are RS instructions by the R3 operand is not used. In the case of the shift instructions, the displacement is added to contents of the register specified as the base register and the result is the amount of the shift. No actual address is calculated. In practice, however, most programs shift by a constant amount. Thus, it is common to see code such as
32

SRA R5,10

which means, shift the bits in register 5 right by 10. The question is, how does the number 10 become represented in the base/displacement operand specification? When you specify a number alone as a base/displacement/index operand, it is as though you specified:
10(0,0)

which is to say, displacement 10, no register contribution. 6.2 Symbolic Addressing In reality, assembly programmers seldom use the explicit base and displacement format when writing programs. Instead, they use labels. The labels refer to other parts or your program. These labels usually appear on data elements or instructions. Labels can appear on either instructions or data. The assembler keeps track of the size of everything you write and knows how many bytes each label is from the start of your program. It is the job of the assembler when you use a label in, for example, an instruction, to calculate the correct base and displacement for you and replace the label in the assembled code with these values. In order to do this, the assembler needs to know which register or registers it can use for base registers. Additionally, it needs to know where in your program these possible base register candidates are pointing so it can calculate the displacement from that point. Thus if, for example, R12 is a base register and is pointing (has as its contents) the address of the first byte of your program, displacements will be calculated as distances from that point. When you write a program you need to tell the assembler not only which register or registers it can use as base registers but also where they are pointing. In practice this is not difficult in simple programs. You use an assembler command called USING to tell the assembler which register(s) can be used as base registers and what their address contents are. (For the examples in this book, the base register will be setup by a system macro named SUBENTRY.) What this all means is that instead of you calculating a lot of base and displacement values, the assembler will do it for you. For example, suppose you have a program in which you want to:
1. 2. 3.

load a value from memory at label I into register 7 add to register 7 the value in memory of J store the result back into memory at label K
33

Assume all values are 32 bit (4 byte) binary values. Assume that your program is using R13 as its base register. Assume that label I is 400 bytes from the start of the program, label J is 404 bytes from the start, and label K is 408 bytes from the beginning. Figure 9 gives a code fragment that shows the code fragment (other parts of the program have been omitted).
L A ST I J K DC DC DS F'10' F'20' F Figure 9 - Example symbolic addressing R7,I R7,J R7,I

The first instruction is the RX load instruction. It loads the 32 bit value from the address specified by the second operand (I) into the register specified as the first operand. Thus, the four byte value from memory at I is now in register 7. When the assembler sees the load instruction, it scans and parses its operands. The first operand, R7, is simple. However, the second operand, I is more complex. The assembler first finds label I. Then it calculates how many bytes from the beginning of the the program the label is located. For this example, let us say that I is at offset 400 from the beginning of the program. Next the assembler calculates the relative offset of label I from your base register. The z390 emulator uses an entry macro named SUBENTRY which, be default, established R13 as you base register and causes it to point to byte 8 of your program. Note: R13 does not point at the beginning or your program but 8 bytes into it! So, given R13 as the base register pointing at byte 8 and the label I is located at location 400 from the actual start of your program, the assembler will generate the explicit code:
L R7,392(R0,R13)

The displacement is calculated relative to the base register, not the start of the program. While your label is 400 bytes from the start of the program, it is only 392 bytes from the value in the base register. Hence, the displacement is 392. Since the load instruction is an RX instruction, it has an index register position but, as is typical, we are not using it so R0 is placed there. Similarly, the other instructions from Figure 9 will be translated to machine language as if they had been written as shown in Figure 10. Obviously, it is easier to have the assembler calculate the displacements than to do the calculation yourself.
34

L A ST I J K DC DC DS

R7,392(R0,R13) R7,396(R0,R13) R7,400(R0,R13)

F'10' F'20' F Figure 10 - Explicit addressing

6.3 Machine Language Formats The end result of submitting your program to the assembler is a translation of your program into binary machine language. In the earliest days of computing, programmers wrote in binary, happily, those days are long gone. Instead, the assembler translates from your symbolic assembly code to the actual binary code. Each instruction type (RR, RX, SI, SS, RS, etc.) has a specific machine language binary format. While these formats are similar to a certain point, they are not identical. In the basic instruction set, the machine language code has the following similarities regardless of the instruction type:
1. 2.

3.

4.

5. 6.

Each instruction begins with an 8 bit opcode (operation code) that identifies the instruction to be executed. Registers, both base and index, are always represented as four bit fields (that's because there are sixteen registers numbered 1 through F and you need four bits to represent the largest of these, F). Displacements are always twelve bits. This is not true with several of the newer instruction types added in recent years but is true for all the basic types. Length specifications are always one byte. The entire 8 bits might be the length or the byte may be subdivided into two four bit length fields, depending on the instruction. All immediate operands are one byte. In some recently added instruction types, this is not true but it is true for all the basic instruction types. Instructions are either two, four or six bytes long. This is true for all basic instruction types but not true for some recent additions.

6.3.1 RR Machine Language Format The machine language format is shown in Figure 11 and an example explicit format is:
AR R1,R2

35

Figure 11 RR Machine Language Format

RR format instructions (see Figure 11) are the simplest. They consist of an opcode and two register specifications. Consequently, the are two bytes in length. In this format, the opcode is in the first byte and the second byte is divided into two four bit fields for each of the registers. For example, consider the instruction:
AR R5,R6

which means to add the signed binary contents for register 6 to the signed binary contents of register 5 and leave the answer in register 5. The opcode for the AR instruction, in hexadecimal, is 1A so the machine language translation of the above is the two bytes:
1A56

Where each hex digit represents four bits, as discussed above. This is the translation of your symbolic code to actual executable code. When you run the assembler, you will see this on the left hand side of the printable output of the assembler. 6.3.2 RX Machine Language Format The machine language format is shown in Figure 12 and an example explicit format is:
A R1,D2(X2,B2)

Figure 12 RX Machine Language Format

RX instructions have two operands. The first is normally a register and the second is the address of an operand in memory. The address of the memory resident operand is calculated by adding the contents of the base register, the index register (if it is not zero), and the displacement. Address calculation always results in a positive (unsigned) number. The displacement is treated as an unsigned twelve bit binary number (that is, it can never be negative). So, if you have an instruction of the form:
A R5,LABEL 36

this means to add the contents of the signed 32 bit operand in memory at label LABEL to the signed binary contents of register 5 and leave the result in register 5. The label LABEL refers to a line in your program where a full word binary valye is stored. Since the second operand is specified as a symbol (rather than a specific displacement and register), it will be converted by the assembler to the explicit format. The assembler will supply the base and displacement that together can calculate the address of LABEL. Your symbolic instruction from above, after the assembler determines the base register and displacement, might look like:
A R5,240(R0,R12)

where 24010 is the value calculated by the assembler as the displacement from the presumed contents of R12 to LABEL. At this point all the information needed to build the machine language instruction is known. The opcode for the Add (RX) instruction is 5A and thus the final result is:
5A50C0F0

In this representation (see Figure 12) the 8 bit op code is followed by the four bits specifying the first operand (R5), followed by the four bits of the index register specification (R0), followed by the base register specification (R12 - 12 is C in hex) followed by the twelve bit displacement 24010 which is 0F016. 6.3.3 RS Machine Language Format The machine language format is shown in Figure 13 and an example explicit format is:
LM R1,R3,D2(B2)

Figure 13 RS Machine Language Format

RS instructions have three operands, two of which are designated as registers and the third a memory location in base/displacement format. There is no index register. The meaning of the two register operands varies depending upon the instruction being executed but the format of the machine language representation is always the same. The machine language format consists of an 8 bit opcode, followed by 4 bits to designate the register being used as the first operand, followed by 4 bits designating the register being used as the third operand, followed by 4 bits to designate the base register then 12 bits for the displacement. The base and displacement designate what is called the second operand even though it appears third in the actual machine language format.

37

For example, one of the RS format instructions is Load Multiple. It loads multiple registers from consecutive words in memory. An example of such an instruction is:
LM R1,R5,MEM

In this example, registers R1, R2, R3, R4 and R5 are loaded with the consecutive 32 bit full words in memory beginning at the label MEM. Altogether, 20 bytes of memory are accessed (5 words of 4 bytes each). A more fully explicit version of the above, after the assembler has conveniently translated MEM into base displacement format, might be:
LM R1,R5,200(R12)

The opcode for LM is 9816 so the machine language instruction would look like:
9815C0C8

By now you should be able to see the opcode (9816), the first operand (1), the third operand (5), the base C16 and the displacement (0C816). 6.3.4 SI Machine Language Format The machine language format is shown in Figure 14 and an example explicit format is:
CLI D1(B1),I2

Figure 14 SI Machine Language Format

The SI instructions all have one of their two operands actually in the instruction. The other operand is the address of a byte in memory. Both the memory operand and the immediate operands are always one byte long. For example, there is an instruction known as CLI - Compare Logical Immediate. It compares a byte in memory with the immediate byte and sets some bits indicating if the byte in memory is equal, less than or greater than the immediate operand. For example, If you want to test is a byte in memory has the value A, the symbolic instruction might be:
CLI MEMB,C'A'

This instruction compares the byte in memory at the label MEMB with the immediate byte whose value is the letter A. After MEMB is translated to an appropriate base and displacement pair, the symbolic instruction might look like:
CLI 64(R12),C'A' 38

The opcode for CLI is 9516 and the machine language instruction for the above would look like:
95C1C040

where C116 is the letter A in hex, C16 (12) is the base register and 04016 is the displacement. Note that in the instruction, the I2 operand actually appears first and the first operand D1(B1) appears second. 6.3.5 SS Machine Language Format Example explicit formats are:
MVC D1(L,B1),D2(B2) AP D1(L1,B1),D2(L2,B2)

SS has two formats that differ slightly from one another with regard to the length field. In SS instructions, both operands are in memory and addressed in base and displacement format. Both also have a length byte. All SS instructions are 6 bytes in length. The machine language formats are shown in Figure 15.

Figure 15 SS Machine Language Format

However, in one format, the length byte is taken as an unsigned 8 bit number. In the other variation, the length byte is interpreted as two unsigned 4 bit numbers. An example of the first format might be the Move Character (MVC) instruction. This instruction copies up to 256 characters beginning at the address specified by the second operand to the target beginning at the address specified by the first operand. The length byte is treated as an unsigned 8 bit number (a negative move length would be meaningless). For example, if you want to copy the 8 bytes beginning at the label FROM to the eight bytes beginning at the label TO, you would express it symbolically as:
MVC TO(8),FROM

In fact, the length designation (8) may be unneeded if the label TO has a length attribute of 8 (see below). In this case, the assembler would use the length attribute of the target. If the explicit form of the above might look like:
MVC 100(8,R12),200(R12)

The opcode of MVC is D216 so the machine instruction would look like:
D207C064C0C8 39

You can see the opcode (D2) the length (07), first base (C16), the first displacement (06416), the second base (C16) and the second displacement (0C816). But wait, the length is 8 not 7? Correct but when represented in machine language, the length is always one less. Thus 0 means 1, 1 means 2 and so forth. This was done because a length of zero had no use and it allowed the maximum length be be one longer (256 as opposed to 255). Some SS instructions divide the length byte into two 4 bit fields in order to get 2 lengths. This is mainly used with a class of arithmetic instructions known as decimal or packed. For example, there is an SS instruction known as Add Decimal (or Add Packed, more commonly) with the mnemonic AP. The length subfields give the length of the first and second operand, respectively. So, a typical AP instruction might look like:
AP VAL1(5),VAL2(3)

This means to add the three byte field from the second operand (VAL2) to the contents of the 5 byte field specified as the first operand (VAL1) and leave the result in the first operand. Translated to explicit format the above might look like:
AP 32(5,R12),64(3,R12)

which would, given the opcode of FA16 yield the machine instruction:
FA42C020C040

where FA16 is the opcode, 4 is the first 4 bit length code (one less than 5 as above), 2 is the second length, C is the first base, 02016 is the first displacement, C16 is the second base and 04016 is the second displacement. It is normal for both base registers to be the same.

40

7 Program Status Word (PSW)


7.1 Layout The PSW (Program Status Word) has been part of the IBM mainframe architecture since the beginning. Originally, it was a 64 bit (8 byte) register in the CPU which contained several important values relating to the status of the system at any given instant. Currently, in the latest models, it is a 128 bit (16 byte) register that has the same purpose and many of the same fields. The longer format is mainly due to an extension of the addressing from 24 to 64 bits over the years. Some of the important fields in the PSW in the ESA/390 level architecture are addressed in the following sections. 7.2 Addressing modes In 24 bit addressing compatibility mode, the address portion of the PSW is bits 40 through 63. In 31 bit addressing mode, the address portion is bits 33 through 63. In 64 bit addressing mode the address is found in bits 65 through 127. In the Z390 emulator, the PSW is 64 bits in length and the address is 31 bits in length. The basic addressing mode is determined by bit 31 (ESA/390 mode) and 32 (Z architecture only). In ESA/390 mode, is bit 31 is 1, addressing is in 31 bit mode, 24 bit mode otherwise. In the ESA/390 mode, the address in contained in the low order 31 bits of the second word of the PSW. In the Z architecture, when both are zero, 24-bit addressing is in effect. When bit 31 is 0 and bit 32 is 1, 31 bit mode is in effect and when they are both 1, 64 bit addressing is operational. In the Z architecture, the PSW is 128 bits and the address is contained in the last 64 bits. 7.3 Condition Code The Condition Code is located at bits 18 and 19. The Condition Code is two bits in the PSW which reflect the result of a prior operation. It can have the values 0, 1, 2 and 3 at any given instant. Many instructions set the Condition Code in order to indicate the result of their execution. But, in the other hand, there are also instructions that do not alter the Condition Code. The meaning of the Condition Code value is connected with how it was set. For example, if you execute a compare instruction, the Condition Code will indicate if the operands were greater than, less than or equal to one another. After signed binary addition, however, the condition code tells you if the result was zero, negative, positive or an overflow (the answer was too large). Thus, knowing which instruction that Condition Code is important to understanding it's meaning. 7.4 Program Mask The Program Mask is located in bits 20 through 23. The Program Mask determines which program exceptions will be recognized. The are:
41

Bit 20 - Enable fixed point overflow exception Bit 21 - Enable decimal overflow exception Bit 22 - Enable floating point underflow exception Bit 23 - Enable floating point significance exception When the bit is 1, the exception is enabled. 7.5 Problem / Supervisor State Bit The Problem State bit is located at bit 15. When 1, the machine is in (unprivileged) problem state. In problem state, not all instructions may be executed. When 0, the system is in supervisor state and all instructions may be executed. 7.6 Instruction Addressing The PSW contains the address of the next instruction to be executed. This is often referred to as the updated address portion of the PSW. When an instruction is fetched, prior to its execution, the address portion of the PSW is updated (incremented) to point to the address of the byte immediately following the instruction about to be executed. Thus, the address portion of the PSW presumably points to the next instruction to be executed. Any of the branch instructions can alter the address portion of the PSW. In effect, a branch means changing the address portion of the PSW. When you alter this value, the next instruction to be executed will be fetched from this location.

42

8 Flow of Control & Branch Instructions


Every program needs a way to control the order in which instructions will be executed. Normally, a computer will consecutively fetch and execute instructions one after another from ascending memory locations. However this is not always desirable. Some times we want to skip blocks of code if some condition is true or false or we may want to loop through a block of code a number of times or we want to branch to a subroutine and return when the subroutine has finished. In the basic architecture there are several branch instructions to handle these situations. These include instructions that branch if a condition is true, instructions that iterate and instructions that are used to call subroutines. The most common form of the branch instruction is the conditional branch. The conditional branch instructions branch or not depending on the Condition Code/ 8.1 Conditional Branching (BC, BCR) The conditional branch instructions branch or transfer control based upon the contents of the Condition Code. For example, if you want to skip a section of code if, for example, the result of some arithmetic operation were negative, the instruction to make the transfer is a conditional branch. The two basic conditional branch instructions are the BC (an RX instruction) and BCR (the RR version of the BC). In both instructions the destination (where to branch to) is specified by the second operand. The explicit formats are:
BC M1,D2(X2,B2) BCR M1,R2

In the BC instruction, the destination address is calculated form the base, index, displacement. On the other hand, in the BCR, the destination address is contained in a register specified as the second operand. In both instructions, the first operand is called a mask. It resides in the 4 bits where there would normally be a register specification in the RX and RR format. The mask tells the computer which setting or settings of the Condition Code should cause the instruction to branch. If the Condition Code has one of these values, the branch takes place. If the Condition Code does not have one of these values, execution resumes with the instruction next following the branch instruction. The mask is 4 bits and these correspond to the 4 possible settings for the Condition Code. If a mask bit is 1, that means the branch will take place if the Condition Code has the corresponding value. If a mask bit is off and the condition Code has the corresponding value, no branch takes place. The instruction will branch is any tested value succeeds.

43

For example, after a signed Add instruction the Condition Code will have the values shown in Table 5.
0 1 2 3 Answer Answer Answer Answer was zero was less than zero was greater than zero caused an overflow

Table 5 Condition Code after signed Add

Let us say you want your program to branch to some label in your program if the result of the Add was zero. You need mask of 10002 as shown in Figure 16. The first operand, B'1000', specifies a 4 bit constant. The first position in the mask corresponds to a Condition Code of 0, the second to 1, the third to 2 and the fourth to 3. In this case, the branch to label LAB1 will occur if the result in R3 is zero.
AR R3,R4 BC B'1000',LAB1 Figure 16 BC example

What if you wanted to branch if the result in R3 was zero or less than zero (negative)? you could place a second BC instruction after the first such as:
BC B'1000',LAB1 BC B'0100',LAB1

which will work because the BC instruction does not alter the Condition Code. However, this is wasteful. Instead, you may combine all the conditions for which you want to branch into one mask on one BC instruction. Thus, the BC to branch if zero or negative becomes the single instruction:
BC B'1100',LAB1

Now the instruction will branch is the Condition Code is either 0 or 1. All possible other combinations are shown in Table 6.
B'0000' B'0001' B'0010' B'0011' B'0100' B'0101' B'0110' B'0111' B'1000' B'1001' B'1010' B'1011' B'1100' B'1101' B'1110' B'1111' Never branch Branch if overflow Branch if > zero Branch if > zero or overflow Branch if < zero Branch if < zero or overflow Branch if not zero or overflow Branch if not zero Branch if zero Branch if zero or overflow Branch if zero or > zero Branch if not < zero Branch if zero or < zero Branch if not > zero Branch if not overflow Branch always Table 6 Mask settings after a signed add

44

The mask can be specified in any manner. The most popular methods are either as a decimal number or as a bit string. When a decimal number is given, its corresponding binary value determines the branch conditions. Table 7 gives examples.
BC BC BC BC BC BC BC BC BC BC BC BC BC BC B'0001',LAB B'0010',LAB B'0011',LAB B'0100',LAB B'0101',LAB B'0110',LAB B'1000',LAB B'1001',LAB B'1010',LAB B'1011',LAB B'1100',LAB B'1101',LAB B'1110',LAB B'1111',LAB or or or or or or or or or or or or or or BC BC BC BC BC BC BC BC BC BC BC BC BC BC 1,LAB 2,LAB 3,LAB 4,LAB 5,LAB 6,LAB 8,LAB 9,LAB 10,LAB 11,LAB 12,LAB 13,LAB 14,LAB 15,LAB

Table 7 Decimal mask settings

A simple way to construct a decimal mask is to remember that the bit positions in the mask each have a decimal equivalent. By adding the decimal equivalents of the bit positions, a final decimal mask can be created. The equivalents are shown in Table 8. So, if you want to branch if the Condition Code is either 0 or 3, the decimal mask would be 9 (8+1). Note that this corresponds the the mask values in Table 7 as well.
Condition Code 0 1 2 3 Decimal Mask Value 8 4 2 1 Table 8 Decimal mask equivalents

The BCR instruction is similar to the BC. The first operand is the four bit mask with the same meanings as in the BC instruction. The second operand is a register which contains the branch address. However, if the second operand is specified as R0, no branch takes place since R0 is not used in addressing contexts. Additionally, there are builtin extended mnemonic branch instructions. These are instructions where the assembler will fill in the mask for you. These are shown in Table 9. The purpose of these is to make your program more readable. Instead of using the mask codes, you use a mnemonic which is indicative of the purpose. The assembler uses a BC or BCR with a predetermined mask. Some mask settings (such as 8) have more than one extended representation: BE after a Compare instruction and BZ after an arithmetic instruction. They are interchangeable.

45

Extended B D2(X2,B2) BR R2 NOP D2(X2,B2) NOPR R2

Basic BC 15,D2(X2,B2) BCR 15,R2 BC 0,D2,(X2,B2) BCR 0,R2

Meaning Branch always Branch always No operation No operation

After Compare Instructions (A:B) BH D2,(X2,B2) BL D2(X2,B2) BE D2(X2,B2) BNH D2(X2,B2) BNL D2(X2,B2) BNE D2(X2,B2) BC BC BC BC BC BC 2,D2(X2,B2) 4,D2(X2,B2) 8,D2(X2,B2) 13,D2(X2,B2) 11,D2(X2,B2) 7,D2(X2,B2) Branch Branch Branch Branch Branch Branch A high A low A equals B A not high A not low not equal

After Arithmetic Instructions BO D2(X2,B2) BP D2(X2,B2) BM D2(X2,B2) BZ D2(X2,B2) BNP D2(X2,B2) BNE D2(X2,B2) After Test Under Mask B0 D2(X2,B2) BM D2(X2,B2) BZ D2(X2,B2) BNO D2(X2,B2) BC BC BC BC 1,D2(X2,B2) 4,D2(X2,B2) 8,D2(X2,B2) 14,D2(X2,B2) Branch Branch Branch Branch if if if if ones mixed zeros not ones BC BC BC BC BC BC 1,D2(X2,B2) 2,D2(X2,B2) 4,D2(X2,B2) 8,D2(X2,B2) 13,D2(X2,B2) 7,D2(X2,B2) Branch Branch Branch Branch Branch Branch on overflow plus minus zero not plus not zero

Table 9 Extended mnemonics

8.2 Branch and Link Instructions 8.2.1 BAL and BALR - Branch and Link The BAL and BALR instructions unconditionally. Normally, they always branch, they do not depend on the condition code. The branch is made to the address specified by the second operand: a base, index, displacement address in the case of the BAL and the address contained in the register designated as the second operand in the case of the BALR except if the register specified is R0, in which case no branch takes place. In both cases, the absolute memory address of the instruction following the BAL or BALR is placed into the register specified as the first operand. This is the linking operation. These instructions were on the earliest implementations of the 360 architecture and assume a 24 bit addressing mode. In addition to placing the 24 bit in the rightmost bits of the register specified as the first operand, they also place, in the high order 8 bits, the following fields from the PSW:
1. 2. 3.

The Instruction Length Code (bits 0 and 1) The Condition Code (bits 2 and 3) The Program Mask (Bits 4 through 7)

46

An important use for these instructions is to branch to a subroutine and load into a register the address of the return point. In the case of the BALR, it is sometimes used, in combination with R0 as the second operand, to load a register with the absolute memory address of the byte following the instruction. Example:
L R15,=V(SUB1) * load the address of a subroutine BALR R14,R15 * branch to subroutine

Because the BAL/BALR place additional information in the high order 8 bits of the address saved in the first operand and the BAS and BASR do not, the BAS and BASR are now the preferred linkage instructions for 31 bit addressing. 8.2.2 Branch and Save - BAS and BASR These are similar to the BAL and BALR instructions and are intended to replace them. They both load the updated address portion of the PSW into the first operand and branch to the address specified by the second operand except, in the BASR if the second operand is specified are R0 in which case no branch takes place. In 24 bit addressing mode, the 24 bit address loaded into the first operand is padded to the left with 8 bits all of which are 1. In 31 bit addressing mode, the 31 bit address is padded to the left with 1 bit whose contents are 1. The BAS and BASR instructions differ from the BAL and BALR instructions mainly in that they do not place additional information in the high order bits of the address stored in the register specified as the first operand. 8.2.3 Branch Relative and Save - BRAS, BRASL These instructions are similar to the BAS instruction. They load the updated instruction address portion of the PSW in the register specified as the first operand. If in 24 bit addressing mode, 8 zeros are appended to the left; in 31 bit addressing mode, a single one bit is appended to the left. In the BRAS instruction there is a 16 bit immediate field which is treated as a signed binary number. In the BRASL, there is a 32 bit immediate field which is also treated as a signed number. In both instructions, the branch address is computed by adding the twice the value of the immediate field to the current instruction address. That is, the immediate field is treated as the number of half words to jump from the current address. 8.3 Looping Branch Instructions 8.3.1 Branch Index Low, Equal, High - BXLE, BXH In the examples above, the loop mechanism involved an arithmetic operation, a compare and a conditional branch. Since this is such a common sequence of
47

events, the architecture provides several instructions that perform all three operations. The first of these is the BXLE instruction, Branch on Index Low or Equal. The instruction is an RS instruction which has the explicit format:
BXLE R1,R3,D2(B2)

The instruction operates as follows: First, an increment is added to the contents of the register specified as the first operand. The value in the first operand is then compared with a limit value and a branch takes place to the address specified by the second operand, the D2(B2). If the result of the comparison indicates that the contents of the first operand are less than or equal to the limit value. The third operand, the R3 in the above, is used to determine the increment amount and the limit value. If the register designated as R3 is even, it is the even register of an even odd pair where the even register of the pair contains the increment and the odd register contains the limit value. If the register designated as R3 is odd, its contents are used as both the limit and increment and the limit values. There are several instructions that use even/odd register pairs. The valid pairs are R0/R1, R2/R3, R4/R5, R6/R7, R8/R9, R10/R11, R12/R13, R14/R15. The program in Figure 17 gives an example of the BXLE in use. In this program we add the first 100 numbers into R2 and then print the result. On lines 5 through 8 we initialize the registers. On line 5, R2 is set to zero by subtracting it from itself. R3 will be our counting register which we set to 1. R4 will be the increment register, also set to 1 and R5 is the limit register, set to 100. We add R3 to R2 in line 9. The BXLE then increments R3 by 1 (R4) and compares the result with 100 (R5). The BXLE branches to LOOP so long as the value in R3 is less than or equal to 100. When R3 becomes 100, execution continues with the XDECO which converts the binary value in R2 to printable characters in the 12 byte string OUT. The XPRNT prints the result to the screen. The second operand of the XPRNT is the length of the string OUT. The data declarations on line 15 and 16 create two full word binary values in memory initialized with the values 1 and 100, respectively. The declaration on line 12 reserves storage for a character string of length 12 but does not initialize it (DC statements initialize, DS statements only reserve the memory). The advantage of the BXLE instruction is that it combines the increment, comparison and conditional branch into one instruction thus, in a large loop, resulting in considerably faster execution. The disadvantage is that it ties up several registers in the process. But, in many circumstances, it is justified. Closely related to the BXLE is the BXH. The BXH operands are the same in scope and function as the BXLE except that the branch takes place when the contents of the register specified as the first operand are greater than the limit value. If not, the branch does not take place.
48

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

SUM100

PRINT NOGEN EQUREGS SUBENTRY SR R2,R2 L R3,ONE L R4,ONE L R5,HUNDRED AR R2,R3 BXLE R3,R4,LOOP XDECO R2,OUT XPRNT OUT,L'OUT SUBRETURN LTORG DC F'1' DC F'100' DS CL12 END Figure 17 BXLE loop example

LOOP

ONE HUNDRED OUT

8.3.2 Branch on Count - BCT (RX) and BCTR (RR) A similar set of looping instructions are the BCT and BCTR or Branch on Count instructions. In both of these, one is subtracted from the contents of the register specified as the first operand. If the result is not zero, a branch is made to the address specified by the second operand. When the result is zero, execution advances to the next instruction. In the case of the BCTR, the second operand is a register whose contents are the branch address except when the second operand is specified as register zero, in which case no branch ever takes place (R0 being used in an addressing context). In the case of the second operand being R0, the BCTR becomes a decrement instruction on the register specified as the first operand. Using a BCT instruction, the program from Figure 17 becomes the program in Figure 18. As before, we zero the contents of R2 (line 5) and load 100 into R5, the count register. On line 7 we add the counting register into the total (R2). The BCT instruction then decrements R5 and branches to LOOP is R5 is not zero.

49

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

SUM100

PRINT NOGEN EQUREGS SUBENTRY SR R2,R2 L R5,HUNDRED AR R2,R5 BCT R5,LOOP XDECO R2,DBL XPRNT DBL,L'DBL SUBRETURN LTORG DC F'100' DS CL12 END Figure 18 BCT loop example

LOOP

HUNDRED DBL

50

9 Data Types
9.1 Arithmetic Data The IBM hardware architecture supports three basic arithmetic data types: binary integer, floating point and packed decimal. Table 10 gives an overview.
1. 2. 3. 4. Signed binary integers of either 2, 4, or 8 byte length Unsigned binary integers of either 4 or 8 bytes length Varying length signed packed decimals up to 16 bytes long. Floating point numbers of either 4, 8 or 16 bytes length with either binary, hexadecimal or decimal radixes. Table 10 Numeric data types

9.1.1 Packed Decimal and Zoned Decimal Format Data The IBM mainframe has a data type called packed decimal, often referred to just simply as packed or BCD (binary coded decimal). In this format, decimal numbers are represented in a string of from 1 to 16 bytes. Each byte contains two decimal digits except for the final byte which has one 4 bit digit and a 4 bit sign. Thus, numbers up to 31 digits in length, plus a sign, can be represented. Each digit is stored in 4 bits, half a byte. The final byte has a digit in the high order 4 bits and the sign of the number in the low order 4 bits. The the decimal numbers 0 through 9 are represented by their binary equivalents 000 through 1001 (hex codes 0 through 9). The codes 1100, 1010, 1111 and 1110 (hex digits C, A, F, and E) in the sign position indicate the number is positive while the codes 1101 and 1011 (hex digits D and B) indicate a negative number. Normally, we only see the hex codes so it is easy to remember that the positive codes are CAFE and the negative are DB (as in debit). Any code is equally valid but C and D are the defaults for positive and negative, respectively. Table 11 gives several examples of packed decimal numbers. They are merely encodings of a decimal number with a sign appended to the end. One advantage of packed decimal is that numbers in this format they can be used to perform accurate decimal arithmetic on values with many digits. Another advantage is that character versions of numbers (such a user might type on a terminal) can be converted to packed decimal very quickly and, likewise, packed decimal can be converted to printable numeric text very quickly as well. Their main disadvantage is that arithmetic operations are relatively slow and thus they are not suitable for procedures which require multiple arithmetic steps. Further, they do not have the range of magnitude often required for scientific calculations. Printable numbers are in what is called zoned format, often referred to simple as zoned, a close cousin of packed decimal format. In zoned format, the high order 4 bits of each byte are always ones (hex F) and the low order 4 bits are the digit
51

portion. For this reason, the high order 4 bits of a byte are called the zone and the low order 4 bits are called the digit.
Decimal +12345 -12345 +1 +12 Packed Decimal (in Hex) 12 34 5C 12 34 5D 1C 01 2C 3 3 1 2 bytes bytes byte bytes

Table 11 Example packed decimal numbers

When text numbers are read from a terminal or other user input device, the input machinery codes each digit in zoned format. This, if you type 1234 into an EBCDIC terminal, internally this will be coded as the four bytes: F1 F2 F3 F4. The CVD instruction converts a binary quantity in a register to packed decimal; the instruction CVB converts a packed decimal to binary. The ED (edit) and UNPK (unpack) instructions convert from packed decimal to zoned decimal and the PACK instruction converts from zoned decimal to packed decimal. The CVD is unusual in that the target is addressed by the second operand. Additional details are described in Chapter 21. 9.1.2 Binary Integers and 2s Complement Positive binary integers are represented as a string of bits of zeros and ones. The value of a binary number is the sum of the values of the bit positions times the value at the position (0 or 1). The positions are powers of two beginning with zero. Table 12 gives the powers of two from 0 to 31 (32 altogether) and the corresponding bit pattern in a 32 bit field. The last row is the largest value you can store in an unsigned binary integer: 2311. Likewise, the larges number you can store in an 8 bit field is 28-1 or 255 (0 through 255 are 256 values, however). An actual binary number is the sum of the values for its bit positions. Thus, the binary number (expressed to 32 bits):
0001 0000 1001 0000 1000 0000 1011 1001

is interpreted as shown in Table 13. In this table, where there are 1s, the corresponding value of the power of two is added to the total. Where there are 0s (not shown), nothing is added to the final total from that position. However, not all numbers are positive. The question becomes, how can you represent negative numbers? There are several possibilities. The first is what is referred to as sign and magnitude. Here, one of the bits, the first one usually, is a sign bit. If it is zero, the number is positive and if it is one, the number is negative. For example, in an 8 bit computer, the positive number 107 is:
0110 1101

and, in sign and magnitude notation -107 would be:


52

1110 1101 1 2 4 8 16 32 64 128 256 512 024 048 096 192 384 768 536 072 144 288 576 152 304 608 216 432 864 728 456 912 824 648 295 20 21 22 23 24 25 26 27 28 29 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232-1 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 0010 0100 1000 1111 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 0010 0100 1000 0000 0000 0000 0000 1111 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 0010 0100 1000 0000 0000 0000 0000 0000 0000 0000 0000 1111 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 0010 0100 1000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1111 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 0010 0100 1000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1111 0000 0000 0000 0000 0000 0000 0000 0000 0001 0010 0100 1000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1111 0000 0000 0000 0000 0001 0010 0100 1000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1111 0001 0010 0100 1000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1111

1 2 4 8 16 33 67 134 268 536 1 073 2 147 4 294

1 2 4 8 16 32 65 131 262 524 048 097 194 388 777 554 108 217 435 870 741 483 967

Table 12 Powers of two

Sign and magnitude notation, however, has several problems. The first of these is there are two ways of expressing zero:
0000 0000 1000 0000 1 x 228 268 435 456 1 x 223 8 388 608 1 x 220 1 048 576 1 x 215 32 768 1 x 27 128 1 x 25 32 1 x 24 16 1 x 23 8 1 x 20 1 ------------------277 905 593 Table 13 Decimal value of a binary number

53

The first is a positive zero and the second is a negative zero. Both, however, are zero. This sort of thing confuses the hardware. If you compare two values you need to take into account that they could both be positive, both negative or mixed. This adds complexity and reduces speed. Another problem is that you can't do arithmetic directly on number in sign and magnitude notation. If I add the value of 107 and -107 I should get zero but I don't:
0110 1101 + 1110 1101 ----------1 0101 1010

The extra bit on the left is an overflow. The answer is not zero. This is a problem. To solve it, you need more specialized hardware to take into account all the possible outcomes. Another solution is called 1s complement. In 1s complement we form the negative of a number by flipping (complementing) the bits. This, 107 and -107 appear as:
0110 1101 1001 0010 107 -107

As it turns out, all negative numbers have a leading one bit so that position is still called the sign but the remainder of the number is quite different. Does this work? It solves the arithmetic problem:
0110 1101 + 1001 0010 ----------1111 1111

And the answer is zero. Yes, 1111 1111 is zero. 1s complement has two zeros too:
0000 0000 1111 1111 positive zero negative zero

So, we still have the problem of comparing two values but there is a solution: 2s complement. 2s complement is formed by adding one to the 1s complement. Thus 107 becomes negative the following way:
0110 1101 1001 0010 1001 0011 107 1s complement 2s complement

How does this solve the two zeros problem:


0000 0000 1111 1111 0000 0000 54 zero 1s complement 2s complement (overflow ignored)

In other words, if you try to create a negative zero, you get the original zero again. Can we do arithmetic? Yes:
0110 1101 + 1001 0011 ------------0000 0000 107 -107

There are special rules for handling overflows which won't be covered here. This, however, is how signed binary integers are represented in a modern computer. A consequence of this is that one bit is lost to sign representation so, in the case of a 32 bit number, the range is not 0 to 4,294,967,295 as shown above but, rather, 2,147,483,648 to + 2,147,483,647. Note: there is one more negative number that positive numbers (that extra zero had to go some place). Unsigned 32 bit numbers, however, do range from 0 to 4,294,967,295. 9.1.3 Nomenclature Table 14 gives the decimal values of several powers of two and along with the terms with which we refer to them. Terms such as kilobytes, megabytes and gigabytes derive from these thresholds. Thus, 1 gigabyte of memory actually has 230 or 1,073,741,824 bytes, expressed in decimal. However, it is currently fashionable among disk drive manufacturers to call 1,000,000,000 bytes a gigabyte - note the small print on the package. This lets them claim what appears to be a higher capacity for their offerings. In fact, however, they are shorting you more than 71 million bytes per "gigabyte." Clock rates are normally expressed in base 10 so 1 gHz is 1,000,000,000 Hz. Memory manufacturers, however, are stuck with the higher binary values due to manufacturing issues. 9.1.4 Threshold Binary Values In many cases, it is important to know the maximum number that can be stored in an unsigned binary number with a particular number of bits. For example, the largest binary number in 4 bits is 1111 which corresponds to 15 decimal. The minimum number, of course, is 0000 or zero. the range 0 to 15 has 16 values. Thus, 4 bits are needed to specify any of registers in an IBM mainframe. Hence, the instruction formats all allow 4 bits whenever a register is designated. That is, you need 4 bits to be able to specify any register. At 8 bits you can have numbers between 0 and 255, a total of 256 values. Thus, the maximum number of binary codes in an 8 bit byte is 256.

55

1 024 2 048 4 096 8 192 16 384 32 768 65 536 131 072 262 144 524 288 1 048 576 2 097 152 4 194 304 8 388 608 16 777 216 33 554 432 67 108 864 134 217 728 268 435 456 536 870 912 1 073 741 824 2 147 483 648 4 294 967 296

210 2
11

1 K 2 K 4 K 8 K 16 K 32 K 64 K 128 K 256 K 512 K 1024 K or 1 M (meg) 2 M 4 M 8 M 16 M 32 M 64 M 128 M 256 M 512 M 1024 M or 1 G (gig) 2 G 4 G

212 2 2
13 14

215 2 2
16 17

218 2 2
19 20

221 2 2
22 23

224 225 2
26

227 228 2
29

230 231 232 Table 14 Binary nomenclature

Similarly, if your unsigned binary number has 12 bits, the size of a displacement, you can have 4096 values between 0 and 4095. Thus, the maximum displacement from a base register is 4095. In 16 bits you can count from 0 to 65,535. At 24 bits your numeric range is 0 to 16,777,215. 16,777,215 (~16 meg) number is significant as it was the upper limit of memory size on the basic 360 Series. Many legacy assembly language programs have coding conventions that take this number into account. It takes 3 bytes to hold a 24 bit number. So, since addresses were almost always stored in 4 byte full words, one byte (the high order or leftmost) was not used for addressing. Many programs and operating system conventions used that byte to communicate information. Consequently, many older legacy programs still run in 24 bit addressing mode to this day. If they were executed in 32 bit mode, the high order byte would be considered part of the address and lead to erroneous results. Modern mainframes can execute programs in 24 bit, 32 bit and 64 bit addressing modes.
56

10 Data Declarations
10.1 Declare Constant and Declare Storage (DC and DS) In a high level language such as C, C++, FORTRAN, Java, and so forth, you manipulate named variables. These are defined with declaration statements that give the name of the variable, its dimensionality (if any), data type, storage class and so forth. Depending upon the data type and dimensionality, an amount of memory is allocated for each variable. For example, a long is 32 bits or 4 bytes in C/C++ while a char is 1 byte. In your program, you access and manipulate this memory by referring to the names of the variables. Assembly language has a similar but different approach. In assembly language, you normally place a label on an area of memory. This label is then used to refer to the memory in program instructions in a manner analogous to variables in a high level program. Note: in some cases the label can be omitted if there are other ways to address the data area. These will be discussed separately. In IBM Assembler, there are two main methods of reserving memory. The first is a DC statement and the second is a DS statement. A DC (declare constant) statement reserves and initializes memory in your program whereas a DS (declare storage) statement only reserves memory without initialization. In both forms you ordinarily (but not always) place a unique label complying with assembler naming rules (see page 18) beginning in column 1. After the label, you include one or more spaces followed by either DC or DS, followed by one or more spaces followed by a series of codes that indicate the data type, dimensionality, length and so forth of the memory being reserved. Based on your combination of codes, the assembler will allocate an amount of memory at that location in your program. The assembler will remember the attributes with which you labeled the memory for future use. When reserving memory, the DS/DC code tells the assembler the type of data you are reserving. There are several codes that may be used but the most common are given in Table 15. Each code implies a data type, a length and the alignment of the memory that will hold the value. In Table 15, several data specification types have no implied length. In these, the minimum length is 1 byte and the maximum is effectively unlimited. In other data specifications, however, there is an implied length. For example, a fixed point binary integer, type F, is normally 32 bits or 4 bytes because this is the size of a general purpose register in which data of this type is normally manipulated (note: on newer 64 bit architectures 64 bit or 8 byte values are possible). Alignment refers to where the memory associated with the label can be put. Some data types require that the address of the memory holding the value be evenly divisible by 4 (word alignment), 8 (doubleword alignment) or 2 (half word alignment). This is for performance reasons as some operations execute quicker if the data is on aligned boundaries.
57

Type C X B F H D P Z A V

Implied Length 4 2 8 4 4

Alignment byte byte byte word halfword doubleword byte byte word word

Format characters hexadecimal digits binary digits fixed point binary fixed point binary long floating point packed decimal zoned decimal address value external address value

Table 15 DS/DC Data Types

In your program, if the next available byte is not aligned properly for the data type your are creating, the assembler will automatically skip one or more bytes in order that your value will be correctly aligned. Fore example, if the next address available is divisible by 2 but not 4 and you are allocating a full word fixed point value (type F), the assembler will skip two bytes before allocating your data item. Normally you won't notice this but if you look carefully, you will see the location counter increment by 6 and not 4 for your variable. In some cases, especially where you need to know the exact amount of memory used by variables in contiguous memory, these extra padding bytes may be important. If you use the DS statement, you do not provide initialization. If you use DC, you give an initial value that will be loaded into the memory location when the program begins. Initialization is normally a single-quoted string beginning immediately after the data type and any qualifications to the data type. The value in the string must be appropriate for the data type. Figure 19 gives some examples. The first three labeled DS statements reserve 4, 2 and 8 bytes respectively. None of the data items at these labels are initialized and, consequently, the contents of each is undefined. The memory reserved by labels LAB1 through LAB5 reserve 4, 11, 2, 2, and 3 bytes respectively and initialize each as shown. The unlabeled memory following LAB5 can be addressed as LAB5+3 (the length of the data at LAB5 is 3 bytes).
DAT1 DAT2 DAT3 LAB1 LAB2 LAB3 LAB4 LAB5 DS DS DS DC DC DC DC DC DC F H D F'123' C'HELLO WORLD' B'1011101010001001' X'2F3C' P'1234' F'789' *fullword uninitialized *halfword uninitialized *doubleword uninitialized *binary full word *character string *bit string *hexadecimal string *packed decimal string *binary full word

Figure 19 Example DS/DC statements 58

In addition to the label and the data type, you may also specify a count. This is the number of items of the type you want to allocate. So, if you say 18F you are asking for 18 fullwords. Your label (lets say LOC) will be the address of the first fullword and the remaining 17 will be at successive 4 byte offsets from this location (LOC+4, LOC+8, LOC+12, and so forth). 10.2 Literals Often for the sake of clarity or convenience, constants are not separately declared in DC statements but contextually with what are called literals. This is a shorthand notation which causes the assembler to make the declaration for you at another place in your program. You may use literal notation in an instruction in place of a label. A literal looks like a DC operand but is always preceded by an "=" sign. Note: there is another form of notation for what are called immediate operands. These are not preceded by the equals signs and the two should not be confused. Table 20 gives several examples. The assembler keeps track of all the literal values and types your program has used. This is referred to as the literal pool. The declarations for these constants will, by default, be placed at the end of your program or at point immediately after the LTORG directive. If you use the same literal more than once, it will only be declared once. In the first example from Figure 20, the literal is in the position of the memory operand of the load (L) instruction. The effect of this is to load register 1 with a full word binary with the equivalent of the decimal number 123.
L R1,=F'123' MVC MESSAGE,=C'Hello World' MVC RESULT,=X'40202120' CLI LAB,C'X' *loads R1 with 123 *moves the string to MESSAGE *moves an edit pattern to RESULT *immediate - no = sign

Figure 20 Literals

One reason for the LTORG directive has to do with base register addressing. Sometimes a program will need to use a very large data area, one which will extend beyond the range of any base and displacement combination. As long as the first byte of the data area in within range of a base and displacement, it can be used without problem (you load the address of the area into a register and address it directly with this register). If, however, you permitted the literals to be placed at the end of the program, they would be beyond the large data area and out of range of any base and displacement. Thus, the LTORG can be used to dump the literal pool prior to the start of a large data area. See the example in Figure 54 in Section Error: Reference source not found on page 132.

59

60

11 Linkage
Linkage refers to the set of conventions used by the operating system whereby programs call one another, pass arguments, and return values. The IBM mainframe still uses the original linkage conventions established when the machine was introduced in 1964 although there have been some additional modes added since then. For purposes of this text, we will deal with the legacy linkage as embodied in the SUBENTRY and SUBEXIT macros. Basically, linkage saves the contents of the calling program's registers in the calling program's save area, creates a local save area to be used by any programs our program calls, and sets up a base register. 11.1 Linkage Registers On entry into a subroutine, several registers have predefined contents as shown in Table 16.
R1 R13 R14 R15 Address Address Address Address of of of of a parameter list save area in calling program return point in calling program entry point in called program

Table 16 Linkage registers

The two main linkage registers are R14 and R15. R14 indicates where the called program is to branch to in the calling program in order to make a return. That is, when the subroutine is finished, it should branch to the address contained in R14. The calling program provides this. Secondly, R15 always contains the address of the entry point in the called program. Normally this is the address of the first instruction in the called program however some subroutines can have multiple entry points. In any event, R15 is the address of the first instruction to be executed. 11.2 Save Area Every program has a save area. A save area, as shown in Table 17, is an 18 full word (72 byte) area in which we place information that will be restored when the program completes as well as information helpful to debugging. When a subroutine starts, it immediately saves the contents of the general purposes registers (except R13) into the calling program's save area then it creates a save area of its own. The address of the calling program's save area will be in R13 upon entry. The code to save the calling program's registers and set up our local save area is in the SUBENTRY macro as shown in Figure 21 as copied from the assembler output file. The line numbers are from the assembler and the plus sign after each indicates that the code is from a macro expansion (non-macro code does not have a plus sign on the line number).
61

Offset Word 0 4 8 12 16 20 24 28 32 36 40 44 50 54 58 62 66 70 Word Word Word Word Word Word Word Word Word Word Word Word Word Word Word Word Word Word 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

Contents Address of calling program save area Address of called program save area Register 14 Register 15 Register 0 Register 1 Register 2 Register 3 Register 4 Register 5 Register 6 Register 7 Register 8 Register 9 Register 10 Register 11 Register 12 Table 17 Save area

On line 3 we tell the assembler that this is the start of a control section and that it's name is ADD (from the label on the SUBENTRY). A CSECT is an assembler directive and does not generate code. On line 4 the STM (Store Multiple) causes registers R14, R15, R0, R1, R11, R12 to be saved in successive 4 byte full words beginning at the fourth full word in the calling program's save area. Word 4 begins at offset 12 (see Table 17) from the start of the calling program's save area whose address is in R13 and thus the displacement of 12 past R13.
3+ADD 4+ 5+ 6+ 7+ 8+ 9+ 10+ 11+ 12+ 13+ CSECT STM BAL DC DC DC DC ST ST LR USING 14,12,12(13) 15,104(15) 18F'0' CL8'ADD' CL8'09/14/10' CL8'20.33' 15,8(13) 13,4(15) 13,15 ADD+8,13

Figure 21 SUBENTRY code

The next instruction, the BAL (Branch and Link), does two things: it causes a branch to the ST (Store) instruction on line 10 and it resets the contents of R15 to point to the first byte of the 18 full word save area immediately following it. The branch address is calculated by adding the contents of R15 and 104, the displacement. At the time it does this, R15 has the address of the STM in it (the first instruction of the program). The ST instruction at line 10 is 104 bytes from the beginning of the STM.

62

But after the BAL calculates the branch address but before the actual branch, the BAL loads into the first operand, R15, the update address portion of the PSW, that is, the address of the byte immediately following the BAL. When an instruction executes, the address portion of the PSW always has the address of the byte immediately following the instruction. Normally, this is the address of the next instruction. In this case, however, it is the address of our (called) program's save area. At line 10, the ST instruction stores the address of our save area into the third word of the calling programs save area then stores the address of the calling program's save area in the second word of our save area. Thus, the calling program's save area points to ours and ours points to the calling program's save area. The contents of R15 (address of our save area) are copied to R13 and the assembler is told to use R13 as a base register and to assume that it is pointing at the 9th byte of the program (the 1st byte of the save area) which it is. You will note that after the 18 word save area are character fields containing the name of the CSECT and the date and time when it was assembled. Happily all this is done by the SUBENTRY macro. Like wise, the SUBEXIT macro reloads the calling program's registers and returns to the address contained in R14.

63

64

12 Assist Macro Input/Output


The overall issue of input/output on the s390 architecture also involves the underlying operating system and many other factors. For purposes of this discussion, the simplified Assist pseudo instructions XREAD and XPRNT will be used. 12.1 Input / Output using XREAD and XPRNT By default, the XREAD pseudo instruction will read from a file with the same name as the file your are assembling but with the .XRD extension. Output will have the .XPR extension and also appear in the console window.
1 2 3 4 5 6 7 8 9 README LOOP PRINT NOGEN SUBENTRY XREAD IN,20 BC B'0100',DONE XPRNT IN,20 BC B'1111',LOOP SUBEXIT DS CL20 END

DONE IN

README.XRD Arms, and the man I sing, who, forc'd by fate, And haughty Juno's unrelenting hate, Expell'd and exil'd, left the Trojan shore. Long labors, both by sea and land, he bore, And in the doubtful war, before he won The Latian realm, and built the destin'd town; His banish'd gods restor'd to rites divine, And settled sure succession in his line, From whence the race of Alban fathers come, And the long glories of majestic Rome. Screen Output: C:\Documents and Settings\user>assist readme C:\Documents and Settings\user>echo off 12:11:36 readme MZ390 START USING z390 V1.5.01b ON J2SE 1.6.0_18 12:11:36 readme MZ390 ENDED RC= 0 SEC= 0 MEM(MB)= 42 IO=578 12:11:36 readme LZ390 START USING z390 V1.5.01b ON J2SE 1.6.0_18 12:11:36 readme LZ390 ENDED RC= 0 SEC= 0 MEM(MB)= 15 IO=32 12:11:36 readme EZ390 START USING z390 V1.5.01b ON J2SE 1.6.0_18 Arms, and the man I And haughty Juno's u Expell'd and exil'd, Long labors, both by And in the doubtful The Latian realm, an His banish'd gods re And settled sure suc From whence the race And the long glories 12:11:36 readme EZ390 ENDED RC= 0 SEC= 0 MEM(MB)= 19 IO=30 INS=53 Figure 22 XREAD example 65

The general format of the XREAD is:


XREAD INFIELD,LENGTH

Where INFIELD is the area into which data will be read. The address is specified in the same manner as a second operand in an RX instruction. The length is specified as either a constant or as a register enclosed in parentheses. If specified as a register, the contents of the register at runtime will be the length. Input lines are in ASCII but will be converted to EBCDIC. On input, carriagereturn/line-feeds will be removed and short records will be padded with blanks (4016 in EBCDIC). Long input records (that is, those that exceed the length stated in the XREAD) will be truncated. In the event of an error, the program aborts with an abend code of S013. At end-of-file, the Condition Code is set to 1. Figure 13 gives an example. Note that the input line are truncated when printed. Also note that the output, besides appearing on the screen, is also placed in the file README.XPR 12.2 XDUMP The XDUMP pseudo instruction will dump the contents of the general purpose registers, the floating point registers and the program memory segment to the standard output. This is an aid for debugging and discussed in greater detail in section 13.3 below. 12.3 XDECO/XDECI These pseudo instructions are used to convert from internal binary numbers to character decimal representations and the reverse. XDECO has the format:
LABEL XDECO R1,D2(X2,B2)

Where first operand designates the register containing the signed 32 bit binary number to be converted to printable decimal and the second operand gives the address of a 12 character field which will receive the converted number. The number will be right justified with a leading minus sign if negative and padded to the left with blanks. The LABEL is optional. The XDECI has the format:
LABEL XDECI R1,D2(X2,B2)

In this case, the first operand designates the register to receive the number converted to signed binary and the second operand designates the address of a filed in memory containing the decimal character representation of the number. The first operand is normal not machine register R1 as this register may be altered by the instruction.
66

XDECI scans the field. If the first character is not numeric or a plus or minus sign, the instruction halts, R1 is set to the address of that character and the Condition Code is set to 3. Note: R1 in this case means the actual register 1, not the first operand. The instruction scans the number until a non-decimal character is encountered (for example, a blank). The converted number is placed in the first operand and the Condition Code is set to 0 if the converted number was zero, 1 if the number was less than zero and 2 if the number was greater than zero. If there are more than 9 digits, however, R1 is set to the first character which is not a digit, the Condition Code is set to 3 and the first operand is unchanged. 12.4 XHEXO/XHEXI These operations are similar to XDECO/XDECI except hexadecimal numbers are converted and there is no usage of either the plus or minus signs.

67

68

13 Integer Arithmetic
13.1 Program to Add Numbers As impressive as Hello World! was, it can't compare with the thrill of actually doing arithmetic or some other ostensibly useful computational activity. First, however, we must examine the question of the internal representation of a number versus its external representation. Externally, we normally prefer to see numbers printed as decimal characters. Internally, however, computers represent numbers in several different formats. Among these are binary integer, floating point, and packed decimal. Any activity involving numbers must convert between these formats when doing input or output operations. Our program will be called add.mlc. Initially, we will start with an initialized (i.e., not read in at run time) table of numbers between 1 and 5 decimal, add them and print the result. The program will borrow from hello.mlc as a starting point. Initially we create the table of numbers as shown in Figure 23.
1 2 3 4 5 6 7 8 9 10 11 12 ADD PRINT NOGEN SUBENTRY EQUREGS XPRNT MSG,L'MSG SUBEXIT DC C'Adding Numbers' DC F'1' DC F'2' DC F'3' DC F'4' DC F'5' END Figure 23 ADD.MLC Step 1

MSG ONE TWO THREE FOUR FIVE

In Figure 23 you can see we modified hello.mlc to change the name (to ADD), the message (to Adding Numbers) and added five additional lines of storage declarations. Each of the storage declarations creates a full word (4 bytes) whose contents are the binary equivalent of the decimal numbers in the quoted fields. The total storage allocated is 20 bytes. Next we need to calculate the result. Since we are working with binary integers (the most common form of integer arithmetic programming), we will need a register in which to do the calculations. A register is required because the integer arithmetic instructions are all of the RR or RX variety and, consequently, one or both of the operands must be a register. We select a register in the range R2 through R12. This is because registers R0, R1 and R13 through R15 have significance with regard to linkage. R2 is a good choice but be careful, it can sometimes be altered by system calls and some instructions. In this case we will select R2.
69

R2 will be out accumulator. That is, we will add each of the values into it until it has the final total and then we will print the total. Obviously we first need to put zero into the register. This can be done in two ways. One way is to load a full word constant zero into the register. This would use a 4 byte Load instruction and require a 4 byte constant in memory as shown in Figure 24. The L instruction loads the full word (4 bytes, fullword aligned) from the memory address specified by the second operand into the register specified as the first operand. It is an RX instruction and the memory address is calculated using the Base, Displacement and Index method.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 ADD PRINT NOGEN SUBENTRY EQUREGS L R2,ZERO *Zero R2 XPRNT MSG,L'MSG SUBEXIT DC C'Adding Numbers' DC F'0' DC F'1' DC F'2' DC F'3' DC F'4' DC F'5' END Figure 24 ADD.MLC Step 2

MSG ZERO ONE TWO THREE FOUR FIVE

Alternatively, we could use a literal as shown in Figure 25 but this is really the same thing as the assembler merely makes the storage declaration for us (it will appear in the .prn file).
1 2 3 4 5 6 7 8 9 10 11 12 13 ADD PRINT NOGEN SUBENTRY EQUREGS L R2,=F'0' *Zero R2 XPRNT MSG,L'MSG SUBEXIT DC C'Adding Numbers' DC F'1' DC F'2' DC F'3' DC F'4' DC F'5' END Figure 25 ADD.MLC Step 3

MSG ONE TWO THREE FOUR FIVE

The preferred alternative is to simply subtract the register from itself as shown in Figure 26. This is the quickest and uses the least memory (2 bytes). The SR instruction subtracts the contents of the register specified as the second operand from the contents of the register specified as the first operand and leaves the result in the first operand. Next we need to add each of the values into R2. To do this, we use five Add (A) instructions as shown in Figure 27.
70

1 2 3 4 5 6 7 8 9 10 11 12 13

ADD

MSG ONE TWO THREE FOUR FIVE

PRINT NOGEN SUBENTRY EQUREGS SR R2,R2 *Zero R2 XPRNT MSG,L'MSG SUBEXIT DC C'Adding Numbers' DC F'1' DC F'2' DC F'3' DC F'4' DC F'5' END Figure 26 ADD.MLC Step 4

The A instruction is an RX instruction that adds the full word aligned binary value from memory at the address specified as the second operand to the value in the register specified as the first operand and leaves the result in the first operand.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ADD PRINT NOGEN SUBENTRY EQUREGS SR R2,R2 *Zero R2 A R2,ONE A R2,TWO A R2,THREE A R2,FOUR A R2,FIVE XPRNT MSG,L'MSG SUBEXIT DC C'Adding Numbers' DC F'1' DC F'2' DC F'3' DC F'4' DC F'5' END Figure 27 ADD.MLC Step 5

MSG ONE TWO THREE FOUR FIVE

At the end of the Add instructions the answer is in R2 in binary format. We need to print it. To print it we need to convert it from binary to decimal characters. The Assist package has a convenient instruction that does this for us named XDECO as shown in Figure 28. XDECO takes the place of several actual instructions (CVD and EDIT) which will be discussed below. XDECO is a pseudo RX instruction in the Assist package that converts the signed binary integer in the register specified as the first operand to a 12 byte signed right justified decimal character (zoned decimal) representation padded to the left with blanks and placed in the 12 bytes of memory beginning at the address specified as the second operand. In the z390 emulator the address of the 12 byte field need not be aligned. Note the operand on the DS statement labeled DBL. This format means character length 12 or, one character string with a length attribute of 12. Another way of allocating it would be an operand of 12C which means 12 character strings of length one (implied default length of a character). However, this later notation
71

would not work with the L'DBL figure in the XDECO. The value of L'DBL would be 1, not 12. 12 would be the repetition count, not the length.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ADD PRINT NOGEN SUBENTRY EQUREGS SR R2,R2 *Zero R2 A R2,ONE A R2,TWO A R2,THREE A R2,FOUR A R2,FIVE XPRNT MSG,L'MSG XDECO R2,DBL XPRNT DBL,L'DBL SUBEXIT DC C'Adding Numbers' DC F'1' DC F'2' DC F'3' DC F'4' DC F'5' DS CL12 END Figure 28 ADD.MLC Step 5

MSG ONE TWO THREE FOUR FIVE DBL

Running the code from Figure 28 results in the output shown in Figure 29 (long lines truncated).
C:\Documents and Settings\user>echo off 13:13:21 add MZ390 START USING z390 V1.5.01b ON J2SE 1.6.0_18 13:13:21 add MZ390 ENDED RC= 0 SEC= 0 MEM(MB)= 43 IO=733 13:13:22 add LZ390 START USING z390 V1.5.01b ON J2SE 1.6.0_18 13:13:22 add LZ390 ENDED RC= 0 SEC= 0 MEM(MB)= 15 IO=35 13:13:22 add EZ390 START USING z390 V1.5.01b ON J2SE 1.6.0_18 Adding Numbers 15 13:13:22 add EZ390 ENDED RC= 0 SEC= 0 MEM(MB)= 19 IO=22 INS=20 Figure 29 ADD.MLC Step 5

13.2 Analyzing the PRN File The file add.prn now contains some interesting information as shown in Figure 30 (some parts now shown). There are several things to take note of. Column labels have been added at the top which do appear in the actual PRN file.
1.

2. 3.

Column 1 is what is known as the location counter. It is in hexadecimal and gives, relative to zero, the starting byte of each line of code in the machine language image being created. Column 2 is also in hexadecimal and is the translation of the assembly language statement up to the first 8 bytes. Column 3 is the effective address, relative to zero, of the first operand if the first operand is a memory address.

72

4. 5. 6.
Col 1 000000 000000 000072 000072 000074 000078 00007C 000080 000084 000088 00008E 000092 000098 0000AA 0000B8 0000BC 0000C0 0000C4 0000C8 0000CC 0000D8

Column 4 is the effective address, relative to zero, of the second operand if the second operand is a memory address. Column 5 indicates the macro level, original line number, and actual line number taking into account macro statements. Column 6 contains your original card images.
Col 3 Col 4 Col 5 (1/1)1 (1/2)2 (1/3)15 (1/4)33 (1/5)34 (1/6)35 (1/7)36 (1/8)37 (1/9)38 (1/10)39 (1/11)40 (1/12)41 (1/13)42 (1/14)49 (1/15)50 (1/16)51 (1/17)52 (1/18)53 (1/19)54 (1/20)55 (1/21)56 Col 6 ADD PRINT NOGEN SUBENTRY EQUREGS SR R2,R2 *Zero R2 A R2,ONE A R2,TWO A R2,THREE A R2,FOUR A R2,FIVE XPRNT MSG,L'MSG XDECO R2,DBL XPRNT DBL,L'DBL SUBEXIT DC C'Adding Numbers' DC F'1' DC F'2' DC F'3' DC F'4' DC F'5' DS CL12 END

Col 2

1B22 5A20D0B0 5A20D0B4 5A20D0B8 5A20D0BC 5A20D0C0 E020D0A2000E 5220D0C4 E020D0C4000C C1848489958740D5 00000001 00000002 00000003 00000004 00000005

0000B8 0000BC 0000C0 0000C4 0000C8 0000AA 0000CC 0000CC

MSG ONE TWO THREE FOUR FIVE DBL

Figure 30 ADD.PRN

Column 2 for a line containing an instruction is the translation of that instruction to machine language. Look at the line with the location counter value of 72 (leading zeros omitted). The code 1B22 is represents the SR instruction. As an RR instruction, the format consists of one byte (2 hex digits) containing the opcode and one byte containing the operands (see section 6.3.1 above). The opcode is 1B as determined from Table 20 on page 135. With regard to the second byte, the first operand is designated by the first four bits and the second operand by the second four bits. Since a hex digit corresponds to four bits, the first hex digit (2) is the first operand and the second hex digit (2) is the second operand. Hence, the code 1B2216 is the result of SR R2,R2. As all RR instructions are two bytes in length, the location counter advanced by 2 from 72 to 74. Note that the location counter jumped from zero at the beginning of the program to 72 following the SUBENTRY. This is because the SUBENTRY macro used 72 bytes. The next instruction is A R2,ONE which says to fetch the 4 bytes beginning at the label ONE and add them to the 4 bytes in register R2, leaving the result in R2. The Add instruction is an RX instruction and, as is the case with nearly all RX instructions except the BC, has the format shown in section 6.3.2 above. Thus we get the hexadecimal machine language 5A20D0B0 16. The first byte (5A) is the opcode as shown in Figure 30. The next byte contains the first operand
73

(2) and the index register (0). The third byte has the base register (D or R13) and the first 4 bits of the displacement (0). The full displacement is 0B0 16 or 17610. In fully explicit notation, this would correspond to:
A R2,176(R0,R13)

In response to our second operand label of ONE, the assembler has calculated the address of ONE is at a displacement of B016 (leading zero omitted) relative to the contents of register 13. This means that when the program is run, the address of ONE will be the sum contents of R13 plus B016 (or 17610). So the question becomes, what's in R13? If you look at the location counter you will see that ONE is at location B816 from the start of the program but the displacement relative to the contents of R13 is B016. Thus, R13 must have 8 in it? Look at Figure 4 on page 25. It shows the expansion of the SUBENTRY macro. Several things happen here. First, in the BAL on line 4, R15 is effectively loaded with the location counter value of 8. Then on line 11 the LR instruction copies this value to R13 (note: the systems macros use ordinary numbers for the registers, not numbers preceded by the letter R). This is how R13 gets the value 8. So how does the assembler know to use R13 as the base register? Line 12 in Figure 4 tells the assembler that R13 is the base register. USING is a directive that does not generate code but tells the assembler something it needs to know. In this case the USING is telling the assembler that R13 is the base register and that it is pointing to the 8th byte of the program which is HELLO+8 or, in the case of our program, ADD+8. The SUBENTRY macro expands the same each time except for the program name which it gets form the label on the invocation and the time and date which it gets from the assembler. Thus the assembler knows that R13 can be used as a base register and that it is pointing 8 bytes into the program. Consequently, when the assembler see the label ONE in the Add instruction, it calculates, correctly, that the label is B0 or 176 bytes from the 8th byte of the program. Hence we see a displacement of 0B016 and a base register of R13 in the machine code. The index register remains. It is specified as R0. When R0 is used in an addressing context it means no register. There is an R0 and you can use it for arithmetic but if you use it in an address it means no value is contributed regardless of the actual value in R0. Normally, the index register in an address will be R0 unless you explicitly use it (see below for an example). Next question, will our program will be loaded into the computer memory at location zero every time? No. The program can be loaded anywhere in memory because all the addresses are relative to R13. Thus, if the program is loaded beginning at location 1 000 00016 everything will work so long as R13 has 1 000 00816 in it. Then the memory at label ONE will be at 1 000 0B816 or R13+B016.
74

So, how does R13 get 1 000 00816 in it? When the BAL instruction on line 4 of Figure 4 executes, it loads the address of the byte immediately following the BAL into R15 and R15 is eventually copied to R13. So, if the program is loaded into memory beginning at 1 000 00016 the byte immediately following the BAL will be at address 1 000 00816. 13.3 Debugging (XDUMP) A dump is ordinarily produced when a program encounters a run time exception or interrupt. Alternatively, a programmer can explicitly request a dump with the XDUMP macro during program execution in order to analyze program execution. For example, if the program from Figure 28 were modified to include the XDUMP as shown in Figure 31 (shown as the .PRN file with macro expansion printing enabled), the result would be the text shown in Figure 32 (long lines truncated). The contents of the dump are as follows:
1.

The contents of the 16 64-bit general purpose registers R0 through RF (R15); The contents of the 16 64-bit floating point register F0 through FF (F15); The contents of memory beginning at location 0000000016 through location 000FFFFF16.

2. 3.

The contents of the general purpose and floating point registers are each displayed as 16 hexadecimal digits (corresponding to 8 bytes). There are four registers displayed per line. For example, the first line for the general purpose registers displays R0, R1, R2 and R3 while the last line displays the contents of registers RC (R12), RD (R13), RE (R14) and RF (R15). A similar pattern is shown for the floating point registers (F0 through FF). As the program only used 32 bit instructions and since the emulator preinitializes each byte of each register to F4, the high order 32 bits of all the general purpose registers are F4. The low order bits are F4 unless the register was used in the course of the program. As none of the floating point registers were used, all of their bytes are shown as F4. The contents of the memory are shown in rows of 32 hexadecimal digits grouped into four fields of 8 digits each. Each group or 8 digits corresponds to one word (4 bytes) of memory and they are separated from one another to improve readability. Each line, therefore, displays 16 bytes of memory. At the beginning of each row is the address of the first byte in the row. On the right hand side is an attempted conversion of each byte in the row to a printable character. Where there is no printable character for a byte code, a period is printed. Where the byte code has a printable equivalent, it is shown. In most cases, the printable equivalents are not meaningful.
75

000000 000000 000000 000000 000004 000008 000050 000058 000060 000068 00006C 000070 000072 000072 000072 000072 000072 000072 000072 000072 000072 000072 000072 000072 000072 000072 000072 000072 000072 000072 000072 000074 000078 00007C 000080 000084 000088 00008E 000092 000098 00009E 00009E 0000A2 0000A6 0000AA 0000AE 0000B0 0000C0 0000C4 0000C8 0000CC 0000D0 0000D4 0000E0

90ECD00C 45FF0068 0000000000000000 C1C4C44040404040 F0F961F1F461F1F0 F2F04BF3F3404040 50FD0008 50DF0004 18DF 000000 000001 000002 000003 000004 000005 000006 000007 000008 000009 00000A 00000B 00000C 00000D 00000E 00000F 1B22 5A20D0B8 5A20D0BC 5A20D0C0 5A20D0C4 5A20D0C8 E020D0A8000E 5220D0CC E020D0CC000C E06000000000 41F00000 58D0D004 58E0D00C 982CD01C 07FE C1848489958740D5 00000001 00000002 00000003 00000004 00000005 0000C0 0000C4 0000C8 0000CC 0000D0 0000B0 0000D4 0000D4

(1/1)1 PRINT GEN (1/2)2 ADD SUBENTRY (2/77)3+ADD CSECT (2/167)4+ STM 14,12,12(13) (2/168)5+ BAL 15,104(15) (2/169)6+ DC 18F'0' (2/170)7+ DC CL8'ADD' (2/171)8+ DC CL8'09/14/10' (2/172)9+ DC CL8'20.33' (2/173)10+ ST 15,8(13) (2/174)11+ ST 13,4(15) (2/175)12+ LR 13,15 (2/188)13+ USING ADD+8,13 (1/3)15 EQUREGS (3/41)16+R0 EQU 0 (3/41)17+R1 EQU 1 (3/41)18+R2 EQU 2 (3/41)19+R3 EQU 3 (3/41)20+R4 EQU 4 (3/41)21+R5 EQU 5 (3/41)22+R6 EQU 6 (3/41)23+R7 EQU 7 (3/41)24+R8 EQU 8 (3/41)25+R9 EQU 9 (3/41)26+R10 EQU 10 (3/41)27+R11 EQU 11 (3/41)28+R12 EQU 12 (3/41)29+R13 EQU 13 (3/41)30+R14 EQU 14 (3/41)31+R15 EQU 15 (1/4)33 SR R2,R2 *Zero R2 (1/5)34 A R2,ONE (1/6)35 A R2,TWO (1/7)36 A R2,THREE (1/8)37 A R2,FOUR (1/9)38 A R2,FIVE (1/10)39 XPRNT MSG,L'MSG (1/11)40 XDECO R2,DBL (1/12)41 XPRNT DBL,L'DBL (1/13)42 XDUMP (1/14)43 SUBEXIT (4/33)44+ LA 15,0 (4/50)45+ L 13,4(,13) (4/51)46+ L 14,12(,13) (4/52)47+ LM 2,12,28(13) (4/53)48+ BR 14 (1/15)50 MSG DC C'Adding Numbers' (1/16)51 ONE DC F'1' (1/17)52 TWO DC F'2' (1/18)53 THREE DC F'3' (1/19)54 FOUR DC F'4' (1/20)55 FIVE DC F'5' (1/21)56 DBL DS CL12 (1/22)57 END

Figure 31 Add program exposed

Thus, the following line:


00002600 *F0F961F1 F461F1F0 00000000 00000000* *09/14/10........*

means that it is the dump of the 16 memory locations beginning at 260016 through 260F16 inclusive (16 bytes of data). Because each line has 1016 (1610) bytes of data, the address will increment by 1016. On the far right column is the attempted character interpretation of the bytes. It tells us that the first eight bytes of the line's content correspond to the characters: 09/14/10 which appears to be a date. The remaining 8 bytes did not have printable equivalents as indicated by the periods.

76

C:\Documents and Settings\user\asm>assist err1 C:\Documents and Settings\user\asm>rem assemble, link, and exec ASSIST C:\Documents and Settings\user\asm>echo off 17:52:04 err1 MZ390 START USING z390 V1.5.01b ON J2SE 1.6.0_18 17:52:04 err1 MZ390 ENDED RC= 0 SEC= 0 MEM(MB)= 43 IO=737 17:52:04 err1 LZ390 START USING z390 V1.5.01b ON J2SE 1.6.0_18 17:52:04 err1 LZ390 ENDED RC= 0 SEC= 0 MEM(MB)= 14 IO=36 17:52:04 err1 EZ390 START USING z390 V1.5.01b ON J2SE 1.6.0_18 Adding Numbers 15 R0-R3 F4F4F4F480008000 F4F4F4F400002300 F4F4F4F40000000F F4F4F4F4F4F4F4F4 R4-R7 F4F4F4F4F4F4F4F4 F4F4F4F4F4F4F4F4 F4F4F4F4F4F4F4F4 F4F4F4F4F4F4F4F4 R8-RB F4F4F4F4F4F4F4F4 F4F4F4F4F4F4F4F4 F4F4F4F4F4F4F4F4 F4F4F4F4F4F4F4F4 RC-RF F4F4F4F4F4F4F4F4 F4F4F4F480008008 F4F4F4F400002018 F4F4F4F480008008 F0-F3 F4F4F4F4F4F4F4F4 F4F4F4F4F4F4F4F4 F4F4F4F4F4F4F4F4 F4F4F4F4F4F4F4F4 F4-F7 F4F4F4F4F4F4F4F4 F4F4F4F4F4F4F4F4 F4F4F4F4F4F4F4F4 F4F4F4F4F4F4F4F4 F8-FB F4F4F4F4F4F4F4F4 F4F4F4F4F4F4F4F4 F4F4F4F4F4F4F4F4 F4F4F4F4F4F4F4F4 FC-FF F4F4F4F4F4F4F4F4 F4F4F4F4F4F4F4F4 F4F4F4F4F4F4F4F4 F4F4F4F4F4F4F4F4 00000000 *00000000 00000000 00000000 00000000* *................* 00000010 *00002000 00000000 00000000 00000000* *..?.............* 00000020 *00000000 00000000 00000000 00000000* *................* ........ 00000040 *00000000 00000000 00000000 00002000* *..............?.* 00000050 *00000000 00000000 00000000 00000000* *................* ........ 00002000 *859999F1 40404040 40404040 40404040* *err1 * 00002010 *00008108 00000000 0A030000 00000000* *..a?....?.......* 00002020 *00000000 00000000 00000000 00000000* *................* ........ 00002070 *00000000 9B000000 00000000 00000000* *...............* 00002080 *00000000 00000000 00000000 00000000* *................* ........ 000020D0 *000080E0 00000000 00000000 00000000* *..\............* 000020E0 *00000000 00000000 00000000 00000000* *................* ........ 00002100 *00000000 00000000 80008008 00002018* *.........?..?.* 00002110 *80008000 80008000 00002300 F4F4F4F4* *......?.4444* 00002120 *F4F4F4F4 F4F4F4F4 F4F4F4F4 F4F4F4F4* *4444444444444444* ........ 00002140 *F4F4F4F4 F4F4F4F4 00000000 00000000* *44444444........* 00002150 *00000000 00000000 00000000 00000000* *................* ........ 00002300 *00002304 00000000 00000000 00000000* *..??............* 00002310 *00000000 00000000 00000000 00000000* *................* ........ 00002600 *F0F961F1 F461F1F0 00000000 00000000* *09/14/10........* 00002610 *00000000 00000000 859999F1 40404040* *........err1 * 00002620 *00000000 00000000 00000000 00000000* *................* ........ 00008000 *90ECD00C 45FF0068 00000000 00002100* *}.?.......?.* 00008010 *00000000 00000000 00000000 00000000* *................* ........ 00008050 *C1C4C440 40404040 F0F961F1 F461F1F0* *ADD 09/14/10* 00008060 *F1F74BF5 F2404040 50FD0008 50DF0004* *17.52 &.?& .?* 00008070 *18DF1B22 5A20D0B8 5A20D0BC 5A20D0C0* *. ??!?}!?}!?}{* 00008080 *5A20D0C4 5A20D0C8 E020D0A8 000E5220* *!?}D!?}H\?}y..?* 00008090 *D0CCE020 D0CC000C E0600000 000041F0* *}\?}..\-....0* 000080A0 *000058D0 D00458E0 D00C982C D01C07FE* *..}}?\}.q?}.* 000080B0 *C1848489 958740D5 A4948285 99A2F6F6* *Adding Numbers66* 000080C0 *00000001 00000002 00000003 00000004* *...............?* 000080D0 *00000005 40404040 40404040 4040F1F5* *.... 15* 000080E0 *00000000 000F7F20 859999F1 4BF3F9F0* *......"?err1.390* 000080F0 *80008000 F5F5F5F5 01F5F5F5 F5F5F5F5* *..5555.5555555* 00008100 *80008000 000000E0 00000000 000F7EF8* *.....\......=8* 00008110 *F5F5F5F5 F5F5F5F5 F5F5F5F5 F5F5F5F5* *5555555555555555* ........ 000FFFF0 *F5F5F5F5 F5F5F5F5 F5F5F5F5 F5F5F5F5* *5555555555555555* 17:52:05 err1 EZ390 ENDED RC= 0 SEC= 0 MEM(MB)= 21 IO=79 INS=21

Figure 32 - Dump format

77

From Figure 31 we can see that the first executable instruction is:
STM 14,12,12(13)

which corresponds to the machine code:


90ECD00C

An STM instruction is a Store Multiple and it is of type RS:


STM R1,R3,D2(B2)

The opcode is 9016. In the instruction in the program, E (R14) is in the R1 field, C (R12) is in the R3 field, D (R13) is in the B2 field and 00C16 is in the D2 field. If you look in the dump at address 800016 you will see the code for the STM instruction. 800016 is, therefore, the first byte of the program. In fact, because of the emulator, all programs will appear to begin at location 800016. Moving on, the next instruction following the STM is:
BAL 15,104(15)

which is the Branch and Link RX instruction and translates into the machine language:
45FF0068

Where 45 is the opcode, F (R15) is the R1 field, F (R15) is the B2 field (base register), 0 (R0) is the X2 (index register) field and 06816 is the D2 field (displacement in hex). Details on subroutine linkage are given in section 11 above. In the memory dump area, the presence of "....." in the address column means the missing lines are the same as the line above. Looking at the general purpose registers you can see the contents of the base register, R13, are 8000800816 (High order bit is 1 but only the lower 31 bits are used for addressing). This corresponds to the address of the start of the save area as described in section 11.2 above. R14 has the return address, 201816 and register 15 has the same contents as R13, as expected. Note that R2 has 15 (F16) in it which is the answer from the calculations. The 12 bytes beginning at label DBL can be seen to start at byte 80D416. This can be deduced from the location counter address from the assembler for DBL which is D416. Since the program is loaded at location 800016, the label DBL is , therefore, at 80D416.

78

The full words for labels ONE, TWO, THREE, FOUR and FIVE can be seen at 80C016, 80C416, 80C816, 80CC16 and 80D016. The body of the program begins with the SR at 807216 followed by the Add instructions. If your program fails, you will normally be given the address contents of the PSW at the time of the failure. As the PSW is always updated, that is, pointing at the next instruction, the actual problem is normally at the instruction preceding the address in the PSW. Using the dump and the assembler listing, it should be easy to locate where the error took place and determine how it was caused. 13.4 Data Addressing Alternatives The program in Figure 28 used several labels. An alternative, which generates identical machine language, can be seen in Figure 33. Here only one label (ONE) is used for each of the second operands but with an increment that takes into account the number of bytes from the label ONE to the desired operand. Thus, the 4 bytes following label ONE are at ONE+4, the next at ONE+8 and so one. Each DC statement generates exactly 4 bytes of data and these are arranged at consecutive memory locations. In Figure 33 the offsets from the label ONE become added to the displacement. Thus, the actual machine code is identical to that in Figure 28. 13.5 More Addressing Alternatives In reality, few programmers would code as shown in either Figure 28 or 33 - at least not for any significant number items to be added. Instead, a loop would be used with a register that incremented by 4 for each iteration and its values added to a base address. There are several ways to do this but the obvious one is to used the index register in the Add instruction (presently R0 meaning no register). To do this we need an additional register, need to initialize it, to increment it and we need a loop mechanism. For a register, we can select any register not otherwise in use except R0. For the loop mechanism, we also need a way to test if we are done and loop if we are not. To do the test, we will use the Compare instruction. To loop, we will use a Branch Conditional (BC) instruction. In Figure 34 we've selected R3 for our loop index register which we initially set to zero. We've added a new label: LOOP which is where we'll branch to until we've added all the numbers. In the Add instruction following LOOP we increment the index register (R3) by 4 (using literal notation) then we compare the contents of R3 with the value 16 (again, using literal notation). The purpose of the Compare instruction is to set the Condition Code.

79

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

ADD

MSG ONE

DBL

PRINT NOGEN SUBENTRY EQUREGS SR R2,R2 *Zero R2 A R2,ONE A R2,ONE+4 A R2,ONE+8 A R2,ONE+12 A R2,ONE+16 XPRNT MSG,L'MSG XDECO R2,DBL XPRNT DBL,L'DBL SUBEXIT DC C'Adding Numbers' DC F'1' DC F'2' DC F'3' DC F'4' DC F'5' DS CL12 END Figure 33 ADD1.MLC - Alternative 1

In the BC instruction (line 9) we tell the computer to branch to label LOOP if the Condition Code indicates that the Compare instruction (line 8) found that the value in R3 was less than or equal to 16. If the contents of R3 are equal to 16, the Condition Code is set to 0. If contents of R3 are less than 16, the Condition Code is set to 1. The BC instruction will branch if the Condition Code is 0 or 1 as indicated in Chapter 8. When the contents of R3 exceed 16, the branch will not take place the the instruction following the BC instruction, the XPRNT (line 10), will execute. The LTORG directive at the end tells the assembler to place any undeclared literals at this place in your program. These will include the =F'4' and =F'16' used above. They are, in effect, assembler generated DC statements. Note: if you do not include a LTORG, the assembler will place any literals it has accumulated at the end of your program anyway. 13.6 Using Extended Mnemonics Figure 35 is a related example. It is a program to sum the integers from 1 to 100. The initializes R2 to 0 and R3 to 1 (lines 4 & 5). It adds R3 to R2 then increments R3 (lines 6 & 7). Then it tests R3 against the value 100 (line 8) and branches (line 9) back to LOOP if the contents of R2 are less than 101 or falls through to the next instruction (XDECO) when the contents of R3 become equal to 101.

80

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

ADD

LOOP

MSG ONE

DBL

PRINT NOGEN SUBENTRY EQUREGS SR R2,R2 *Zero R2 SR R3,R3 *Zero R3 A R2,ONE(R3) A R3,=F'4' C R3,=F'16' BC B'1100',LOOP XPRNT MSG,L'MSG XDECO R2,DBL XPRNT DBL,L'DBL SUBEXIT DC C'Adding Numbers' DC F'1' DC F'2' DC F'3' DC F'4' DC F'5' DS CL12 LTORG END Figure 34 ADD2.MLC - Alternative 2

In Figure 35 we see another form of the BC instruction is used: the extended mnemonic form. BL on line 9 is really a BC with a mask of B'0100'. There are several of these forms accepted by the assembler as shown in Table 9 on page 46. They help make your program more readable but are, in reality, no different than the BC instruction with the appropriate mask.
1 2 SUM100 3 4 5 6 LOOP 7 8 9 10 11 12 13 14 DBL 15 PRINT NOGEN SUBENTRY REGS SR R2,R2 * zero R2 L R3,=F'1' * init R3 AR R2,R3 A R3,=F'1' * increment R3 C R3,=F'101' BL LOOP XDECO R2,DBL XPRNT DBL,L'DBL SUBRETURN LTORG DS CL12 END Figure 35 Loop example

81

82

14 Other Binary Arithmetic Instructions


14.1 Subtraction Similar to the A and AR instructions are the Subtract S and SR instructions. The S instruction is of type RX and the SR is of type RR. Both subtract the contents of the second operand from the register specified as the first operand leaving the result in the first operand. Both operate on 32 bit signed (2s complement) binary integers. 14.2 Halfword Instructions In addition to full word Add and Subtract, there are also halfword RX versions of these: AH and SH along with the utility instructions Load Halfword (LH) and Store Halfword (STH). The first operand of each of the halfword instructions is a register. The second operand is a 2 byte location in memory. When a LH is executed, the 2 bytes from memory are loaded into the low order two bytes of the register and then the sign bit of the value from memory is extended to the high order 16 bits of the register. Similarly, when a SH or AH is executed, the 2 bytes from memory are expanded to 32 bits by extending the sign before the operation with the register takes place. The value in memory is unchanged. The first operand is treated as a 32 bit signed binary integer. In the case of a STH, the low order 16 bits of the register are stored in memory at the address specified by the second operand. 14.3 Condition Codes After Binary Operations All signed arithmetic add and subtract instructions set the Condition Code to indicate the result of the operation as shown in Table 18.
Result zero < zero > zero overflow Condition Code 0 1 2 3

Table 18 Conditions Codes

14.4 Overflows The signed arithmetic instructions A, AH, AR, S, SH and SR can encounter situations where the result of the operation would overflow the register. This happens in 32-bit addition when the result exceeds the maximum allowed for a
83

signed positive 32 bit number (+2,147,483,647) or the minimum allowed for a signed negative 32 bit number (-2,147,483,648). Overflows can also occur with the Shift Left Arithmetic (SLA) and Shift Left Double Arithmetic (SLDA) instructions when a bit unlike the sign bit is shifted into the sign bit position (the high order bit). As this would result in a sign change, it is considered to be an overflow. When an overflow occurs, the Condition Code is set to 3 and a fixed-pointoverflow exception interrupt is raised. This normally results in program termination unless bit 20 of the PSW is on in which case the interrupt is disallowed. 14.5 Unsigned Arithmetic (AL, ALR, SL, SLR) The architecture provides for unsigned arithmetic in the form of the Add Logical (AL and ALR) and Subtract Logical (SL and SLR) instructions. All four instructions treat both operands as unsigned 32 bit binary integers. The AL and SL instructions are of the RX type with the first operand the contents of a register and the second the contents of a specified memory address. In the ALR and SLR instructions, both operands are memory resident. As with the other Add and Subtract instructions, the result is placed in the first operand. An overflow cannot occur as a result of these instructions. Instead, the Condition Code indicates if a carry took place as shown in Table 19.
Condition code zero, no carry 0 not zero, no carry 1 zero, carry 2 not zero, carry 3 Table 19 CC after logical add/subtract Result

This information can be used to construct extended precision binary integer arithmetic. 14.6 Multiply (M, MR) The basic binary integer multiply instructions are the M and MR. In both, the first operand specifies the even register of an even/odd pair of registers. The multiplicand is a 32 bit signed integer which resides in the odd register of the pair. The multiplier is a 32 bit signed integer which resides either in the register designated as the second operand (MR) or at the memory address specified (M). The contents of the even register are ignored. The result is a 64 bit signed binary number which is placed in the even/odd register pair with the high order 32 bits or the result in the even register and the low order 32 bits in the odd register. The sign of the result is determined by rules of algebra except a zero result is always positive. No overflow can take place and the Condition Code remains unchanged.
84

There is also a MH instruction where a 16 bit signed number from memory is multiplied by the 32 bit signed contents of the register specified as the first operand. The low order 32 bits of the result replace the contents of the first operand. No overflow can occur and the Condition Code remains unchanged. For example, If R5 contains 2010 and R6 contains 310, we can multiply them with the instruction:
MR R4,R6

The result will be in R4 and R5. As the answer is 6010, the result is effectively in R5. R6 will contain results only in the case when answers exceed 32 bits. 14.7 Divide (D, DR) The basic binary integer divide instructions are D and DR. In both, the register specified as the first operand, the dividend, is the even register of an even odd pair. Both registers are treated as one 64 bit signed binary integer with the high order part of the number in the even register. The divisor is a 32 bit signed number located in the register specified as the second operand (DR) or at the memory location specified by the second operand address. The result consists of a remainder located in the even register of the first operand and the quotient located in the odd register. The sign of the of the quotient is determined by the rules of algebra and the remainder has the same sign as the divided except that zero is always positive. A divide by zero will raise a fixedpoint divide exception. The condition code is unchanged. For example, if location VAR1 contains the 32 bit number 10, and location VAR2 contains the 32 bit number 3, you can divide the value at VAR1 by the value at VAR2 with the following:
L R2,VAR1 SRDA R2,32 D R2,VAR2

The result will be 1 in R2 (the remainder) and 3 in R3 (the quotient). Because all 64 bits of the even/odd pair R2/R3 participate, we load the dividend into the even register and then do a shift double arithmetic to the right by 32. In the SRDA instruction, both registers of the even odd pair participate. Effectively, we are loading the dividend into the odd register but insuring that the even register will contain bits like the sign bit of the dividend. See section 17.3.2 Arithmetic (SRA, SRDA, SLA, SLDA) on page 100 for full details on the arithmetic shift instructions.

85

86

15 Character Instructions
15.1 Basic Character Instructions The basic architecture has several instructions to compare and move strings of character data. These were extended in later versions of the architecture but we begin with the most basic. 15.1.1 Moving Characters (MVC) The basic character move instruction is the MVC instruction. It is an SS instruction and copies up to 256 bytes form the operand specified as the second to the operand specified as the first address. The addresses may overlap. In the machine language coding of an MVC (as is also the case with other SS character instructions - see Figure 15 on page 39), the length is expressed as an 8 bit field whose value is one less than the actual length to be moved. Thus, in the machine language format, a length value of 0 means move 1 byte and a length value of 255 means move 256 bytes, and so on. In the assembly language representation, the actual length is coded (one will be subtracted from this value in constructing the machine language representation). In the case where no length is supplied, the implied length attribute of the first operand is used. Some examples are given in Figure 36.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 MVC MVC L1,L2 L1(10),L2 *20 bytes from L2 are copied to L1 *10 bytes from L2 are copied to L1

LA R2,L1 LA R3,L2 MVC MVC * MVC MVC * L1 L2 DS DC 0(20,R2),0(R3) * 20 bytes from L2 are copied to L1 10(10,R2),0(R3) * 10 bytes from L2 are copied to L1 * beginning at position 10 in L1 L1(1),=C' ' L1+1(19),L1 * blank is copied to the 1st byte of L1 * overlapped move - L1 is made * all blanks

CL20 C'ABCDEFGHIJKLMNOPQRST' Figure 36 MVC Examples

15.1.2 Move Immediate (MVI) The MVI (Move Immediate) instruction copies the immediate byte from the instruction to an address in memory. In SI (storage immediate) instructions (see Figure 14 on page 38), the second operand is a single byte contained in the
87

instruction. This is called the immediate operand and is designated as I2 in the instruction set description. Because of the EX instruction, the second operand actually appears in the machine format before the first operand as shown in Figure 14 on page 38. However, when writing in assembly language, the second operand appears second. Figure 37 has some example.
MVI MVI MVI MVI L1,C'A' L1,X'C1' L1,B'11000001' L1,193 * * * * sets sets sets sets byte byte byte byte at at at at L1 L1 L1 L1 to to to to be the letter A A (C1 is hex for A) A (binary code for A) A (decimal equivalent)

Figure 37 MVI Examples

Note that the scond operand of the CLI is always a constant. It is never a literal (for example, C'A' and never =C'A'). 15.1.3 Compare Logical Characters (CLC) The basic instruction for comparing strings of bytes is the CLC (compare logical character)instruction. It is an SS format instruction using a single 8 bit length field as shown in the format in Figure 15 on page 39. When characters are compared, they are compared one by one as unsigned 8 bit bytes. The byte with the larger absolute value is considered the greater of the two. The condition code is set to indicate the result:
CC=0 CC=1 CC=2 CC=3 All bytes in both operands are equal; The first operand less than the second; The first operand greater than the second; is not possible.

As with the MVC, the length encoded in the machine language format is one less than the actual length. If the length is not specified, the assembler will use the length attribute of the first operand. The instruction compares successively each corresponding byte of each operand (first with first, second with second, and so forth). The instruction continues so long as the bytes compared are equal. If all bytes are found to be equal, the condition code is set to 0 and the instruction halts.
CLC L1,L2 * CC will be 1 CLC L1,L3 * CC will be 2 CLC L1(3),L2 * CC will be 0 - only 3 bytes compared L1 L2 L3 DC C'ABCDEF' DC C'ABCDEX' DC C'ABCDEA' Figure 38 CLC Examples

If the instruction encounters an unequal pair of bytes, the instruction halts and the condition code is set to reflect the inequality. If the byte from the first operand
88

is less than the byte from the second operand, the condition code is set to 1, otherwise, 2. Figure 38 gives examples. 15.1.3.1 Compare Logical Immediate (CLI) The first one, CLI, compares one byte in memory with the instruction's immediate byte and sets the condition code accordingly. For example:
CLI XXX,C'A'

In this case, the byte in memory at label XXX is compared with the immediate byte containing the EBCDIC code for the letter A. The condition code is set to reflect the relationship. Alternatively, the following has the same effect:
CLI XXX,X'C1'

where the hexadecimal code C116 is the equivalent of the letter A. 15.2 Character Long Instructions Two instructions were added to the architecture when the IBM 360 evolved into the IBM 370. These are the CLCL (compare logical character long) and MVCL (move character long). In the original architecture, the CLC and MVC instructions were limited to character strings no longer than 256 bytes. The string length was said to be based on the maximum amount of time an instruction could execute on a low end version of the IBM 360 without the possibility of missing an interrupt. Both the MVC and CLC are uninteruptable and, should more than one interrupt take place while they are executing, the first interrupt might be overwritten by the second. This is no longer an issue. The IBM 370 architecture introduced the CLCL and MVCL instructions with a string length limit of 224-1 (16 MB). 15.2.1 Compare Logical Character Long (CLCL) The CLCL instruction is an RR instruction. Both operands must designate the even register of an even-odd pair. The instruction compares the bytes beginning at the address specified by the even register of the first operand (R1) with the bytes at the address specified by the even register of the second operand (R2). The odd register of the first operand contains the first operand's length expressed in the low order 24 bits of the odd register. The odd register of the second operand contains an 8 bit padding byte followed by a 24 bit length. Up to 16M bytes can be compared. Comparison is byte by byte. The shorter operand is considered to be extended to the right by the padding byte, if needed.

89

The comparison terminates when an inequality is found or at the end of the longer operand. If the operation ends with an inequality, the even registers of both operands contain the addresses of the unequal bytes. The length fields in the odd registers of both operands give the number of bytes remaining to be compared when the operation ended. The instruction is interruptible. The Condition Code will be set to 0 if both operands are equal, 1 if the first operand is less than the second, and 2 if the first operand is greater than the second. 15.2.2 Move Character Long (MVCL) The MVCL instruction is an RR instruction. Both operands must designate the even register of an even-odd pair. The instruction copies the bytes beginning at the address specified by the even register of the first operand (R1) with the bytes at the address specified by the even register of the second operand (R2). The odd register of the first operand contains the first operand's length expressed in the low order 24 bits of the odd register. The odd register of the second operand contains an 8 bit padding byte followed by a 24 bit length. Up to 16M bytes can be copied. If the first operand is longer than the second, the first is padded to the right by the padding byte. The instruction is interruptible. The instruction checks for destructive overlap. That is, are bytes from the first operand used as source bytes after bytes have been moved into same. If there was no destructive overlap the Condition Code is 0 if both length are equal, 1 if the fistr operand is shorter than the second, and 2 if the first operand is longer than the second. The Condition Code is 3 and no copying is performed if a destructive overlap is detected. 15.3 Translate (TR) and Translate and Test (TRT) Scanning input fields is important so the 360 architecture provided a single instruction to do this known as the TRT (Translate and Test) instruction. The TRT uses a table (given as the second operand) and a string (the first operand). The table is 256 bytes long. Source bytes from the string are successively (left to right) used to index into the table. The byte found in the table at the offset determined by the source byte decides what should happen:
1. 2.

If the byte in the table is zero, the operation continues; If the byte in the table is non-zero, the operation terminates and the byte from the table is placed in the low order byte of register 2 and the address of the byte from the source string causing the halt is placed in register 1; If all tested bytes are zero, the condition code becomes zero.

3.

90

4.

If a tested byte is non-zero, the Condition Code becomes 1 if the byte from the source string was not the final byte of the source string. The Condition Code is set to 2 if the source string byte was the final byte of the source string.

The source string is not altered. While this may sound complicated it isn't. Take for example the case where you want to scan a source string for the first non-blank character, a not uncommon thing to do. To use a TRT to do the scanning you need a table that causes the TRT to continue to scan if blanks are encountered and to halt if a non-blank character is found. Putting it simply, you need a table were all the values are non-zero except the value corresponding to the offset of the blank character (hex 40 or decimal 64). While the concept of the table is simple, it is also clear that typing 256 bytes is not pleasant. However, the assembly language provides short cuts:
1. 2.

Build a table all of whose bytes are non-zero (X'01', for example); Go into the table at offset 64 and change the value to X'00'.

This is shown in Figure 39.


TAB DC ORG DC ORG 256X'01' TAB+C' ' X'00' Figure 39 TRT Table with ORG

In Figure 39, first you build a table of 256 bytes all initialized to X01 (these bytes, since they are not zero, will cause the TRT to halt). Then, you back into the table and replace the byte corresponding to the offset of blank (4016 , 6410) with X'00'. The ORG directive resets the assembler's location counter to the value specified. In this case, we reset the location counter to the start for TAB plus C' ' (which is the equivalent of saying 4016 or 6410 but is easier to understand). Now the location counter is in the table at the offset corresponding to a blank. Here you place the X'00' and this replaces the X'01' that was here. Next, you need to cause the location counter to spring back to where it was when you initially built the table (or subsequent code will overwrite the remainder of the table). An ORG with no argument resets the location counter to the highest value it has ever held. Hence the naked ORG (no argument) The effect of all this is to create a table mainly of X01 codes except in the offset position for blank. The example in Figure 45 scans each input record for the first word delimited by blanks, and prints the word.
91

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57

PRINT NOGEN START 0 REGS * PROGRAM TO SCAN AN INPUT IMAGE FOR THE FIRST * WORD DELIMITED BY A BLANK BEGIN LOOP SUBENTRY XREAD REC,L'REC BC B'0100',ATEND XPRNT REC,L'REC LA TRT BE LR LA MVC L1 LA LA LA CR BNL CLI BE MVC B XPRNT MVI MVC B R3,REC 0(L'REC,R3),TAB EXIT * only blanks found R3,R1 R5,WORD 0(1,R5),0(R3) R3,1(R0,R3) R5,1(R0,R5) R4,REC+30 R3,R4 PRNT 0(R3),C' ' PRNT 0(1,R5),0(R3) L1 * addr of non-blank * target * copy 1st byte * * * * * * * * * increment increment end addr at end? yes blank? yes - end move next loop source addr target addr * read a record * EOF? * write the record

of word character

PRNT

WORD,L'WORD * print word WORD,C' ' * blank to 1st position WORD+1(L'WORD-1),WORD * ripple move LOOP * again

* * * ATEND EXIT * * * REC WORD MSG TAB

EOJ processing XPRNT MSG,L'MSG SUBEXIT Literals LTORG DS DC DC DC ORG DC ORG END CL32 actual input record CL30' ' C'***** DONE *****' 256X'01' TAB+C' ' X'00' BEGIN Figure 40 TRT Example (continued on next page)

92

The input images are: TEST1 TEST3 TEST2 * * *

Figure 40 TRT Example (continued)

The example in Figure 45 reads records with numbers, verifies their content, sums and prints the result.
1 2 3 4 SUB 5 6 LOOP 7 8 9 10 11 12 13 14 15 16 17 18 19 20 PLUS 21 22 23 24 25 ERR 26 27 28 PCK 29 30 31 32 33 34 ADD 35 36 37 * 38 * 39 * 40 41 ATEND 42 43 44 PRINT NOGEN START 0 REGS SUBENTRY XREAD BC XPRNT MVI TRT BC CLI BC MVI MVI BC CLI BNE MVI BC REC,L'REC B'0100',ATEND REC,L'REC NEGFLG,C'0' REC,TAB B'1000',PCK 0(R1),C'-' B'0111',BPLUS NEGFLG,C'1' 0(R1),C' ' B'1111',PCK 0(R1),C'+' ERR 0(R1),C' ' B'1111',PCK read a record EOF? write the record set flag to 0 only blanks and numbers minus sign found? set flag to 1 make - a blank plus sign found make + a blank must be bad data

XPRNT ERRMSG,L'ERRMSG BC B'1111',RET PACK CLI BC NI AP BC NBR,REC NEGFLG,C'1' B'0111',ADD NBR+7,X'FB' SUM,NBR B'1111',LOOP

is this number neg no yes: make its sign D - negative loop

EOF processing XPRNT MVC ED XPRNT MSG,l'MSG RSLT,=X'4020202020202120' RSLT,SUM RSLT,L'RSLT Figure 41 TRT Verifying Input (continued on next page)

93

45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61

RET REC NBR NEGFLG SUM RSLT MSG ERRMSG TAB

SUBEXIT LTORG DS DC DC DC DC DC DC DC ORG DC ORG DC ORG END CL10 actual input record PL4'0' C'0' PL4'0' X'4020202020202120' C'DONE***************' C'ERROR - BAD DATA' 256X'01' TAB+C'0' 10X'00' TAB+C' ' X'00' SUM

Figure 41 TRT Verifying Input (continued)

94

16 Miscellaneous Register Operations


16.1 Load (L) The load instruction load a 32 bit word from memory into a general purpose register. The word in memory should be on a word boundary (a memory address evenly divisible by 4). The Condition Code is unchanged.
L R5,L1

16.2 Load (LR) The contents of the register specified as the second operand are copied to the register specified as the first operand. The Condition Code is unchanged.
LR R5,R6

16.3 Store (ST) The store instruction stores the 32 bit contents of a register to a word in memory. It is an RX instruction. The memory address should be a word boundary. The Condition Code is unchanged.
ST R5,L1

16.4 Load Multiple (LM) One or more general purpose registers are loaded from consecutive words beginning at the memory address specified as the second operand. The Condition Code is unchanged. The registers to be loaded begin with the register specified as the first operand through and including the register specified as the third operand. If the register specified as the first operand is greater than the register specified as the third operand, wrap around occurs. If the first and third operands both specify the same register, only 4 bytes are loaded.
LM R1,R5,L1 LM R6,R4,L2 * R1,R2,R3,R4 and R5 are loaded * R6,R7, R0,R1, R4 are loaded.

16.5 Store Multiple (STM) One or more general purpose registers are stored to consecutive words beginning at the memory address specified as the second operand. The Condition Code is unchanged. The registers to be stored begin with the register specified as the first operand through and including the register specified as the third operand. If the register specified as the first operand is greater than the register specified as the third operand, wrap around occurs. If the first and third operands both specify the same register, only 4 bytes are stored.
STM R1,R5,L1 STM R6,R4,L2 * R1,R2,R3,R4 and R5 are stored * R6,R7, R0,R1, R4 are stored

95

16.6 Load and Test (LTR) The contents of the register specified as the second operand are loaded into the register specified as the first operand and the Condition Code is set to reflect the value of the binary integer word copied. Often both operands are specified as the same register in which case the only effect is to set the Condition Code.
CC=0 Zero CC=1 Negative CC=2 Positive

16.7 Load Positive (LPR) The absolute value of the signed binary value in the register specified as the second operand is loaded into the register specified as the first operand. Both operands may be the same register. The Condition Code is set.
CC=0 CC=1 CC=2 CC=3 Zero, no overflow Not possible Greater than zero, no overflow Overflow

16.8 Load Negative (LNR) The 2s complement of the absolute value of the signed binary integer contained in the register specified as the second operand is loaded into the register specified as the first operand. The Condition Code is set.
CC=0 CC=1 CC=2 CC=3 Zero Negative Not possible Not possible

96

17 Bit Operations
Bit operations involve modification or manipulation of individual bit in an operand. The basic Boolean operations, AND, OR, EXCLUSIVE and OR can be RR, RX, SI or SS instructions. The COMPLEMENT and SHIFT instructions work only on operands in registers. 17.1 Boolean Instructions In the Boolean instructions (AND, OR, and EXCLUSIVE OR), the designated operation takes place between the corresponding bits of each operand and the result replaces the first operand. 17.1.1 AND (N, NR, NI, NC) In the bitwise AND instructions, corresponding bits from each operand are and'ed together. If both bits are 1, the resulting bit is 1. If either or both bits are 0, the resulting bit is 0. The bitwise AND instructions are:
1.

NR - RR format - the bits of the operand in the register designated as the second operand are and'ed with the bits of the register designated as the first operand and the result is placed in the first operand. N - RX format - the bits from the word in memory addressed by the second operand are and'ed with the bits in the register designated as the first operand and the result is placed in the first operand. NI - SI format - the bits in the immediate operand are and'ed with the bits of the byte in memory designated as the first operand and the resulting byte replaces the byte in memory. NC - SS format - from 1 to 256 bytes beginning at the address specified by the second operand are and'ed with the corresponding bytes beginning at the address specified by the first operand with the resulting bytes replacing the bytes from the first operand. The number of bytes is determined by an 8 bit length field.

2.

3.

4.

17.1.2 OR (O, OR, OI, OC) In the bitwise OR instructions, the corresponding bits from both operands are or'ed. If either or both bits are 1, the resulting bit is 1. If both bits are 0, the resulting bit is 0. The bitwise OR instructions are:
1.

OR - RR format - the bits of the operand in the register designated as the second operand are or'ed with the bits of the register designated as the first
97

operand and the result is placed in the first operand.


5.

O - RX format - the bits from the word in memory addressed by the second operand are or'ed with the bits in the register designated as the first operand and the result is placed in the first operand. OI - SI format - the bits in the immediate operand are or'ed with the bits of the byte in memory designated as the first operand and the resulting byte replaces the byte in memory. OC - SS format - from 1 to 256 bytes beginning at the address specified by the second operand are or'ed with the corresponding bytes beginning at the address specified by the first operand with the resulting bytes replacing the bytes from the first operand. The number of bytes is determined by an 8 bit length field.

6.

7.

17.1.3 Exclusive OR (X, XR, XI, XC) In the bitwise Exclusive OR instructions corresponding bits from both operands are exclusive or'ed with one another. If both bits are 0 or if both bits are 1, the resulting bit is 0. If one bit is 0 and the other is 1, the resulting bit is 1. The bitwise EXCLUSIVE OR instructions are:
1.

XR - RR format - the bits of the operand in the register designated as the second operand are exclusive or'ed with the bits of the register designated as the first operand and the result is placed in the first operand. X - RX format - the bits from the word in memory addressed by the second operand are exclusive or'ed with the bits in the register designated as the first operand and the result is placed in the first operand. XI - SI format - the bits in the immediate operand are exclusive or'ed with the bits of the byte in memory designated as the first operand and the resulting byte replaces the byte in memory. XC - SS format - from 1 to 256 bytes beginning at the address specified by the second operand are exclusive or'ed with the corresponding bytes beginning at the address specified by the first operand with the resulting bytes replacing the bytes from the first operand. The number of bytes is determined by an 8 bit length field.

2.

3.

4.

17.2 Complement LCR There is only one complement instruction: LCR. The LCR loads into the register designated as the first operand the 2s complement of the contents of the register designated as the second operand. Both register designations may be the same in which case the contents of the designated register are complemented. A value of zero in is unchanged (the 2s complement of 0 is 0). The condition code is set:
98

CC=0 CC=1 CC=2 CC=3

Result 0 Result negative Result positive Overflow

17.3 Shift The shift operators move bits either left or right in one or more registers. They are classed as either logical or arithmetic. Logical shifts treat all bits the same. There is no special treatment of the sign bit position. No overflow can occur. On both left and right shifts a zero bit replaces the shifted bit. Arithmetic shifts are cognizant of the sign bit. When shifting to the left, if a bit unlike the sign bit is shifted into the sign bit position, an overflow occurs. On a right shift, bits like the sign bit replace the shifted bits. Additionally, shifts may be either single (only one register participates) or double (two registers participate). In the case of a double shift, the register specified as the operand must be the even register of an even-odd pair. For all the shift instructions the first operand designates the register to be shifted and the second operand indicates the number of bit positions to be shifted. The number of bits to shift is calculated from the base and displacement of the second operand. If the base is specified as zero, the amount of shift is the displacement. If the base is specified as any other register, the contents of the register plus the value of the displacement are the number of bits to shift. In many cases only the displacement is specified such as:
SLL R5,10

In this case the second operand is shorthand for:


0(R0)

and thus the instruction means to shift the contents of R5 left 10 binary positions. Shifting a binary number to the left has the effect of multiplying it by 2; shifting it 2 positions to the left multiplies by 4; 3 positions by 8 and so forth. Similarly, shifting a binary number to the right has the effect of dividing by 2,4,8, etc. 17.3.1 Logical (SRL, SRDL, SLL, SLDL) The logical shift instructions are:

99

SRL - shift right logical (single) SRDL - shift right double logical SLL - shift left logical (single) SLDL - shift left double logical

The Condition Code remains unchanged. Zeros are provided to replaced the shifted bits. 17.3.2 Arithmetic (SRA, SRDA, SLA, SLDA) The arithmetic shift instructions are:
SRA - shift right arithmetic (single) SRDA - shift right double arithmetic SLA - shift left arithmetic (single) SLDA - shift left double arithmetic

The Condition Code is set:


CC=0 CC=1 CC=2 CC=3 Result is 0 Result is negative Result is positive Overflow

An overflow can occur only in left shifts when a bit unlike the sign bit is shifted into the sign bit position. During left shifts, zeros are supplied to replace the shifted bits. During right shifts, bits like the sign bit are provided to replace the shifted bits. 17.4 Test Under Mask (TM) The TM instruction is an SI instruction. The bits of the byte in memory addressed by the first operand corresponding to those bits with a value or 1 in the the immediate operand are tested and the Condition Code is set.
1. 2. 3.

If all the tested bits are 0, the Condition Code is set to 0. If the tested bits are mixed 1s and 0s, the Condition Code is set to 1. If all the tested bits are 1s, the Condition Code is set to 3.

For example, if a byte in memory at label L1 has the value:


0011 0101

The instruction:
TM L1,B'11001010'

will set the Condition Code to 0 (all tested bits were 0s). The instruction:
TM L1,B'00110101'

will set the Condition Code to 3 (all tested bits were 1s). The instruction:
TM L1,B'00001111' 100

will set the Condition Code to 1 (tested bits were mixed). 17.5 Test and Set (TS) The TS (Test and Set) instruction is an SI instruction but the immediate operand is omitted. The instruction tests the leftmost (high order) bit of the byte in memory designated by as the first operand. If the bit is 0, the Condition Code is set to 0. If the bit is 1, the Condition code is set to 1. Regardless of the result, the byte in memory is set to 1111 1111. The original purpose of this instruction was to provide an uninterruptible way in which to see if a resource is available and mark it as in use. Example, consider the case where a byte is used to indicate that some block of memory is available with all 0s indicating it is available for allocation and 1s indicating it is in use. If the byte is all zeros a TS on the byte will reflect this in the Condition Code and mark the byte as all 1s. On the other hand, if the block is allocated and the byte is all 1s, a TS will indicate this and have no real effect (the byte is still all 1s). What this instruction avoids is the situation where a program tests a byte, see 0s, but before it can set the byte, an interrupt occurs and another program gains control. Likewise this program tests the same byte, sees 0s and sets the byte to 1s. When the first program regains control it believes that the byte is 0s, likewise marks it as 1s and now two programs believe they own the block of memory. The TS instruction is uninterruptible - the testing and setting take place in one operation.

18 Decimal Arithmetic
18.1 PACK Both operands are in memory. The operands are processed from right to left. The result occupies the first operand. The second operand is treated as a zoned decimal number. The Condition Code is unchanged. The zone and digit of first byte of the source are reversed and placed in the right most byte of the target. Subsequent bytes (to the left) of the source are read, the zone removed and the digit portion stored in the next available half byte going right in the target. If the second operand is short, the first operand is padded to the left with zeros. Further examples are given in Chapter 21. 18.2 Add, Subtract, Zero and Add Positive (AP, SP, ZAP)
101

In these instructions the first operand is the target and the second is the source. The first operand must be large enough to contain the result or a Decimal Overflow occurs. In the case of the ZAP, the result is the equivalent of an addition to zero. The Condition Code will be zero if the result is zero; 1 if the result is less than zero; 2 if the result is greater than zero and 3 in the case of overflow. 18.3 Multiply Packed (MP) The multiplier (the second operand) is multiplied by the multiplicand (first operand) and the result is placed in the first operand. The multiplier may not be longer than 15 digits and must be shorter in length than the multiplicand. In order to prevent an overflow from occurring, the multiplicand must include at least as many leading bytes of zeros as the number of bytes in the multiplier. If this is not the case, a data exception occurs. The Condition Code is unchanged. 18.4 Divide Packed (DP) The first operand is the dividend and the second operand is the divisor. The results are a quotient and a remainder which wil replace the dividend. The divisor may not be longer than 15 digits. The quotient occupies the leftmost bytes of the result. Its length is equal to the difference between the length of the dividend (L1) and the divisor (L2). The remainder occupies the remaining bytes of the first operand. A Decimal Divide exception occurs in the case of divide by zero or a quotient too large to fit in the digits available. The Condition Code is unchanged. 18.5 EDIT (ED) The ED instruction is used to convert packed decimal number to zoned decimal (printable) values. The first operand is a set of pattern codes that control the formatting process and the second operand is the packed number to be converted. The result replaces the first operand. The first byte of the first operand is the Fill byte. It will be placed in the leading bytes of the result in place of non-significant leading zeros. Following the fill byte are a collection of pattern bytes and message bytes. When the instruction begins the significance indicator is off. It stays off until a significant digit (i.e., non-zero) is encountered or turned on by a pattern byte. When the significance indicator is off, zeros in the source are replaced by the fill byte. If the significance indicator is off, message bytes are replaced by the fill byte. If the significance indicator is on, they remain in the result.

102

There are two main pattern bytes: X'20' and X'21'. The first is called the digit selector. If encountered in the format, the next digit in the source field is selected. If the digit is zero and the significance indicator is off, the fill byte replaces the digit selector. If the digit is non-zero or the significance indicator is on, the digit is converted to zoned decimal and replaces the digit selector. If a non-zero digit is selected, the significance indicator is turn on if not already on. The pattern code X'21' is called the significance starter. It acts like the X'20' above except it always turns the significance indicator on if not already on. Turning the significance indicator on affects the next digit, not the current digit. When the last digit of a number is selected, the sign is examined. If the sign is positive (CAFE), the significance indicator is turned off. If the sign is negative, it remains on or is turned on. The effect of this is to leave or replace trailing characters in the format. For example, the final characters in the format could be (DB) indicating a debit or negative balance. The (DB) will be replaced by the fill byte if the number is positive but remain in the result if the number is negative. (Note: you often see this in bank statements where a negative value is indicated at the end of the number). Further examples are given in Chapter 21. 18.6 Miscellaneous Decimal Related Instructions 18.6.1 UNPACK (UNPK) The UNPK instruction converts its packed decimal second operand to zoned format. Except for the digit, each digit in the source becomes a byte in the result with a leading X'F' zone. In the case of the last digit, it becomes the digit in the final result byte but the zone becomes the sign. Further examples are given in Chapter 21. 18.6.2 Move Numerics (MVN) This instruction uses only one length field. The right-most 4 bits of each source byte (second operand) are moved to the right-most 4 bits of the target operand (first operand). The Condition Code is unchanged. 18.6.3 Move Zones (MVZ) This instruction uses only one length field. The left-most 4 bits of each source byte (second operand) are moved to the left-most 4 bits of the target operand (first operand). The Condition Code is unchanged.

103

104

19 Multiple Base Registers


19.1 Base Register Addressing As we have seen, memory resident operands in RX, SI, SS and RS instructions are addressed by a combination of index register, base register and displacement (in RX format), or displacement and base (in all others). In the case of RX instructions, the index register is seldom used and addressing of the memory operand is usually accomplished by only the base register and the displacement. When addressing a memory operand with base and displacement, the base register (any register between R1 and R15 but usually R13 or lower) contains the absolute address of a location in memory in our program. The address of a memory resident operand is calculated as a forward displacement from the location in memory contained in the base register. Displacements in the basic architecture are positive 12 bit numbers and thus can range from 0 to 4095 (more recent instructions may use longer displacements). At the beginning of an assembly language program we load the base register with the absolute address of a location near the beginning of the program and then tell the assembler which register we have selected to be the base register and where it is pointing. From this point on, the assembler will calculate the addresses of labels as displacements from the point in the program whose address is contained in the base register. One problem with the base-displacement addressing scheme used in the IBM mainframe is that the maximum displacement from a base register is 4095 bytes. That is, the assembler cannot address a label which is more than 4095 bytes from the address contained in the base registers. When a label is within this window of addressability we say that the label is within using of the base register. Programs, however, are obviously longer than 4095 bytes in the real world. The base register addressability problem is solved by having multiple base registers with the second pointing 4096 bytes beyond the first and so forth. However, for large programs, there are usually not enough spare registers so other techniques are employed. In these larger programs, blocks of code establish their own base register on entry so the same register or registers are re-used. When there is more than one base register available, the assembler selects which to use. In the case were the scope of two base registers overlaps (the 4096 byte window beginning with the byte pointed to be a base register), the assembler selects the register that would yield the smaller displacement. Loading a base register with the an absolute address can be accomplished by a BALR instruction in which the second operand is specified as R0. In this case, no branch takes place because the second operand is R0. However the first operand receives the absolute address of the byte immediately following the BALR.

105

So, for example, if we want to establish R12 as a base register, we would first want to load it with the absolute address of where we are in the program then inform the assembler that R12 is a base register and tell the assembler where the contents of R12 are pointing. This could be accomplished with the following:
BALR R12,R0 USING *,R12

The above loads the absolute address of the byte following the BALR into R12 then tells the assembler to use R12 as a base register. The format of the assembler directive USING is an address expression followed by one of more register designations. In this case the address expression is asterisk meaning here. The first register is assumed to contain the address of the address expression and subsequent registers, if any, are assumed to contain the address expression plus 4096, 8192, and so forth. Note that the USING follows the BALR. This is because the address in R12 is the address of the byte immediately following the BALR and, hence, as the asterisk refers to the current address, the USING needs to be after the BALR. Had it been the other way around, the assembler would assume that the address in R12 was the address of the BALR. You will also note there is a DROP directive. This discontinues use of a base register. The use of USING and DROP are assemble-time directives - they cover areas of code and are not run time states. That is, from the point or line in a program where a register is designated as a base register by USING until the point or line where it is dropped by a DROP, the register may be selected by the assembler to construct a base/displacement address. Outside that area, the register is not a base register. When operands can be addressed with a valid base and displacement combination, they are said to be in using; if an operand is beyond the maximum 4095 byte displacement of any base register, the operand is said to be out of using. As there are only fifteen register that can be used as base registers, most large programs frequently re-use base registers rather than using many registers at once. However, it is not unusual to have more than one base register available for addressing. In this case the programmer needs to be sure to load each register correctly. An example can be seen in Figure 42.
1 2 3 4 5 6 BALR R12,R0 USING *,R12,R11,R10 LA R11,2048(R0,R12) LA R11,2048(R0,R11) LA R10,2048(R0,R11) LA R10,2048(R0,R10 Figure 42 Multiple Base Registers

The code in Figure 42 first loads R12 with the absolute address of the byte immediately beyond the BALR. Then it tells the assembler that registers 12, 11 and 10 maybe used as base registers. The assembler assumes that these registers are set to 4096 and 8192 bytes apart, respectively. Then, the LA instruction is used to set
106

R11 and R10 from the value in R12. Note that since the maximum displacement is 4095, two LAs are required to add 4096.

107

108

20 System Macro Input/Output


Input/output operations on a mainframe traditionally have been record oriented. In most cases these involved fixed length records. Access to files is by means of input/output macros that are specific to the type of data being accessed. In the examples up to this point, the ASSIST pseudo-macros have been used as they simplify the process for novice users. In this section we introduce several basic QSAM (Queued Sequential Access Method) macros and show their usage. In order to perform either input or output it is first necessary to define a DCB (Data Control Block). The DCB is a table built partly by the user and partly by the system which defines the file being operated upon. The DCB has many options, only a few are shown here. A DCB is constructed with the DCB macro. Once a DCB has been constructed, a file is opened with the OPEN macro. The OPEN macro connects your program's DCB with the file being accessed. The OPEN and the DCB specify if the file is being opened for input, output or both. Once a file is open, you may access the file with several macros. Among these are GET and PUT. Others are also possible. When file processing is finished, you should issue a CLOSE macro to finalize any output, free buffers and disconnect from the file. In the example in Figure 43, 34 byte input records are read from one file and written to another. The input DCB is named INDCB and the output DCB is named OUTDCB. The DCB parameters used are as follows:
LRECL=34 RECFM=FT MACRF=GM MACRF=PM EODAD=ATEND DDNAME=IN DDNAME=OUT logical record length of 34 bytes fixed length records - ASCII/EBCDIC conversion the GET file access macro will be used the PUT file access macro will be used branch to label ATEND on end of input data DDNAME name to be opened and read DDNAME name to be opened and written

The LRECL determines the size of the input or output records. In the actual input file, the text records are actually 32 bytes long. The extra two bytes in the LRECL (and the associated input data area REC) allow for the carriage-return/line-feed (CR/LF) characters that are at the end of each line in a Microsoft text file. Note: Linux and Unix based systems have only one character at the end of a line, a linefeed (LF). The input records must each consist of 32 bytes of text. The RECFM parameter tells the system that the input and output files will consist of fixed length records. The MACRF parameter tells the system that the GET or PUT macros will be used for actual input and output. For input operations, the EODAD parameter tells the system the label to be branched to upon encountering the end of file. This parameter is not used for output DCBs.

109

Finally, the DDNAME is used to link the program's DCB to an actual file. In the z390 emulator running of a Windows based PC, this will be the name of an environment variable set by the user which will have the actual file name to be used. Before running the program, the user needs to create environment variables IN and OUT and set them to values that are valid file names. For example, to the Command Prompt, type:
set IN=IN.DAT set OUT=OUT.DAT

When the assembly language program runs, it will attempt to read from the file IN.DAT and write to the file OUT.DAT. You can see the complete list of environment variables by typing the command set by itself. You can delete an environment variable by entering a set command equating variable with nothing such as:
set IN=

The selection of the DDNAMEs IN and OUT was arbitrary. You may use any names that the system accepts. In the program in Figure 43, after the usual initialization, the DCBs are opened by the OPEN macro for OUTPUT and INPUT, respectively. They could have also been opened individually with code such as:
OPEN OUTDCB,OUTPUT OPEN INDCB,INPUT

The WTO macro writes to the console that the OPENs succeeded. Next the program enters a three line infinite loop consisting of the GET and PUT macros and the unconditional branch. The GET macro reads from the file associated with INDCB into the data area REC and the PUT macro writes from the data area to the output file associated with OUTDCB. When the GET encounters the end of file, the GET macro causes a branch to the label ATEND as determined by the EODAD=ATEND parameter in the INDCB. The CLOSE macro at ATEND flushes the buffers and disconnects from the output file. Failure to CLOSE an output file will usually result in the loss of about 2 lines of data. The file OUT.DAT will be an identical copy of the input file.

110

21 Converting Between Zoned, Packed and Binary


Arithmetic on an IBM mainframe can be carried out in binary integer, packed decimal and floating point modes. In this section we show how to convert between printable character, packed decimal and binary. Floating point is not covered here. When numbers are read from character (EBCDIC) input, they are in Zoned Decimal format. For example, the printable number 1234 in EBCDIC appears as:
X'F1F2F3F4'

Arithmetic may not be performed on these character representations of numbers. Instead, they must be converted to one of the numeric types, such as Packed Decimal or Integer (binary).
1 2 3 COPY 4 5 6 7 8 9 LOOP 10 11 12 * 13 * 14 * 15 ATEND 16 17 * 18 * 19 * 20 OUTDCB 21 22 INDCB 23 * 24 * 25 * 26 REC 27 PRINT NOGEN EQUREGS SUBENTRY OPEN (OUTDCB,(OUTPUT),INDCB,(INPUT)) WTO '*** FILES OPEN ***' GET PUT B INDCB,REC OUTDCB,REC LOOP read a record write the record loop

EOJ processing CLOSE INDCB SUBEXIT File DCB's DCB DCB LRECL=34,RECFM=FT,MACRF=PM,DDNAME=OUT LRECL=34,RECFM=FT,MACRF=GM,EODAD=ATEND,DDNAME=IN

INPUT RECORD DS END CL34 COPY Figure 43 QSAM Input/Output

Arithmetic may not be performed on these character representations of numbers. Instead, they must be converted to one of the numeric types, such as Packed Decimal or Integer (binary). A Packed Decimal is a string of bytes containing in each half byte a value (in bits) from 0 to 9 except for the last half byte. The last half byte contains the sign of the number. The hex codes C,A,F, and E mean the number is positive and the codes D and B mean its negative. Thus, the above Zoned Decimal number, in packed format would be:
X'01234F' 111

In this format, it can be seen that the zones have been eliminated and a sign appended. Packed decimal numbers can occupy up to 16 bytes and thus can represent numbers up to 31 digits in length. packed decimal is especially useful for business applications where many digits of accuracy are required. Packed decimal operations do not create round-off errors that are common with floating point numbers. We use the PACK instruction to convert a positive zoned decimal number to packed decimal. The PACK instruction removes the zones and packs the numerics except for the last byte of the zoned number where the zone and numeric are swapped. Since the zone of a text number is always F, all packed numbers appear to be positive (sign of F). To change the sign, we must modify the numeric portion of the last byte. The PACK instruction packs into the first operand from the second. Each operand may be up to 16 bytes in length. Once a number is in packed format, you may do arithmetic on it. While packed or decimal arithmetic is slower than binary arithmetic, it can handle more digits of accuracy and it does not need any further conversion. On the other hand, using a 32 bit binary value limits the results to about +/- 2 billion (the range of values is much greater for 64 bit binary numbers, however). With both 32 and 64 bit binary numbers additional conversion is required from/to packed format. To read in a number in and convert it to binary, you first must pack the number (PACK is very fast), then perform a CVB (convert to binary). The CVB instruction converts a packed number to binary leaving the result in a register. The CVB is nontrivial. For many commercial transactions where a record is read and updated (by adding or subtracting) then quickly written back to disk, packed arithmetic is faster and more flexible. The basic set of packed arithmetic instructions are:
AP SP MP DP CP ZAP Add Packed Subtract Packed Multiply Packed Divide Packed Compare Packed Zero and Add Packed

The example in Figure Error: Reference source not found illustrates some basic packed arithmetic operations. It reads in a table of positive numbers, packing them and adding them into a sum then prints the total and the average. When using the z390 emulator for the program in Figure Error: Reference source not found you need first to establish the connection between the DDNAME=IN and the actual input file. This is done with the Windows command:
set IN=INPUT1.DAT

where INPUT1.DAT is the name of the input file. Note: either upper or lower case in the above is acceptable.
112

The input file for the program in Figure Error: Reference source not found is shown at the end. Note: leading blanks are also permitted as a blank (X'40') and a zero (X'F0') both PACK to zeros. The program in Figure Error: Reference source not found operates as follows (see also Chapter 18):
1. 2.

3.

4. 5.

The input file is opened on line 4 and connected with the DCB INDCB. Line 6 through 10 are a loop in which lines of data are read (line 6), echoed back to the console (line 7), PACKed (line 8) and summed into SUM (line 9). The branch instruction on line 10 causes the loop to iterate. The loop ends when there is no more input due to the EODAD=ATEND option in the DCB on line 22. This triggers a branch from the GET on line 6 to the label ATEND when the GET encounters the end of file. AT line 15 the input file (DCB) is closed. On line 16 the edit (ED) instruction is used to convert the packed value in SUM to printable characters in RSLT. Initially RSLT has an edit pattern in it as can be seen in line 38. This pattern will convert up to seven packed digits to characters with a padding byte of blank. Zero suppression will not apply to the last digit. Line 17 writes the output.

The program in Figure Error: Reference source not found is fine as far as it goes but it only handles positive number. The program in Figure 45 solves this problem by taking minus signs into account. A sample execution can be seen in Figure 46 (note input echoed to the console). The program in Figure 45 operates as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 PRINT ADD LOOP NOGEN EQUREGS SUBENTRY OPEN (INDCB,(INPUT)) GET WTO PACK AP B INDCB,REC MF=(E,RECX) NBR,REC(8) SUM,NBR LOOP * * * * * READ A RECORD WRITE THE VALUE TO CONSOLE PACK THE NUMBER ADD TO TOTAL READ ANOTHER RECORD

* * * ATEND

EOF - BRANCH HERE WHEN OUT OF RECORDS CLOSE INDCB ED RSLT,SUM WTO MF=(E,RSLTX) SUBEXIT File DCB's DCB LRECL=10,RECFM=FT,MACRF=GM,EODAD=ATEND,DDNAME=IN Figure 44 Decimal Arithmetic (continued on next page) * DONE WITH INPUT * UNPACK AND FORMAT RESULT

* * * INDCB

113

23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41

* * * RECX REC RECEND NBR SUM RSLTX RSLT RSLTEND

input record DC DC DS EQU DS DC DC DC DC EQU END AL2(RECEND-*-2,0) * SUB 2 TO AVOID CR/LF C'INPUT=' CL10 * INPUT RECORD + 2 BYTES FOR CR/LF * PL8 PL4'0' AL2(RSLTEND-*,0) C'ANSWER=' X'4020202020202120' * EDIT PATTERN * ADD

Sample input data: 00000010 00000020 00000030 00000040 Figure 44 Decimal Arithmetic (continued) 1.

2.

3.

4. 5.

6. 7. 8.

9.

The input loop is basically the same as in Figure 44. Each input record is treated as an 8 byte number and is assumed to be correct (that is, the program does minimal error checking). On line 10, it loads the address of the input record into R3 and sets a flag (NEGFLAG) to character zero. If it detects a minus sign, this flag will reset to character one. A loop beginning on line 12 and extending through line 40 examines each character in the input. If it finds a minus sign, NEGFLAG is set to character 1. The loop scans the input until it finds a leading digit, a plus or a minus. It continues scanning the input is it sees a blank. If a sign is detected, the program sets NEGFLAG as appropriate and replaces the sign by a blank (we do not want the sign present when we pack the number). The number is PACKed (line 41). After the number is PACKed, if NEGFLAG is 0, we add the result. The input number was positive. If NEGFLAG is 1, we And Immediate the last byte of the packed number with the mask byteX'FD' on line 44. The high order F16 in the mask byte will preserve the contents of the high order digit of the last byte. The low order digit of the last digit of the packed number must be F16 because it is the zone of the last digit of the input. ANDing this with D16 results in it becoming D16 as well - a minus sign in packed format. Now we add the negative number to the sum. At end of input the results are printed.

114

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55

ADD LOOP

PRINT NOGEN EQUREGS SUBENTRY OPEN (INDCB,INPUT)) GET WTO LA MVI INDCB,REC MF=(E,RECX) R3,REC NEGFLG,C'0' 0(R3),C'-' MINUS 0(R3),C'+' PLUS 0(R3),C' ' BLANK 0(R3),C'0' NUM * READ A RECORD * WRITE RECORD TO CONSOLE * MAKE FLAG 0 * MINUS SIGN FOUND? * PLUS SIGN FOUND? * BLANK FOUND? * 0 OR GREATER NUMERIC FOUND?

L1

CLI BE CLI BE CLI BE CLI BNL

ERR MINUS

WTO 'BAD DATA - EXITING' SUBEXIT MVI MVI B MVI B CLI BH LA LA CR BL PACK CLI BNE NI AP B NEGFLG,C'1' 0(R3),C' ' PCK 0(R3),C' ' PCK 0(R3),C'9' ERR R3,1(R0,R3) R4,REC+8 R3,R4 L1 NBR,REC(8) NEGFLG,C'1' ADD NBR+7,X'FD' SUM,NBR LOOP * SET FLAG TO 1 * MAKE MINUS A BLANK * MAKE PLUS A BLANK * 9 OR LESS? * MUST BE BAD DATA * * * * INCREMENT POINTER GET ADDRESS OF END COMPARE ADDRESSES LOOP IF NOT DONE

PLUS NUM BLANK

* IS THIS NUMBER NEGATIVE? * NO * YES - MAKE SIGN X'D' * LOOP

ADD * * * ATEND

EOJ processing CLOSE INDCB WTO 'DONE*******' ED RSLT,SUM WTO MF=(E,RSLTX) SUBEXIT Figure 45 Negative Decimal Arithmetic (continued on next page)

115

56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81

* * * INDCB * * * RECX REC RECEND NBR NEGFLG SUM RSLTX RSLT RSLTEND MSG

File DCB's DCB LRECL=10,RECFM=FT,MACRF=GM,EODAD=ATEND,DDNAME=IN

input record DC DC DS EQU DS DC DC DC DC DC EQU DC END AL2(RECEND-*-2,0) * SUBTRACT 2 TO AVOID CR/LF C'INPUT=' CL10 * INPUT RECORD + 2 BYTES FOR CR/LF * PL8 C'0' PL4'0' AL2(RSLTEND-*,0) C'ANSWER=' X'4020202020202120' * EDIT PATTERN * C'DONE***************' BEGIN

Figure 45 Negative Decimal Arithmetic (continued)


C:\DOCUME~1\user\ASMLAN~1>asmlg addloop1.mlc C:\DOCUME~1\user\ASMLAN~1>rem asmlg assemble, link, and go from mlc to 390 execution C:\DOCUME~1\user\ASMLAN~1>echo 12:42:32 addloop1 MZ390 START 12:42:32 addloop1 MZ390 ENDED 12:42:32 addloop1 LZ390 START 12:42:32 addloop1 LZ390 ENDED 12:42:32 addloop1 EZ390 START INPUT=00000001 INPUT=-0000002 INPUT=00000003 DONE******* ANSWER= 2 off USING RC= USING RC= USING z390 V1.5.03 ON J2SE 0 SEC= 0 MEM(MB)= 46 z390 V1.5.03 ON J2SE 0 SEC= 0 MEM(MB)= 15 z390 V1.5.03 ON J2SE 1.6.0_18 05/16/11 IO=2414 1.6.0_18 05/16/11 IO=70 1.6.0_18 05/16/11

Figure 46 Example Execution

116

22 Programming Examples
22.1 Console Input/Output In Figure 22 on page 65 we saw an example of reading and writing files using the XREAD and XPRNT macros. In Figure 43 on page 111 we saw an example of QSAM based file input/output using the GET and PUT macros. Here we examine console based input output using the WTO and WTOR macros. You may read and write directly to the console using the WTO and WTOR macros. Alternatively, you may read and write files using the GET and PUT macros or the ASSIST XPRNT and XREAD macros. Here we demonstrate the WTO and WTOR macros which are normally available in the IBM assembler. The WTO macro can be used to write a constant string to the console (your command prompt window) or it can be used to write a string stored in memory. The simplest form is:
WTO 'STRING TO BE WRITTEN'

The above will write the contents within the quote marks (up to 119 characters) to the console window. Alternatively, you can write a string stored in memory to the console with:
WTO MF=(E,MSG)

where MSG refers to a data area such as the following:


MSG DC AL2(MSGEND-*,0) MSG1 DS CL20 MSGEND EQU *

The first line, MSG, consists of 2 half words. The first will contain the length of the string to be written (including the half words). The second half word contains a zero. This is then followed by the data area which will contain the string to be written, in this case a string of length 20 whose contents are filled-in somewhere else in the program. The label MSGEND has as its value the location counter value of this point in your program. This value is used in the line with label MSG. The value of the first half word it the difference between the location counter at MSG (*) and the value of the location counter after the string and half words. The WTOR macro is similar, its parameters are a message to be written, an area in memory to receive a reply, an optional length or the input field, and an event control block (ECB) (A full word binary initially set to zero). If the length is omitted, it will be determined from the implied length of label. The macro is followed by a line with the WAIT macro with the ECB from the WTOR. This pauses the program until the reply has been entered.

117

The example in Figure 47 gives an example where a message is written by the simple form of the WTO macro. Next, another message is written by the WTOR macro and the program which waits for a reply. The reply is then printed using the extended form of the WTO.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 PRINT NOGEN EQUREGS WTO SUBENTRY WTO 'CONSOLE READ/WRITE' WTOR 'ENTER A STRING',STRING,20,EV WAIT ECB=EV WTO MF=(E,MSG) SUBEXIT MSG DC AL2(STREND-*,0),C'YOU TYPED ' STRING DS CL20 STREND EQU * EV DC F'0' END WTO Figure 47 Console I/O using WTO/WTOR

22.2 Random Numbers Many random number generators operate on a formula of the form:
x = ( a * x + b) % N

where x is initially the seed, a and b are constants and N is usually a power of 2. The values of a and b determine the overall performance of the program. Each iteration of the formula produces a new random number until the sequence repeats. If N is a power of 2, then the modulo operation can be performed as a shift rather than as a real division operation. For example, if N is 32768 or 215 a divide by 32768 can be accomplished by a right shift of 15 bits. The result will be the quotient. The remainder, however, will be the bits shifted out of the register, that is, the low order 15 bits of the original number. Thus, we can obtain modulo 32768 on a binary number by zeroing out all bits but the lower 15. Thus can be accomplished by and And instruction. For example, in a 32 bit word, we would And the word with the mask:
X'00007FFF'

whose lower 15 bits are:


B'0111111111111111'

Figure 48 contains a short C program to generate 1000 random numbers with this technique. The values for a and b are 214013 and 2531011, respectively, were taken from:
118

http://rosettacode.org/wiki/Random_number_generator_(included) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include <stdio.h> int main() { unsigned int i, a, b, x, N; a=214013; b=2531011; N=32768; x=79; // seed for (i=1; i<1000; i++) { x = ( a * x + b ) % N; printf("%d\n",x); } } Figure 48 Random Numbers in C

The assembly language equivalent of the program in Figure 48 can be see in Figure 49. Note that the Multiply instruction on line 11 addresses the even register of the even/odd pair. Also note the Add Logical instruction on line 13. This causes the number to be treated as an unsigned quantity for purposes of addition. The Multiply instruction, on the other hand, has a 64 bit result only the lower 32 bits of which we use and thus the matter of overflow is not an issue.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 PRINT NOGEN EQUREGS SUBENTRY WTO 'RANDOM NUMBERS' LA R2,8(0,0) LOOP L R5,X M R4,A AL R5,B N R5,MASK ST R5,X XDECO R5,OUT XPRNT OUT,12 BCT R2,LOOP SUBEXIT A B X MASK OUT DC DC DC DC DS F'214013' F'2531011' F'79' X'00007FFF' CL12 * LOAD R2 WITH 8 * LOAD SEED OR LAST VALUE * MULT BY A * * * * ADD (LOGICAL) B MODULO 32768 STORE RESULT PRINT RESULT

RAND

* DECR R2, BRANCH IF > 0

END RAND Figure 49 Random Number Generator

119

22.3 Convert Infix to Suffix In the example in Figure 50 we use a simplified algorithm to convert fully parenthesized infix notation the suffix notation. In infix notation, the operators appear between the operands. In suffix notation, the operands appear after the operands. In our example we assume that all operands are a single character, there are no embedded blanks in the input string and that the input string has a dollar sign at the end as a terminator character. The algorithm uses a stack. In a stack, when we place a new item on the stack, the existing items are pushed down. When we remove an item, the remaining items pop-up. Stacks are very useful in many algorithms and the are an example of a last in, first out data structure. The (simplified) infix-to-suffix procedure is as follows:
1. 2. 3. 4. 5. 6.

Examine the next character in the input. If it is a open parenthesis, ignore it and go to step 1. If it is a dollar sign, done. Check results. if it is an operand, copy it to the output string. If it is an operator, push it on the stack. If it is a close parenthesis, pop the top element on the stack to the output string.

When done, the output should contain the translation to suffix and the stack should be empty. Fore example:
((A+B)*(C-D))$ yields AB+CD-*

The program works as follows:


1.

On line 3 we print in the infix expression to be converted. The figure L'IN in the XPRNT tells the assembler to calculate the implied length of the data declared at label IN and place the number here. In lines 4 and 5 we copy blanks into the output field OUT. The easy way to do this is to place a blank in the first position (line 4) and then propagate it across the remaining 19 positions (line 5). The MVC on line 5 moves is offset by one from its source to its target and the length is 19, not 20. Thus, byte 0 (the blank) is copied to byte 1 then byte 1 is copied to byte 2 and so forth. We load our main registers in lines 6 through 8. R2 will point to the current byte in the input string, R3 will point to the next available byte in the output string, and R4 will point to the next available byte in the stack. The stack will start empty (R4 points to the start of STACK) and grow to higher addresses in STACK when items are added. The address in R4 will always point at the next available position. When items are removed from the

2.

3.

120

stack, the address in R4 will be decremented.


4.

The main input character processing loop begins at line 13. This line and several following it examine each character of input in order to determine how to handle same. On line 13 itself, we test if the byte of input pointed to be R2 is a open parenthesis. If it is not, we branch to label L1. If it is, we increment R2 (line 15) and branch back to the top of the loop (effectively, we ignore the open parenthesis). Note the first operand on the CLI instruction on line 13. It means zero displacement past the address in R2. That is, R2 has the address of the operand. In an SI instruction the first operand is addressed by a combination of displacement and base: D1(B1). In this example, the base position is taken by R2.

5.

Line 15 tests for the terminating dollar sign and branches out of the loop to print the results. Lines 21 through 28 test if the input character is one of the operators. If it is, we branch to the label OPR. If not, on line 29, we branch around the operator handling section to label L2. At OPR we move the operator character onto the stack. Remember, R2 points to the operator and R4 points to the next available position in the stack. The MVC on line 31 copies the operator byte from the input string to the stack. Again, the displacements are zero because the registers contain the entire address. The 1 in the first operand is the length. We must provide the length as the assembler can not calculate an implied length (it needs a label to do this). On lines 32 through 34 we increment the input and stack pointers then branch to the top of the loop for the next input character. On line 36 we test if the input is a close parenthesis. If it is not, we branch to label L3. If it is, we decrement the stack pointer and copy the byte from the stack to the next available byte in the output string (pointed to by R3). Then we increment both the input and output pointers. Note that we needed to decrement the stack pointer first because it always points to the next available position. It needs to be decremented to point to the last used position. After the byte from the stack has been copied to the output, the current position in the stack is no longer in use so the stack pointer (R4) is correct. Finally, beginning at line 44, the only alternative is that the character is an operand which we copy to the output string, increment the input and output pointers and branch to the top of the loop. At line 49 we write out the output string and exit.

6.

7.

8.

9.

10.

121

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55

SUFFIX SUBENTRY EQUREGS XPRNT IN,L'IN MVI OUT,C' ' * PUT BLANK IN 1ST POSITION MVC OUT+1(19),OUT * PROPOGATE BLANK ACROSS FIELD LA R2,IN * ADDRESS OF INPUT STRING LA R3,OUT * ADDRESS OF OUTPUT STRING LA R4,STACK * ADDRESS OF STACK * * LOOP TO EXAMINE AND PROCESS INPUT * LOOP CLI 0(R2),C'(' BNE L1 LA R2,1(R0,R2) B LOOP CLI 0(R2),C'$' BE FIN CLI 0(R2),C'+' BE OPR CLI 0(R2),C'-' BE OPR CLI 0(R2),C'*' BE OPR CLI 0(R2),C'/' BE OPR B L2 OPR MVC 0(1,R4),0(R2) A R4,=F'1' A R2,=F'1' B LOOP CLI 0(R2),C')' BNE L3 S R4,=F'1' MVC 0(1,R3),0(R4) A R3,=F'1' A R2,=F'1' B LOOP MVC 0(1,R3),0(R2) A R3,=F'1' A R2,=F'1' B LOOP XPRNT OUT,L'OUT SUBEXIT DC C'((A+B)*(C/D))$' DS CL20 DS CL20 END Figure 50 Convert Infix to Suffix * IS INPUT CHAR ( ? * NO * INCREMENT INPUT POINTER * PROCESS NEXT CHARACTER * IS INPUT CHAR $ ? * YES - END OF INPUT * IS INPUT +. -, * OR / ? * YES

L1

* PUSH OPERATOR ONTO STACK * INCRMENT INPUT POINTER * PROCESS NEXT CHARACTER

L2

L3

FIN IN OUT STACK

22.4 Bubble Sort a Table of Numbers The program in Figure 51 performs a bubble sort on the ten full word binary numbers in the table beginning at label TAB. The program consists of two loops: an outer loop beginning at OUTER and and inner loop beginning at LOOP.
122

The inner loop examines each element of the table from element 0 to element 9 and compares it with the element in the position above it. That is, element 0 is compared with element 1, element 1 is compared with element 2 and so forth until element 9 is compared with element 10. If the value of an element is greater than the value of the element above it, their contents are swapped with one another. When a pair of elements are swapped, a flag is set to indicate that a swap has taken place. After all elements have been examined the flag is examined. If the flag indicates that a pair of elements were swapped, the process is repeated. If the flag indicates that no swap took place, the fort is finished and the results are printed. In the program, R2 is the counter from 0 to 9 and R8 is the swap flag. At the beginning of the outer loop these are both set to zero (lines 4 and 5). Inside the loop we convert the counter in R2 to an offset in R4. That is, while the counter may be 0, 1, 2, ..., we need the actual offset into the table in order to address the elements. These are of the form 0, 4, 8, 12, ... To convert the count into an offset we load the count into R4 and then shift the value left by two bits (lines 7 and 8). A shift left by 2 is the equivalent of multiplying by 4 and thus the value becomes our offset. We load the value from the table into R3 on line 9. Note that the format of the statement in line 9 causes R4 to be used as the index register. This, the value we load is at TAB+R4. Next we load into R5 the value of R4 incremented by 4 (Line 10). We use the LA instruction which sums the value of R4 and the displacement (4) and places the result in R5. This is a common trick for incrementing positive numbers by small amounts and is faster that an RX Add instruction. Now R5 is the offset into the table of the element just above the element whose value is in R3. On line 11 we compare the contents of R3 with the value in the table at offset R5. If the contents of R3 are greater than the value of this element, we branch to the section of code where we swap the contents (SWAP). If we do not swap we advance to line 14 and increment R2 by one using the LA trick. We compare the contents of R2 with 9. If the value in R2 is less than 9 we continue and execute another loop cycle (note: the value in R2 will range between 0 and 8 which is nine values - we want our first offset to be zero). If not, we have completed a full 9 iterations of the inner loop. Next we check the contents of R8. If the value in R8 is zero, it means that all nine iterations of the inner loop resulted in no swap. The table is now sorted so we branch to the location where we print the results. If the contents of R8 are not zero, we branch to the top of the outer loop and reset R2 and R8.
123

In the swap section (lines 21 through 26), we load the values of the two elements that need to be swapped into R6 and R7 and then store the upper element's value (R7) into the lower element slot (R4 offset) then store the lower element's value in the upper element's slot (R5 offset). We place a 1 in R8 indicating a swap has taken place then branch to label INC to increment the counter and test as described above. AT DONE we do a very similar loop based on offsets and print the results. As before, R2 is a counter but this time it will range between 0 and 9 rather than 0 to 8. R4 becomes the offset as before by shifting it left by two. We load the value from the table into R3 then convert it to printable characters and print it (lines 31 through 33). We increment R1 by 1, compare it with 10 and iterate if the value is less than 10.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 BUBBLE SUBENTRY EQUREGS OUTER LOOP SR R8,R8 SR R2,R2 LR R4,R2 SLA R4,2 L R3,TAB(R4) LA R5,4(R0,R4) C R3,TAB(R5) BH SWAP LA R2,1(R0,R2) C R2,=F'9' BL LOOP C R8,=F'0' BE DONE B OUTER * FLAG * COUNTER * * * * MULT by 4 GET VALUE OFFSET OF NEXT VALUE COMP VALUES

INC

* INCR COUNTER * INNER LOOP DONE? * CHECK FLAG * DONE? * DO INNER LOOP AGIAN

SWAP

L R6,TAB(R4) * LOWER L R7,TAB(R5) * HIGHER ST R7,TAB(R4) * HIGHER TO LOWER ST R6,TAB(R5) * LOWER TO HIGHER LA R8,1(0,0) * SET FLAG B INC SR R2,R2 * LOOP AND PRINT RESULTS LR R4,R2 SLA R4,2 L R3,TAB(R4) XDECO R3,OUT XPRNT OUT,L'OUT LA R2,1(0,R2) Figure 51 Bubble Sort (continued on next page)

DONE PLOOP

124

35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55

* * TABLE OF NUMBERS TO SORT * TAB DC F'9' DC F'7' DC F'3' DC F'10' DC F'4' DC F'1' DC F'2' DC F'11' DC F'5' DC F'0' OUT DS CL12 END Figure 51 Bubble Sort (continued)

C R2,=F'10' BL PLOOP SUBEXIT

22.5 Search for Prime Numbers The program in Figure 52 searches for prime numbers in the range of 4 through 999. The program is a loop that tests each number between 4 and 999 to see if it is divisible by any number between 2 and one-half the number being tested. The program operates as on outer loop whose counter is the number to be tested and an inner loop whose counter iterates between 2 and one-half the outer loop counter. The outer loop counter is R3 and it is initialized to the value 3 on line 4. The outer loop begins on line 6 where the counter is incremented by one (thus, we begin with the counter having a value of 4). We compare the counter with 1000 and, if equal, we exit. Consequently, we test the values between 4 and 999. On lines 10 and 11 we set up the limit for the inner loop. We load the counter (R3) into R4 then shift the value in R4 right by one. In effect, this divides the value in R4 by 2 and this gives us the upper limit for the inner loop counter. On Line 13 we initialize the inner loop counter to 1. The inner loop begins on line 12 and extends to line 24. First we increment the counter (hence, we begin our testing with 2, not 1). The loop will iterate testing all the values between 2 and one-half the value being tested to see if they divide evenly. If we find a case where some counter value from the inner loop divides evenly (remainder of zero), we exit the inner loop and try the next outer loop value. If on the other hand, we make it through the entire inner loop finding no value that divides evenly into our candidate value, the value must be prime so we print it and continue to the next. At line 16 we compare the value in R2, our inner loop counter, with the limit value in R4. If the value in R2 is greater than or equal to the value in R4, we branch to label PRIME and print the number. We have tried all the alternatives.
125

Otherwise, we load the candidate outer loop counter into R6 and double shift it 32 bits to the right into R7. This places the candidate into R7 and (since we are only using positive numbers) zeros out R6. Note: when doing a right arithmetic shift, bits like the sign bit are supplied at the high end. Since our numbers are all positive, the sign bit is always zero. Next we divide the candidate by the inner loop counter on line 21. The quotient will be in R7 and the remainder in R6. If the remainder is zero (line 22), the number is not prime and we branch back to the outer loop. If the remainder is not zero, we test the next inner loop counter value. If a number is prime, we print it at line 26 then branch back to the outer loop for the next candidate to test.
1 PRIME 2 3 4 5 6 LOOP 7 8 9 10 11 12 13 14 15 INNER 16 17 18 19 20 21 22 23 24 25 26 PRIME 27 28 29 30 DONE 31 32 OUT 33 OUT1 34 35 SUBENTRY EQUREGS L R3,=F'3' A R3,=F'1' C R3,=F'1000' BE DONE LR R4,R3 SRA R4,1 L R2,=F'1' A R2,=F'1' CR R2,R4 BNL PRIME LR R6,R3 SRDA R6,32 DR R6,R2 C R6,=F'0' BE LOOP B INNER * CANDIDATE NUMBER TO TEST * DONE? * CALCULATE INNER LOOP LIMIT * DIVIDE BY 2 * INNER LOOP COUNTER * INNER LOOP LIMIT TEST

* PREPARE EVEN/ODD REGISTER PAIR * CHECK THE REMAINDER * NOT PRIME

XDECO R3,OUT XPRNT OUT,L'OUT+L'OUT1 B LOOP SUBEXIT DS CL12 DC C' IS PRIME' END Figure 52 Search for Prime Numbers

22.6 Print a String in Hexadecimal The program in Figure 54 prints a string of characters in their equivalent hexadecimal notation. For example, if the string is ABC123, the equivalent hexadecimal is:
126

C1C2C3F1F2F3

The program will advance through the input string byte by byte. For each byte, it will first extract the high order four bits and use these as a number (between 0 and 15) to index into a table of equivalent printable characters which correspond to the value of the four bit field. For example, if the four bit field has 1010 (10 in base 10), it will index to the eleventh position in the table where there will be a character A. Note: the table begins at zero. Hence, offset 10 into the table is to the eleventh element. The program proceeds as follows:
1.

The length of the input string is loaded into R2 (line 7). The length is derived from the value stored at label STRLEN on line 33. This value is declared as an A-type address constant whose value is the location counter value of the label STRX. STRX gets it's location counter value from the EQU directive which calculates the difference between the current location counter and the location counter at the beginning of STRING. STRX could not be loaded directly because it does not exist at run time - it is only and equate symbol. STRLEN, however, does exist at run time and will be initialized with the value of STRX. While STRX is not really an address, Atype address constants are often used for this purpose since they permit initialization of their run time content by computer values as is the case here. Registers R4 through R6 are set to zero (lines 8,9, and 10). R4 will be an offset into the input string, R5 will be a register into which we load the input characters and R6 will be an offset into the output string. Beginning on line 12 we loop through the input until done. The loop control is the BCT instruction on line 25. Each time the BCT is executed, it decrements the value in R2 (the string length) by one. When R2 is still greater than zero, branch is made to LOOP. When R2 is zero, no branch is made and the loop ends. On line 12 we use the Insert Character instruction to load a byte from the string into the low order 8 bits of R5 (we zeroed all the bits of R5 - this instruction only modifies the low order 8 bits so the high bits remain zero). The address of the byte to be loaded is computer with the displacement, index, and base format. The assembler will construct the base and displacement for STRING and also place R4, our offset into the string, into the index register position. As the loop progresses, the value in R4 will increment by one for each passage through the loop (line 23). We now have an input character in the low order 8 bits of R5. We need to extract the high order four bits, do a lookup and copy a result to the output then do the same for the low order four bits. The SRA on line 13 shifts the contents of R5 to the right by four. This removes the low order 4 bits and causes what were the high order four bits of the low byte to now be in the
127

2.

3.

4.

5.

low order position. R5 will consist of 28 bits of zeros (high order bits) followed by the four bits that were in the high end of the input character. R5 is now a number between 0 and 15 and the offset into our lookup table.
6.

On line 14 we use the Insert Character instruction indexed by the value in R5 to load a character from TABLE. TABLE is a string containing the characters 0 through A used to represent hexadecimal numbers. Thus, if the value in R5 is 10 (decimal), we will load A into the low byte of R5 and likewise for any value in R5 between 0 and 15. The previous contents of R5 are lost in this operation. On line 15 we store the low order byte from R5 into the output string and increment the offset into the output string on line 16. Lines 18 through 22 process the low order four bits from the original character. To process the low bits, we only need to eliminate the high four bits. We do this by and And instruction with a mask. The mask is a 32 bit value in memory with binary zeros in all but the last four bits. These are ones. When this mask is and'ed with another 32 bit value, only the low order four bits will remain. This is done on line 19. Lines 20 through 22 do the lookup and store the result. As we have now processed all 8 bits of the input character, line 23 increments the offset into the input. Line 25 determines if we should process any more characters as noted above. Line 27 writes to output. Note that the length of the output is twice the length of the input (there are two character of hexadecimal for each input character).

7.

8.

9.

22.7 Word Count Program The following program builds a dictionary of words. It stores up to 1000 words of length up to 8 characters and maintains a count of the number of times each occurs. Information storage and retrieval systems often index documents based only on a maximum number of characters in a word. The stem of a word is mainly in the first part of the word. The Salton SMART System was originally based on six character words - the size of the computer word on early mainframes. Word counts are useful to identify common and infrequent words which may make poor indexing terms. In this example, the data structure for each word will be eight characters of text followed by four bytes of of binary giving the number of time the word has occurred in the input text. In the program in Figure 54, the word data structure is contained in a table whose declaration is on line 120. It is a 12000 byte table thus allowing for 1000 12 byte entries. Note that the table begins on a full word boundary. This is insured by the declaration on line 116. The notation 0F in a DS statement causes the assembler to allocate zero instances of a full word binary but it has the effect of forcing the assembler to advance to the next full word boundary (an address value evenly
128

divisible by 4). Thus, the next declaration, the table TAB begins on a full word boundary.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 PRINT NOGEN EQUREGS SUBENTRY WTO 'HEXADECIMAL' L R2,STRLEN SR R4,R4 SR R5,R5 SR R6,R6 LOOP IC R5,STRING(R4) SRA R5,4 IC R5,TABLE(R5) STC R5,OUT(R6) LA R6,1(R0,R6) IC R5,STRING(R4) N R5,MASK IC R5,TABLE(R5) STC R5,OUT(R6) LA R6,1(R0,R6) LA R4,1(R0,R4) BCT R2,LOOP XPRNT OUT,STRX*2 SUBEXIT STRING STRX STRLEN OUT MASK TABLE * * * * * * * * * * * * * * * LENGTH OF STRING OFFSET INTO INPUT STRING REGISTER TO RCV STRING CHARS OFFSET INTO OUTPUT STRING LOAD NEXT INPUT CHAR MAKE 4 HIGH BITS the 4 LOW BITS LOAD CHAR FROM HEX TABLE STORE CHAR in OUTPUT STRING INCREMENT OUTPUT OFFSET LOAD INPUT CHAR AGAIN ZERO HIGH 4 bits LOAD FROM HEX TABLE STORE TO OUTPUT INCREMENT OUTPUT OFFSET INCREMENT INPUT OFFSET

HEX

* DECR R2, BRANCH IF > 0 * PRINT RESULTS

DC C'THIS IS A TEST STRING 0123456789' EQU *-STRING DC A(STRX) DS CL(STRX*2) DC X'0000000F' DC C'0123456789ABCDEF' END HEX Figure 53 Print Hex Equivalent

This is important because each full word binary word count in the table must itself be on a full word boundary in order to be accessible by the Load and Store (and other) instructions. The structure of the table at TAB is not visible in the declaration. Rather, the structure is imposed on it by the code which maps this area of memory to be a table of 1000 elements. Note that the table TAB is declared last. Note that the LTORG appears before the TAB definition. The LTORG causes any literals, elements looking like =F'100', to be placed in memory beginning at the point where the LTORG appears. Thus, any literals will appear prior to our definition of TAB. What is the problem with TAB? Since the extent of TAB is much larger than 4095, the largest displacement allowed, anything placed after TAB would be out of using for our single base register. We could have more than one base register but it
129

is unnecessary. We only need that the first byte of TAB be within using as we can address it directly from that point as will be seen. The program works as follows:
1.

The input consists of lines of text up to 80 characters long, not counting the CR/LF. Input is processed in a loop of code beginning at line 7 and extending through line 62. Input is read into the field IN on line 7 and a branch is made to EOF when there is no more data (line 8). Each input line is processed by a Translate (TR) instruction to remove punctuation (except the hyphen character) and numerics. The TR converts all alphabetics to upper case (a common case for indexing terms is normally used in retrieval applications). The TR uses the table declared on lines 91 through 112. The TR table: We declare an area of memory 256 bytes long (as normally the case with a TR table) and we initialize each byte to blank - the default (line 91). At this point, every character looked up will return a blank. Next, we backup into the table by means of the ORG directive and change some of the blanks. The ORG directive resets the assembler's location counter back into the address space of the table. Once repositioned, the DC statement replace the blanks. The first set of changes are lines 92 through 105. In these lines, we replace the blanks in the table at the offsets associated with the upper and lower case character with the upper case equivalent. That is, at the offset into the table associated with the letter a we replace the blank with a capital A. Thus, when the TR looks up a lower case a, it will return (and substitute) a capital A. We do this for all the alphas. The net effect: input containing upper or lower case letters will be converted to upper case letters. Next we modify the TR table offsets for the hyphen and single quote which will likewise be retained in the resulting input image. The final ORG with no operand causes the location counter to spring back to the highest value it has had so far which, in this case, is the address just beyond the TR table.

2.

3.

4.

Thus, after the TR instruction on line 9, the input image consists only of blanks, upper case alphabetics, hyphens and single quote marks. Retention of hyphens and single quote marks was based on the input used (Dryden's translation of the Aeneid) to test this application in which these characters were important. Next, we scan each input image and extract each word. On Line 11 we load the address of the input image into R3 and the address of the end of the input image into R4. On line 14 we test if the byte being pointed to by the contents of R3 is a blank. If it is not, we branch to label L2. If it is, we fall through to line 17 where we increment the pointer in R3, compare it with the limit value in R4. If we have reached the end of the input, we branch to

5.

130

LOOP and read a new line of input. If not, we branch to L1 to process the next character. Thus, we ignore blanks in the input.
6.

Reaching line 22 we know we are at the start of a word whose address we copy into R5 to preserve the origin of the word. Lines 24 through 28 locate the end of the word by incrementing the input pointer (R3), testing it against the limit. If we reach the end of the input image, we branch to label L4. We then (line 27) test if the character pointed to by the contents of R3 are a blank. If yes, we advance to line 30. If not, we loop and look at the next character When we get to line 30, R5 has the address of the starting point of the word and R3 has the address of the byte just beyond the end of the word. We copy R3 to R6 and subtract R5 from R6 leaving in R6 the length of the word that begins on at the address contained in R5. Lines 32 and 33 ripple move a blank across the field OUT (this program assumes no word will be longer that 30 characters, the length of OUT).

7.

In line 34 we use the EX (Execute) command to move R6 bytes from the input beginning at the address contained in R5 to OUT. The EX uses the data area MVC at the label MVC. This is the image of the MVC that the EX will execute after ORing the low byte of R6 (contains the length) with the second byte of the MVC at MVC. Since the second byte of the MVC at label MVC is a zero, this effectively substitutes the low byte of R6 into the length portion of the MVC instruction and exactly R6 bytes are moved to OUT. The remaining bytes of OUT remain blanks. Now we need to do a lookup on the table to see if we have this word. The words in the table are no longer than 8 bytes. Thus, we truncate long words. Each table word is followed by a four byte binary integer giving the number of times the work as appeared. If we do not find the word in the table, we add it with a count of one. On line 36 we load the count of the number existing entries in the table into R5. Initially, COUNT is 0. On line 37 we load the address of the table of words TAB into R6. Even though most of TAB is beyond the reach of using (base register + 4095), the start of the table is within using. Thus, we can load its address. Once we have its absolute memory address in a register, we can address its contents without need for displacements as will be seen. The loop to search the table to see if our word in OUT is already in the table extends from lines 38 through 46. Lines 38 and 39 test if we have examined the entire table. Each time we examine an entry, we decrement the count in R5. When the contents of R5 become zero, we have examined all entries and we branch to L6 where we add our word from OUT as a new entry. Lines 41 and 42 compare the first 8 bytes of the word in OUT with the word in the table. The CLC (Compare Logical Character) on line 41
131

8.

9.

10.

11.

specifies an 8 byte length. The first operand begins at label OUT and the second operand begins at the address contained in R6. Note there is no displacement. R6 has the address. If the words match, we branch to L7 to increment the count for this word. If they do not, we increment the contents of R6 by 12 (line 44), decrement the count in R5 and branch to look at the next entry, if any.
12.

If we find the word, lines 48 through 51 increment its count. We load into R5 the 4 bytes offset 8 bytes from the word in the table, that is, the 4 byte binary count entry. To this we add 1 and then store the result back in the table. Then we branch to the top to process the next word (label L1A). If we looked at every entry in the table and did not find the word, we arrive at label L6. At label L6 we know that R6 will be pointing at the 1st byte of the next available 12 byte slot in the table. We simply copy the first 8 bytes from OUT to the 1st 8 bytes of the new entry we are creating (line 53), load a 1 into R7 (line 54) and store the 4 byte binary 1 in the last 4 bytes of the 12 byte entry (line 55). We load the original value of COUNT, increment it, test it against the table limit, and store it (lines 56 through 60). The we return to the top to process the next word. Lines 64 through 77 print the table of words and counts using a similar loop to that used to search the table above.
PRINT NOGEN EQUREGS SUBENTRY WTO 'WORDS'

13.

14.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

WORDS

LOOP

XREAD IN,80 BC B'0100',EOF TR IN,TRTAB LA R3,IN LA R4,80(R0,R3)

* CVT UPPER CASE & REMOVE NON-ALPHAS * ADDRESS OF END OF INPUT * BLANK? * BRANCH IF NOT BLANK TO PROCESS WORD * * * * INCR PTR INTO INPUT AT END? YES - END OF INPUT STRING NO - PROCESS NEXT CHARACTER

L1 L1A

CLI 0(R3),C' ' BNE L2 LA R3,1(R0,R3) CR R3,R4 BNL LOOP B L1

Figure 54 Dictionary Program (continued on next page)

132

22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74

L2 L3

LR R5,R3 LA R3,1(R0,R3) CR R3,R4 BNL L4 CLI 0(R3),C' ' BNE L3 LR R6,R3 SR R6,R5 MVC OUT(1),BLANK MVC OUT+1(29),OUT EX R6,MVC L R5,COUNT LA R6,TAB C R5,=F'0' BE L6 CLC OUT(8),0(R6) BE L7 LA R6,12(R0,R6) S R5,=F'1' B L5

* COPY WORD START ADDR TO R5 * * * * * * * * * * * * * * INCR INPUT POINTER END? YES BLANK? NO - CONTINUE COPY WORD END ADDR TO R6 LENGTH OF WORD IN R6 COPY BLANK TO POSITION 1 PROPOGATE BLANK COPY WORD TO OUT NUMBER OF ENTRIES IN TABLE START OF ARRAY OF ENTRIES NO MORE ENTRIES IN TABLE TO LOOK AT? YES

L4

L5

* COMPARE NEW WORD WITH TABLE ENTRY * FOUND WORD IN TABLE * INCREMENT PTR TO NEXT ENTRY * DECREMENT LOOP COUNTER * CONTINUE * * * * * * * * * * * * WORD FOUND - LOAD COUNT INCR COUNT STORE COUNT LOOK FOR NEXT WORD IN INPUT COPY WORD TO TABLE LOAD 1 INTO R7 STORE IN COUNT FIELD MAIN COUNT OF ENTRIES INCR TEST LIMIT OVER LIMIT STORE UPDATED COUNT

L7

L R5,8(R0,R6) A R5,=F'1' ST R5,8(R0,R6) B L1A MVC 0(8,R6),OUT LA R7,1(R0,R0) ST R7,8(R0,R6) L R5,COUNT LA R5,1(R0,R5) C R5,=F'1000' BNL ERROR ST R5,COUNT B L1A

L6

* PROCESS NEXT INPUT WORD * * * * * * * * * * TABLE ADDRESS COUNT OF ENTRIES EMPTY? DONE COPY WORD TO OUTPUT STRING LOAD WORD COUNT CVT WORD COUNT TO CHARS WRITE WORD AND COUNT INCR TO NEXT ENTRY DECR R6 AND REPEAT IF > 0

EOF

L8

LA R5,TAB L R6,COUNT C R6,=F'0' BE BYE MVC OUT(8),0(R5) L R7,8(R0,R5) XDECO R7,OUT+8 XPRNT OUT,20 LA R5,12(R0,R5) BCT R6,L8

Figure 54 Dictionary Program (continued) (continued on next page)

133

75 BYE L R5,COUNT * TOTAL NUMBER OF ENTRIES 76 XDECO R5,OUT * CVT TO PRINTABLE 77 XPRNT OUT,12 * PRINT TOTAL 78 SUBEXIT 79 80 ERROR WTO 'ERROR - TABLE OVERFLOW' 81 SUBEXIT 82 83 BLANK DC C' ' 84 OUT DS CL30 * OUTPUT STRING & TEMP STORE 85 MVC MVC OUT(0),0(R5) * FOR EX INSTRUCTION 86 IN DS CL80 * INPUT STRING 87 COUNT DC F'0' * NBR ENTRIES COUNT 88 * 89 * TRT TABLE TO CONVERT TO UPPER CASE AND REMOVE NON-ALPHAS 90 * 91 TRTAB DC 256C' ' 92 ORG TRTAB+C'a' 93 DC C'ABCDEFGHI' 94 ORG TRTAB+C'A' 95 DC C'ABCDEFGHI' 96 97 ORG TRTAB+C'j' 98 DC C'JKLMNOPQR' 99 ORG TRTAB+C'J' 100 DC C'JKLMNOPQR' 101 102 ORG TRTAB+C's' 103 DC C'STUVWXYZ' 104 ORG TRTAB+C'S' 105 DC C'STUVWXYZ' 106 107 ORG TRTAB+C'-' * RETAIN HYPHENS 108 DC C'-' 109 110 ORG TRTAB+C'''' * RETAIN SINGLE QUOTES 111 DC C'''' 112 ORG 113 114 LTORG * LTERALS NEED TO BE AHEAD OF TABLE 115 116 DS 0F * FULL WORD ALIGN 117 * 118 * TABLE IS 1000 ENTRIES. EACH ENTRY IS 8 CHARS FOR WORD 119 * AND 4 BYTES COUNT. 120 * 121 TAB DS 12000C 122 123 END HEX Figure 54 Dictionary Program (continued)

134

23 General Instruction Set


Name Mnemonic Type CC OpCode RR RX RX RI RR RX RR RX SS SI RR RX RR RX RR RR RR RX RR RX RS RS RI RI RI RSI RSI RRE RR RX S RS RS RX RI RR RX SS SI RS RR RS RRE RRE RX RX RRE RR RX RR RX SS SI RX RRE RX C C C C C C C C C C 1A 5A 4A A7A 1E 5E 14 54 D4 94 05 45 0D 4D 0C 0B 07 47 06 46 86 87 A75 A74 A76 84 85 B241 19 59 B21A BA BB 49 A7E 15 55 D5 95 BD 0F A9 B25D B257 B2|4F 4E B24D 1D B2|5D 17 57 D7 97 44 B24F 43

ADD AR ADD A ADD HALFWORD AH ADD HALFWORD IMMEDIATE AHI ADD LOGICAL ALR ADD LOGICAL AL AND NR AND N AND (character) NC AND (immediate) NI BRANCH AND LINK BALR BRANCH AND LINK BAL BRANCH AND SAVE BASR BRANCH AND SAVE BAS BRANCH AND SAVE AND SET MODE BASSM BRANCH AND SET MODE BSM BRANCH ON CONDITION BCR BRANCH ON CONDITION BC BRANCH ON COUNT BCTR BRANCH ON COUNT BCT BRANCH ON INDEX HIGH BXH BRANCH ON INDEX LOW OR EQUAL BXLE BRANCH RELATIVE AND SAVE BRAS BRANCH RELATIVE ON CONDITION BRC BRANCH RELATIVE ON COUNT BRCT BRANCH RELATIVE ON INDEX HIGH BRXH BRANCH RELATIVE ON INDEX LOW OR EQ. BRXLE CHECKSUM CKSM COMPARE CR COMPARE C COMPARE AND FORM CODEWORD CFC COMPARE AND SWAP CS COMPARE DOUBLE AND SWAP CDS COMPARE HALFWORD CH COMPARE HALFWORD IMMEDIATE CHI COMPARE LOGICAL CLR COMPARE LOGICAL CL COMPARE LOGICAL (character) CLC COMPARE LOGICAL (immediate) CLI COMPARE LOGICAL C. UNDER MASK CLM COMPARE LOGICAL LONG CLCL COMPARE LOGICAL LONG EXTENDED CLCLE COMPARE LOGICAL STRING CLST COMPARE UNTIL SUBSTRING EQUAL CUSE CONVERT TO BINARY CVB CONVERT TO DECIMAL CVD COPY ACCESS CPYA DIVIDE DR DIVIDE D EXCLUSIVE OR XR EXCLUSIVE OR X EXCLUSIVE OR (character) XC EXCLUSIVE OR (immediate) XI EXECUTE EX EXTRACT ACCESS EAR INSERT CHARACTER IC

C C C C C C C C C C C C C C C C

C C C C

Table 20 General Instructions (continued on next page) 135

INSERT CHARACTERS UNDER MASK INSERT PROGRAM MASK LOAD LOAD LOAD ACCESS MULTIPLE LOAD ADDRESS LOAD ADDRESS EXTENDED LOAD AND TEST LOAD COMPLEMENT LOAD HALFWORD LOAD HALFWORD IMMEDIATE LOAD MULTIPLE LOAD NEGATIVE LOAD POSITIVE MONITOR CALL MOVE (character) MOVE (immediate) MOVE INVERSE MOVE LONG MOVE LONG EXTENDED MOVE NUMERICS MOVE PAGE (facility 1) MOVE STRING MOVE WITH OFFSET MOVE ZONES MULTIPLY MULTIPLY MULTIPLY HALFWORD MULTIPLY HALFWORD IMMEDIATE MULTIPLY SINGLE MULTIPLY SINGLE OR OR OR (character) OR (immediate) PACK PERFORM LOCKED OPERATION SEARCH STRING SET ACCESS SET PROGRAM MASK SHIFT LEFT DOUBLE SHIFT LEFT DOUBLE LOGICAL SHIFT LEFT SINGLE SHIFT LEFT SINGLE LOGICAL SHIFT RIGHT DOUBLE SHIFT RIGHT DOUBLE LOGICAL SHIFT RIGHT SINGLE SHIFT RIGHT SINGLE LOGICAL STORE STORE ACCESS MULTIPLE STORE CHARACTER STORE CHARACTERS UNDER MASK STORE CLOCK STORE HALFWORD STORE MULTIPLE SUBTRACT SUBTRACT SUBTRACT HALFWORD SUBTRACT LOGICAL SUBTRACT LOGICAL

ICM IPM LR L LAM LA LAE LTR LCR LH LHI LM LNR LPR MC MVC MVI MVCIN MVCL MVCLE MVN MVPG MVST MVO MVZ MR M MH MHI MSR MS OR O OC OI PACK PLO SRST SAR SPM SLDA SLDL SLA SLL SRDA SRDL SRA SRL ST STAM STC STCM STCK STH STM SR S SH SLR SL

RS RRE RR RX RS RX RX RR RR RX RI RS RR RR SI SS SI SS RR RS SS RRE RRE SS SS RR RX RX RI RRE RX RR RX SS SI SS SS RRE RRE RR RS RS RS RS RS RS RS RS RX RS RX RS S RX RS RR RX RX RR RX

C C

C C

C C C C

C C C C C C L C C C C

C C C C C C

BF B222 18 58 9A 41 51 12 13 48 A78 98 11 10 AF D2 92 E8 0E A8 D1 B254 B255 F1 D3 1C 5C 4C A7C B252 71 16 56 D6 96 F2 EE B25E B24E 04 8F 8D 8B 89 8E 8C 8A 88 50 9B 42 BE B205 40 90 1B 5B 4B 1F 5F

Table 20 General Instructions (continued) (continued on next page) 136

SUPERVISOR CALL TEST AND SET TEST UNDER MASK TEST UNDER MASK HIGH TEST UNDER MASK LOW TRANSLATE TRANSLATE AND TEST UNPACK UPDATE TREE

SVC TS TM TMH TML TR TRT UNPK UPT

RR S SI RI RI SS SS SS E

C C C C C C

0A 93 91 A70 A71 DC DD F3 0102

Table 20 General Instructions (continued)

Over the years people have suggested a number of interesting if less practical extensions (humorously, that is):
ARG BDM CMN DDS EMR ETO FSE GSI GQS HEM IDD IKI IMU JPF JUM KFP LNM MAW NNI OBU PNG QWF QVC RWD SCE SDJ TTC UBC VDP VMB WAF XID YII ZAM PI POPI RASC RPM RSSC RTAB RWDSK SPSW SRSD WBT : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : Agree to Run Garbage Branch and Destroy Memory Convert to Mayan Numerals Damage Disk and Stop Emit Microwave Radiation Emulate Toaster Oven Fake Serious Error Garble Subsequent Instructions Go Quarter Speed Hide Evidence of Malfunction Inhale Dust and Die Ignore Keyboard Input Irradiate and Mutate User Jam Paper Feed Jeer at Users Mistake Kindle Fire in Printer Launch Nuclear Missiles Make Aggravating Whine Neglect Next Instruction Overheat and Burn if Unattended Pass Noxious Gas Quit Working Forever Question Valid Command Read Wrong Device Simulate Correct Execution Send Data to Japan Tangle Tape and Crash Use Bad Chip Violate Design Parameters Verify and Make Bad Warn After Fact eXchange Instruction with Data Yield to Irresistible Impulse Zero All Memory Punch Invalid Punch Operator Immediately Read And Shred Card Read Programmers Mind Reduce Speed, Step Carefully (for improved accuracy) Rewind Tape and Break ReWind DiSK Scramble Program Status Word Seek Record and Scar Disk Water Binary Tree Figure 55 Over-Extended Instructions (humor)

137

138

Alphabetical Index
1s complement................................................................54 24 bit address.................................................................... 9 2s Complement...............................................................52 A..................................................................................... 71 AH.................................................................................. 83 AL................................................................................... 84 Alignment....................................................................... 57 ALR................................................................................ 84 AND............................................................................... 97 ARCHLVL1..................................................................... 9 ARCHLVL2..................................................................... 9 ARCHLVL3..................................................................... 9 Arithmetic shift instructions..........................................100 BAL................................................................................ 62 Base/displacement...........................................................16 Base/displacement addressing.........................................15 Basic Character Instructions............................................87 BC................................................................................... 81 BCD................................................................................ 51 BCT................................................................................ 49 BCTR.............................................................................. 49 Binary............................................................................. 11 Binary integer............................................................51, 69 Binary Integers................................................................52 Bit Operations.................................................................97 Boolean instructions........................................................97 BXLE.............................................................................. 48 CAFE.............................................................................. 51 Character Long Instructions............................................89 CISC............................................................................... 10 CLC................................................................................ 88 CLCL.............................................................................. 89 CLI.................................................................................. 89 CLOSE.......................................................................... 110 Compare logical character...............................................88 Compare Logical Character Long...................................89 Compare Logical Characters...........................................88 Complement....................................................................98 Condition Code/..............................................................43 Conditional branch..........................................................43 Conditional Branching (BC, BCR)..................................43 CR/LF........................................................................... 109 CSECT............................................................................ 62 CVB........................................................................ 52, 112 CVD................................................................................ 52 D..................................................................................... 85 DB.................................................................................. 51 DC.................................................................................. 57 DCB.............................................................................. 110 DDNAME..................................................................... 110 Decimal Arithmetic.......................................................101 Declare constant..............................................................57 Declare storage................................................................57 Digit selector.................................................................103 Divide............................................................................. 85 Divide Packed...............................................................102 DP................................................................................. 102 DR.................................................................................. 85 DROP........................................................................... 106 DS................................................................................... 57 Dump.............................................................................. 75 EBCDIC.......................................................................... 52 ED........................................................................... 52, 102 EDIT............................................................................. 102 End-of-file....................................................................... 66 Entry point...................................................................... 61 EODAD........................................................................110 EQUREGS................................................................18, 23 Even/odd register pairs....................................................48 EX................................................................................... 88 Exclusive OR..................................................................98 Explicit Addressing.........................................................31 Extended mnemonic........................................................45 Extended Mnemonics......................................................80 Floating point............................................................51, 69 Floating point registers....................................................15 General purpose registers................................................15 GET..............................................................................110 Halfword Instructions......................................................83 Hexadecimal................................................................... 11 IBM 360............................................................................9 Immediate operand....................................................29, 32 Index register..................................................................16 Index registers.................................................................32 L................................................................................70, 95 Labels............................................................................. 18 LCR................................................................................ 98 LH................................................................................... 83 Line Format....................................................................18 Linkage........................................................................... 61 Linkage Registers............................................................61 Literal............................................................................. 88 Literals............................................................................59 LM.................................................................................. 95 LNR................................................................................ 96 Load................................................................................95 Load and Test..................................................................96 Load Multiple.................................................................95 Load Negative.................................................................96 Load Positive..................................................................96 Location counter.............................................................72 Logical shift instructions.................................................99 LPR................................................................................. 96 LRECL.......................................................................... 109 LTR................................................................................ 96 M.................................................................................... 84 Machine language...........................................................35 Machine Language Format..............................................35 MACRF........................................................................109 Mask............................................................................... 43 Mask settings..................................................................44 MH.................................................................................. 85 Move Character Long.....................................................90 Move Immediate.............................................................87 Move Numerics.............................................................103 Move Zones..................................................................103 Moving Characters..........................................................87 MP................................................................................ 102 MR.................................................................................. 84 Multiply..........................................................................84 Multiply Packed............................................................102 MVC............................................................................... 87 MVCL............................................................................. 90 MVI................................................................................ 87 MVI)............................................................................... 87 MVN............................................................................. 103 MVZ............................................................................. 103 N..................................................................................... 97 NC.................................................................................. 97 NI.................................................................................... 97 NR.................................................................................. 97 Numeric data types..........................................................51

139

O..................................................................................... 98 OC.................................................................................. 98 OI.................................................................................... 98 OR.................................................................................. 97 ORG................................................................................ 91 Overflow......................................................................... 83 Overflows....................................................................... 83 PACK....................................................................101, 112 Packed Decimal.................................................51, 69, 111 Padding bytes..................................................................58 Powers of two.................................................................53 PRINT NOGEN........................................................18, 23 PRN File......................................................................... 72 Program Status Word......................................................41 PSW.......................................................................... 41, 63 PUT............................................................................... 110 QSAM........................................................................... 109 RECFM......................................................................... 109 Relocatability..................................................................16 RR Machine Language Format........................................35 RS Machine Language Format........................................37 RX Machine Language Format.......................................36 S...................................................................................... 83 Save Area........................................................................ 61 SH................................................................................... 83 Shift................................................................................ 99 SI Format........................................................................ 29 SI Machine Language Format.........................................38 Sign and magnitude.........................................................52 Significance starter........................................................103 SL................................................................................... 84 SLA................................................................................ 84 SLDA.............................................................................. 84 SLR................................................................................. 84 SR............................................................................. 70, 83

SS Machine Language Format........................................39 ST................................................................................... 95 STH................................................................................ 83 STM..........................................................................62, 95 Store................................................................................95 Store Multiple.................................................................95 SUBENTRY.............................................................19, 34 SUBEXIT....................................................................... 19 Subtraction...................................................................... 83 Symbolic Addressing......................................................33 Test and Set...................................................................101 Test Under Mask...........................................................100 TM................................................................................ 100 TR................................................................................... 90 Translate and Test...........................................................90 TRT................................................................................ 90 TS................................................................................. 101 UNPACK......................................................................103 UNPK........................................................................... 103 Unsigned arithmetic........................................................84 USING....................................................................33, 106 X..................................................................................... 98 XC.................................................................................. 98 XDECI............................................................................66 XDECI ........................................................................... 67 XDECO...............................................................66, 67, 71 XDUMP..........................................................................66 XHEXI............................................................................67 XHEXO..........................................................................67 XI.................................................................................... 98 XPRNT........................................................................... 65 XR.................................................................................. 98 XREAD..........................................................................65 Zoned Decimal........................................................51, 111 Zoned format...................................................................51

140