IBM Basic assembly language and successors


The IBM Basic assembly language and successors is a series of assembly languages and assemblers made for the IBM System/360 mainframe system and its successors through the IBM Z.
The first of these, the Basic Assembly Language, is an extremely restricted assembly language, introduced in 1964 and used on 360 systems with only 8 KB of main memory, and only a card reader, a card punch, and a printer for input/output, as part of IBM Basic Programming Support. The Basic Assembler for BAL was also available as part of Basic Operating System/360.
Subsequently, an assembly language appeared for the System/360 that had more powerful features and usability, such as support for macros. This language, and the line of assemblers that implemented it, continued to evolve for the System/370 and the architectures that followed, inheriting and extending its syntax. Some in the computer industry referred to these under the generic term "Basic Assembly Language" or "BAL". Many did not, however, and IBM itself usually referred to them as simply the "System/360 Assembler Language", as the "Assembler" for a given operating system or platform, or similar names. Specific assemblers were known by such names as Assembler E, Assembler F, Assembler H, and so forth. Programmers utilizing this language, and this family of assemblers, also refer to them as ALC, or simply "the assembler".
The latest derived language is known as the IBM High-Level Assembler.

General characteristics

As it is an assembly language, BAL uses the native instruction set of the IBM mainframe architecture on which it runs, System/360, just as the successors to BAL use the native instruction sets of the IBM mainframe architectures on which they run, including System/360, System/370, System/370-XA, ESA/370, ESA/390, and z/Architecture.
The simplicity of machine instructions means that the source code of a program written in assembler will usually be much longer than an equivalent program in, say, COBOL or Fortran. In the past, the speed of hand-coded assembler programs was often felt to make up for this drawback, but with the advent of optimizing compilers, C for the mainframe, and other advances, assembler has lost much of its appeal. IBM continues to upgrade the assembler, however, and it is still used when the need for speed or very fine control is paramount. However, all of the IBM successors to BAL have included a sophisticated macro facility that allows writing much more compact source code.
Another reason to use assembler is that not all operating system functions can be accessed in high level languages. The application program interfaces of IBM's mainframe operating systems is defined as a set of assembly language "macro" instructions, that typically invoke Supervisor Call or Diagnose instructions to invoke operating system routines. It is possible to use operating system services from programs written in high-level languages by use of assembler subroutines.

Assembler statement format

The format of assembler language statements reflects the layout of an 80-column punched card, though successive versions have relaxed most of the restrictions.
  • The optional statement label or name is a string alphanumeric characters beginning in column 1. The first character has to be alphabetic. Later versions added @, #, $, and _ to the legal characters used in labels, and increased the size from the initial six, to eight characters, then to almost unlimited lengths.
  • The operation code or "mnemonic" can begin in any column to the right of column 1, separated from the statement label by a blank. The operation code would be only a machine instruction, making it usually 1, 2, 3, or rarely 4 letters. The operation code was enhanced to allow up to eight characters, then later to effectively unlimited lengths.
  • The operand field can begin in any column to the right of the operation code, separated from the operation code by at least one blank. Blanks are invalid in operands except in character constants. The operand field, consisting of one or more operands, is optional depending on the operation code.
  • Optional comments can appear to the right of the operand field, separated by at least one blank.
  • Basic Assembly Language does not allow statement continuation. Later versions of the assembler indicate continuation by the appearance of any non-blank character in column 72 of the statement being continued. Basic Assembly Language requires that column 72 be blank.
  • A "full-card comment" is indicated by an asterisk in column 1.
  • Card columns 73–80, called the identification-sequence field can be used by the programmer for any purpose, but usually contain sequence numbers for resorting a jumbled card deck.
Basic Assembly language also permits an alternate statement format with the statement starting in column 25, allowing the assembled instruction to be punched into the same card beginning in column 1. This option was not continued in later versions of the assembler.

Types of instructions

Three main types of instructions are found in the source code of a program written in assembler.

Assembler instructions

Assembler instructions, sometimes termed directives, pseudo operations or pseudoops on other systems, are requests to the assembler to perform various operations during the code generation process. For instance, CSECT means "start a section of code here"; DSECT provides data definitions for a structure, but generates no code; DC defines a constant to be placed in the object code.
One of the more important assembler instructions is USING, which supports the base-displacement addressing of the S/360 architecture. It guides the assembler in determining what base register and offset it should use for a relative address. In BAL, it was limited to the form

USING base,reg-1,...,reg-n

Machine instruction addresses on S/360 specify a displacement from the value in a base register; while later versions of the architecture added relative-address formats, the older formats are still used by many instructions. USING allows the programmer to tell the assembler that the specified base registers are assumed to contain the address of "base", base+4096, etc. This only provides a shortcut for the programmer, who otherwise would have to specify the base register in each instruction. Programmers are still responsible for actually loading the address of "base" into the register before writing code that depends on this value.
The related DROP assembler instruction nullifies a previous USING.

Machine instructions (mnemonic)

There is a one-to-one relationship with machine instructions. The full mnemonic instruction set is described in the Principles of Operation manual for each instruction set.
Examples:

* This is a comment line
* Load the fullword integer stored at the
* location labeled 'ZIGGY' into general register 3:
L 3,ZIGGY
SLA 4,5 shift the value in general register 4 left by 5 bits
MVC TARGET,SOURCE move characters from location 'SOURCE' to 'TARGET'
AP COUNT,=P'1' add 1 to value in memory location 'COUNT'
B NEXT unconditional branch to label 'NEXT'
HERE EQU * This is a label
CLC TARGET,=C'ADDRESS' Compare memory location 'TARGET' to string 'ADDRESS'
BE THERE branch if equal to program label 'THERE'

Generally accepted standards, although by no means mandatory, include the identification of general purpose registers with mnemonics. Unlike assemblers for some other systems, such as X86 assembly language, register mnemonics are not reserved symbols but are defined through EQU statements elsewhere in the program. This improves readability of assembler language programs and provides a cross-reference of register usage. Thus typically you may see the following in an assembler program:

R3 EQU 3
...
L R3,ZIGGY

Some notable instruction mnemonics are BALR for a call storing the return address and condition code in a register, SVC, DIAG, and ZAP.
System/360 machine instructions are one, two, or three halfwords in length. Originally there were four instruction formats, designated by the first two bits of the operation code field; z/Architecture added additional formats.

Macros and conditional assembly

The Basic Programming Support assembler did not support macros. Later assembler versions beginning with Assembler D allow the programmer to group instructions together into macros and add them to a library, which can then be invoked in other programs, usually with parameters, like the preprocessor facilities in C and related languages. Macros can include conditional assembler instructions, such as AIF, used to generate different code according to the chosen parameters. That makes the macro facility of this assembler very powerful. While multiline macros in C are an exception, macro definitions in assembler can easily be hundreds of lines.

Operating system macros

Most programs will require services from the operating system, and the OS provides standard macros for requesting those services. These are analogous to Unix system calls. For instance, in MVS, STORAGE dynamically allocates a block of memory, and GET retrieves the next logical record from a file.
These macros are operating-system-dependent; unlike several higher-level languages, IBM mainframe assembly languages don't provide operating-system-independent statements or libraries to allocate memory, perform I/O operations, and so forth, and different IBM mainframe operating systems are not compatible at the system service level. For example, writing a sequential file would be coded differently in z/OS and in z/VSE.