System z Instruction Architecture

A Visible/Z Lesson


The Idea:

    The term “machine architecture  refers to the design of the electronic components that comprise a computer.  Since we are studying assembly language, we are most interested in the design of the components that directly affect the assembler programs we write.  Perhaps “instruction architecture” is a more accurate descriptor of our subject matter.  These instruction architecture components include Memory, Registers, the Program Status Word, and the CPU.  The orginal IBM architecture was designed in the early 1960’s and was known as the System 360.  The “360” in the name referred to 360 degrees - the number of degrees in a circle.  (System 360 machines were supposed to be be “all-purpose” machines, capable of handling business as well as scientific applications. )  In the early 1970’s the architecture was modified to allow access to larger amounts of memory and was known as the System 370 architecture.  The architecture has continued to evolve and today is known as the System z.  Throughout this evolution, the architecture has remained “backwards compatible”.  In fact, programs that were written to run on 1960’s era machines can run on current machines with little or no change in their code.  The IBM mainframe has been an incredibly stable platform and this fact has accounted for much of the success of this family of machines.   We begin our discussion of the architecture by looking first at the main storage memory of the machine.


   The smallest unit of storage memory is a bit (binary digit).  A bit can hold a binary digit, 0 or  1, and is represented internally in the machine as a high or low voltage.  Bits are organized into consecutive groups called bytes.  In the System z architecture, a byte consists of 8 bits together with a “hidden” ninth bit that is used for parity checking.  Since the parity bit is unavailable to us as programmers, we will assume that there are 8 bits in a byte.  With 8 bits there are 28 = 256 possible bit patterns that can be made.

                           Binary Pattern        Decimal Equivalent

                                00000000      =              0

                                00000001      =              1

                                00000010      =              2

                                00000011      =              3

                                    00000100      =              4


                                    11111101      =            253

                                    11111110      =            254

                                    11111111      =            255

Each of the 256 bit patterns is used to represent one character of data in the EBCDIC encoding sequence.  “EBCDIC” is an acronym for “Extended Binary Coded Decimal Interchange Code”.  This is a fancy name for a code created by IBM to represent characters in memory.  For instance 11000001 represents a character “A” , and 11110001 represents a character ‘1’ in the EBCDIC encoding sequence. “ASCII” is another binary code which is used on non-IBM machines.   See the article on Character Data for more details.

    Each byte can be divided into two 4-bit areas called the zone and numeric portions as pictured below.  Programmers will refer to a half-byte as a “nibble  or sometimes “nybble”.  This is a colloquial term that is not found in the IBM documentation.  Nevertheless,  bits 0 - 3 are called the “High Order Nibble” and bits 4 - 7 are called the “Low Order Nibble”.


    Bytes are arranged consecutively and numbered, starting with the first byte, which is numbered 0 as indicated in the diagram below.  The number assigned to each byte is called an address.  The idea of an address is an important one when learning to program in assembly language since every reference to memory is made using an address.  This idea will be thoroughly developed in the article on Base/Displacement Addressing.


   A byte is the smallest unit of storage on the machine that has an address.  Bits do not have addresses.

    Consecutive bytes are arranged into groups called fields.  The address of a field is denoted by the address of the first byte that is in the field.   A halfword is a 2-byte field that begins on an address that is evenly divisible by 2 ( Addresses 0, 2, 4, 6, ...).  Such an address is called a halfword boundary.  A fullword is a 4-byte field that begins on a fullword boundary (an address evenly divisible by 4).  A doubleword is an 8-byte field that begins on a doubleword boundary (an address that is evenly divisible by 8).  In the diagram above there are 3 halfwords pictured (bytes 0 and 1, bytes 2 and 3, and bytes 4 and 5), 1 fullword ( bytes 0,1,2, and 3 ), and the beginning of a doubleword ( bytes 0 - 8).

 There are several terms that are commonly used to describe blocks of memory:

                              1)   kilobyte    = 210 = 1,024 bytes

                             2)   megabyte =220 = 1,048,576 bytes

                             3)   gigabyte   =230 = 1024 megabytes

   The original System 360 architecture, called for a 24-bit address size when referring to bytes in main storage.  With 24 bits, the maximum address which could be constructed (24 consecutive binary 1’s) was 224 - 1 = 16 megabytes.  The architecture was extended in the 1970’s in order to support 31-bit addresses.  Today, the machine is capable of creating addresses with 64 bits and values as large as 264 – 1 = 16 exabytes.


    A register consists of special circuitry devoted to high speed arithmetic, addressing main storage locations, and providing control information for the operating system.  There are  2  types of registers of interest to an assembler programmer:

    1)  General purpose -  There are 16 general purpose registers numbered 0 through 15 that are available to an assembler programmer.  These registers are used for high-speed arithmetic and addressing storage locations.  Each general purpose register is 64 bits in length, but in ESA/390 mode (the mode for most beginning assembler programmers), the registers appear to be 32 bits - just large enough to hold a fullword.

    2)  Floating point -  There are 16 floating point registers available for an assembler  programmer.  These registers are used for scientific data processing where the data is quite large or has a large number of decimal places.  Each floating point register is 64

   We are most interested in learning about the general purpose registers since these are heavily used by application programmers.  In fact, we will assume that the term “register” refers to the term “general purpose register” unless otherwise specified.



   The Program Status Word or PSW is a collection of 64 bits that are used to indicate the current status of the machine.  There are numerous fields in the PSW  and two of these fields are of special importance to an assembler programmer:

   1)   Condition Code -  This is a 2 bit field that is used to indicate the results of a comparison operation or an arithmetic operation.  The condition code has four settings since it is a 2-bit field  ( equal - 00, low/minus - 01, high/positive - 10, overflow - 11 ).  After the condition code is set, it can be tested with a branch instruction.  Here is an example,


                   BE   THERE              TEST THE CONDITION CODE


