Common instructions and linkage conventions
A small set of instructions does most of the work in real assembler code: load, store, move, compare, packed decimal arithmetic and branch. Programs call each other using fixed register conventions, so any program, in any language, can call any other. Learn both and most modules become readable.
The everyday instructions
| Instruction | Format | What it does |
|---|---|---|
| L R,addr | RX | Load 4 bytes (a fullword) from storage into a register |
| ST R,addr | RX | Store the register's 4 bytes into storage |
| LA R,addr | RX | Load the address itself into the register; storage is not read |
| MVC to(len),from | SS | Move 1 to 256 bytes from one storage area to another |
| CLC a(len),b | SS | Compare two storage areas byte by byte; set the condition code |
| AP a,b | SS | Add packed decimal field b to field a |
| CVB R,dword | RX | Convert an 8-byte packed field to binary in a register |
| CVD R,dword | RX | Convert a register's binary value to an 8-byte packed field |
| BAL / BALR | RX / RR | Save the return address in a register, then branch |
| BC mask,addr / BR R | RX / RR | Branch if the condition code matches the mask; BR is unconditional |
Two traps catch beginners. LA does not touch storage: LA 3,10(0,0) puts the number 10 in R3, and it is often used that way to load small constants or to step a pointer. And MVC moves exactly the length it is given, with no padding and no awareness of field types, so a wrong length silently overwrites the next field.
AP works on packed decimal fields, the same format as COBOL COMP-3. If either field does not contain valid packed data, the instruction fails with a data exception, which is the S0C7 abend. CVB fails the same way on invalid packed input.
The condition code and branch masks
Many instructions set a 2-bit condition code (CC) in the PSW. BC then tests it with a 4-bit mask: each bit stands for one CC value. If any selected bit matches the current CC, the branch is taken.
| Mask bit | Tests | After CLC | After AP |
|---|---|---|---|
| 8 | CC 0 | Equal | Result zero |
| 4 | CC 1 | First operand low | Result negative |
| 2 | CC 2 | First operand high | Result positive |
| 1 | CC 3 | (not set) | Overflow |
Masks add together: BC 15 branches always (the extended mnemonic B), BC 0 never branches, and BC 7 (8 not set) means not equal. The assembler provides readable extended mnemonics such as BE (BC 8), BNE (BC 7), BL (BC 4) and BH (BC 2). BR 14 is BCR 15,14: branch always to the address in R14.
What BC mask value branches only when the condition code is 0 (for example, after CLC finds the fields equal)?
Show a hint
Mask bits 8, 4, 2, 1 correspond to CC 0, 1, 2, 3.
Show the solution
8. The leftmost mask bit (value 8) tests CC 0, so BC 8 is the same as BE.
Standard linkage conventions
When one program calls another, both sides follow the same register conventions. This is why a COBOL program can call an assembler routine, and why an exit written by a site can be driven by z/OS.
| Register | On entry to the called program | On return to the caller |
|---|---|---|
| R1 | Address of the parameter list | Varies by interface |
| R13 | Address of the caller's 72-byte save area | Restored to the caller's save area |
| R14 | Return address in the caller | Restored; used to branch back |
| R15 | Entry point address of the called program | Return code (0, 4, 8, 12...) |
The called program first saves the caller's registers into the caller's save area, then provides its own save area for anything it calls, chaining the two together. At the end it restores the registers, puts the return code in R15 and branches back through R14.
DATECHK CSECT
STM 14,12,12(13) save caller's registers
LR 12,15 entry address becomes base
USING DATECHK,12
LA 11,SAVEAREA our own save area
ST 13,4(,11) back chain to caller's area
ST 11,8(,13) forward chain from caller's area
LR 13,11
L 2,0(,1) address of first parameter
* ... processing ...
L 13,4(,13) back to caller's save area
L 14,12(,13) restore return address
LM 0,12,20(13) restore R0 to R12
SR 15,15 return code 0
BR 14
SAVEAREA DS 18FThe parameter list is a list of fullword addresses, one per parameter. In 31-bit code the high-order bit of the last address is set to mark the end of a variable-length list. COBOL CALL ... USING builds exactly this list, and the COBOL RETURN-CODE special register picks up R15 after the call. Many sites use the SAVE and RETURN macros to generate this code. 64-bit programs use a larger save area format, but the idea is the same.
Common mistakes
LA loads an address, L loads the data at that address. Swapping them gives wrong values without any abend, so check every one when reviewing.
MVC moves exactly the length coded or implied by the first operand. A longer move overwrites neighbouring fields silently; use explicit lengths and check field definitions.
Restoring all registers with LM 14,12 after setting the return code wipes the RC. Set R15 after the restore, or skip it in the restore, as in the example.
What you will see at work
- When a COBOL program calls an assembler routine and gets an unexpected return code, the first check is what the routine put in R15 and why.
- Code reviews of assembler changes focus on lengths in MVC and CLC, branch masks and register usage across calls.
- Dumps include the save area chain, so following back pointers from R13 shows which programs called which before the failure.
Key terms
Check your understanding.
Take this lesson's quiz and save your progress. Free.