The first instruction is a “Compare Logical Character” instruction which compares the two fields OLDCOST and NEWCOST.  This has the effect of setting the bits in the condition code.  Subsequently, the condition code is tested with the second instruction which is called  Branch Equal”.  This instruction examines the condition code and causes execution to continue at the label “THERE” if the two fields are equal.

   2)  Instruction Address - This is a 31-bit field that contains the address of the next instruction that the machine will execute.  The address of the instruction is used in a process that is called the “Fetch/Execute” cycle.  This process describes, algorithmically, how a computer operates.  The Fetch/Execute cycle is a “loop” which the CPU continually executes.  The cycle consists of the following 5 steps:

                  1)   Fetch the instruction whose address is in the PSW instruction address field.

                  2)  Decode the instruction which was fetched.

                  3)  Update the PSW instruction address field so that it points at the next

                       instruction in the program.

                  4)   Execute the decoded instruction.

                  5)   Go back to step 1.

  Cycling through the Fetch/Execute cycle, the machine usually executes instructions in a sequential fashion.  There is one exeception to this which occurs when the CPU executes a branch instruction.  In this case, if the branch is sucessful, the instruction address becomes the address which is the target of the branch instruction.  For example, suppose we execute the following branch instruction,

                    BE   THERE

                    CLC  X,Y


             THERE  EQU  *

                    MVC  X,Y

If the condition code indicates “equal”, the address specified by the label  THERE” will be placed in the instruction address field of the PSW.  When the CPU loops back to fetch the “next  instruction, the “MVC” instruction is retrieved rather than the “CLC” instruction.

Trying It Out: 

1)  Load the program c1.obj into VisibleZ.  Try cycling through the instructions and pay attention to the condition code after executing the compare instruction.  At that point, what is the condition code?  What condition does it represent?

2)  How many general purpose registers are available in VisibleZ?  How many bits are contained in each register?  VisibleZ operates in an ESA/390 mode.  How many bits seem to be used in each register as you cycle through the program?  How many bytes will fit in a register?  How many bytes in a register are actually used in ESA/390 mode?

3)  How does the machine determine which instruction to execute next? 

4)  Which instruction causes the execution sequence to begin repeating instructions? 

5)  What happens to the address field as the program executes?