IBM 1130

From Wikipedia, the free encyclopedia
Jump to: navigation, search
IBM 1130 console
IBM 1130 with IBM 1442 card reader/punch.

The IBM 1130 Computing System, introduced in 1965,[1] was IBM's least expensive computer at that time. It was aimed at price-sensitive, computing-intensive technical markets like education and engineering, succeeding the IBM 1620 in that market segment.

Description[edit]

A double width SLT card from an IBM 1130. The square metal cans contain the hybrid circuits.

The total production run of the 1130 has been estimated at 10,000.[2] The 1130 holds a place in computing history because it (and its non-IBM clones) gave many people their first direct interaction with a computer. Its price-performance ratio was good and it notably included inexpensive, removable disk storage, with reliable, easy-to-use software that supported several high-level languages. The low price (from around $32,000 or $41,000 with disk drive)[3] and well-balanced feature set enabled interactive "open shop" program development.

The IBM 1130 used System/360 electronics packaging called Solid Logic Technology (SLT) and had a 16-bit binary architecture, as did later minicomputers like the PDP-11 and Data General Nova.

The address space was 15 bits, limiting the 1130 to 32,768 16-bit words (65,536 bytes) of memory. The 1130 used magnetic-core memory, which the processor addressed on word boundaries, using direct, indirect, and indexed addressing modes.

Models[edit]

IBM implemented five models of the 1131 Central Processing Unit, the primary processing component of the IBM 1130. The Model 1 through Model 5 described the core memory cycle time, as well as the model's ability to support disk storage. A letter A through D appended to the model number indicated the size of core memory installed.

 
Memory cycle time
Core memory
3.6 µs,
no internal disk
3.6 µs,
plus disks
2.2 µs,
plus disks
5.6 µs
(3.6 µs: see below),
single disk
2.2 µs,
no internal disk
4096 words
Model 1A
Model 2A
---
Model 4A
---
8192 words
Model 1B
Model 2B
Model 3B
Model 4B
Model 5B
16,384 words
Model 1C
Model 2C
Model 3C
---
Model 5C
32,768 words
Model 1D
Model 2D
Model 3D
---
Model 5D

The Model 4 was a lower-priced product with a 5.6 µs cycle time. Some purchasers of performance upgrades observed that the field adjustment to achieve the improvement was surprisingly trivial.

The IBM 1132 printer relied on the 1130 processor rather than internal logic to determine when to fire the print wheels as they rotated. Printers for the Model 4 ran more slowly, but the slower processor still could not keep up with it. The hardware manual disclosed that when the Model 4 was servicing the two highest-level interrupts (the level 0 card-reader column interrupt or the level 1 printer interrupt), it ran at the faster 3.6 µs cycle time. Some users of the Model 4 would write a phony printer driver that did not dismiss the printer interrupt, in order to benefit from the higher processor speed. However, lower-level interrupts were disabled during this interval, even the end-of-card interrupt (level 4) from the 1442 card reader.

Follow-on products

The IBM 1800 was a variant of the IBM 1130 for process control applications. It used hardware rather than core memory for the three index registers and featured two extra instructions (CMP and DCM) plus extra interrupt and I/O capabilities. It was a successor to the IBM 1710, as the IBM 1130 was a successor to the IBM 1620.

The IBM 1500 was a multi-user educational system based around either an IBM 1130 or an IBM 1800. It supported up to 32 student work stations each with a variety of audio-visual capabilities.

Chronology
  • February 11, 1965 - IBM introduces the 1130 (Models A1, A2, B1 and B2). Also announced is the IBM 1132 printer, the lowest cost online computer printer ever announced by IBM at that time.
  • Fourth quarter 1965 - First customer shipments begin from the San Jose plant.
  • March 31, 1966 - IBM introduces the IBM 1500 educational system.
  • April 1966 - IBM 1800 ships.[4]
  • August 9, 1966 - IBM rolls out the 1130 synchronous communications adapter, which permits the small 1130 system to be connected by regular leased telephone lines to, and function as a communications terminal for, any model of the IBM System/360.
  • April 17, 1967 - A four-way expansion of the 1130 is announced (Models B3, C2, C3, D2 and D3), involving:
    • Five times the disk storage and four times the core memory;
    • An additional processing speed almost 40 percent faster than previously available;
    • More and faster peripheral equipment, including an optical mark reader;
    • An improved commercial programming package.
  • January 1968 - First shipments begin of the 1130 Models B3, C2, C3, D2 and D3.
  • July 1968 - The Boca Raton plant begins shipping the 1130.
  • July 22, 1971 - 1130 Models 4A and 4B are introduced at new levels of economy.
  • September 1971 - First customer shipments begin of the 1130 Model 4.
  • May 31, 1972 - Models 1C, 1D, 5B, 5C and 5D are announced.

Operating procedure[edit]

Punched card containing a self-loading 1130 program that would copy the deck of cards placed after it in the input hopper.

The enduring memories of the IBM 1130 may have resulted from its need for continual human intervention. It was usually occupied running "jobs" specified by a deck of punched cards. The human operator would load jobs into the card reader and separate them back into jobs for return, perhaps along with printed output, to the submitter. The operator would also have to watch the 1130 for evidence of a malfunctioning or stalled job and intervene by keyboard to skip ahead to the start of the next job.

Nearly all systems had at least one disk drive, which contained the components of the Disk Monitor System (DMS) or its Release 2 (DM2). During the execution of a job, a resident monitor of DMS called the Skeleton Supervisor resided at the start of core memory. When the job ended or was aborted, the Supervisor loaded the next task.

Marking the start of a job was a punched card that started with // JOB. Any card that started with // was a command to the Supervisor and could not be used as user program or data. Other commands included // DUP to execute the Disk Utility Program (to delete files or add the file in the temporary area to the file collection) and // XEQ to execute a named program from disk. If a user program tried to read a command card, the standard card reader routine would signal end-of-input to the program and save that card's content for the Supervisor.

The Supervisor was tiny by modern standards, containing assorted system details such as interrupt responders plus the disk driver and routines to load the interpreter of the // commands and its card reader driver. A task's first available memory started with address /01FE (hexadecimal) or word 510, thus the Supervisor required just 1020 bytes.

A particular task might involve additional I/O devices, so device drivers would be incorporated as part of the loading of that task, which might also call for the replacement of the basic disk driver by a more advanced driver. While the task was running, the Supervisor was inactive, aside from device drivers and their interrupts: all CPU time was entirely devoted to the task's activities.

Recovery procedures

When the IBM 1130 was started, the Supervisor would still be in memory and probably intact, as core memory retains its state without power. However, it was usual to begin by booting. The bootstrap procedure read one card from the card reader. The boot card contained binary code to read the contents of sector zero of the disk drive, which in turn would handle the "operation complete" interrupt from the disk drive and perform additional disk reads to prepare the 1130 for the first punched-card job. The whole process took about a second to complete.

If the operator concluded that a user program had stalled, the Supervisor could sense a key press to abort the program and skip ahead to the next // card. The Supervisor was not protected against modification by a badly written job, a case that might require that the operator reboot the 1130. Nor was there protection against writing to disk. If the copy of the system software on disk were modified, it could be restored by reloading it from about 4000 binary-coded punched cards.

Disk organization
2315 compatible disk cartridge.(dimensions 1 3/8 x 15 in.)

The IBM 2310 disk drive stored sectors of 320 words (640 bytes). All disk files were contiguous: A file started at some sector and continued unbroken to its last sector, thus there was no fragmentation. A program in need of working storage could use and modify named files, but could not expand them beyond their created size. Free space started after the last named file, and might be partially occupied by a temporary file, as the assembler or a compiler might produce. If a file was to be modified, the usual process was to use // DUP commands to delete it, which would move any subsequent files back to close the gap, and then rename the temporary file as the new version of the file. Rarely modified files would thus sink towards the start of the disk as new files or new versions were appended, and frequently modified files would jostle amongst each other towards the end of the disk.

Disk space was at a premium, so program source files were normally kept as decks of cards. Users having larger requirements would arrange to have a disk of their own containing the operating system but only their files and would have to replace the "pool" system disk with theirs and restart the system when their turn at being operator came. A system with a second disk drive that could be devoted entirely to some user's code and data provided a great sense of spaciousness.

There was a hierarchy of device drivers: those ending in Z were for Fortran, such as DISKZ, while assembler programmers might use DISK0, and DISK1 was even faster at reading multiple disk sectors. But DISKZ started its sector addressing with the first available unused sector, while the others started with sector zero of the disk, making it easy for a Fortran programmer dabbling in assembler to inadvertently overwrite the bootstrap loader.

Software[edit]

To maximize speed and conserve space, the operating system and compilers were written entirely in assembly language and employed techniques that are rare today, including intermixing code and data as well as self-modifying code.

Much user programming was done in Fortran. The 1130 Fortran compiler could run on a machine with only 4,096 words of core—though the compiled program might not fit on such a machine. A compilation comprised many small "phases" that processed the entire source program and took it another step toward machine code. For example, the first phase read the source statements into memory, discarding comment lines, squeezing out all spaces (Fortran syntax is unusual in that no spaces are significant except in text literals), concatenating continuation lines and identifying labels, and performing no syntax checking beyond what might be discovered during this stage. The compiler was available in a disk-resident version as well as on 8-channel punched paper tape or punched cards.

Other programming languages available on the 1130 included APL,[5] BASIC, COBOL, FORTH, PL/I, and RPG. There was even an Algol compiler, written in French, so that "Debut ...Fin;" took the place of "Begin ... End;". All its messages were in French, so "Bonne compilation" was the goal. Eastern Michigan University developed a Fortran IV compiler for the 1130, known as Fortran-EMU as an alternative to the Fortran II compiler provided by IBM. It added many features, including the LOGICAL data type, enhanced diagnostics, and six-letter variable names. Oklahoma State University developed an ALGOL 68 compiler, written in ANSI Fortran 1966.[6][7][8]

Peripheral devices[edit]

IBM 1442 card reader/punch
IBM 1627 drum plotter.

The basic 1130 came with an IBM 2310 voice-coil actuated disk drive, called "Ramkit", from IBM's General Products Division in San Jose.[9]:497 These read pizza-box-sized 2315 single platter cartridges that held 512 K words or 1 M byte (less than a 3.5" HD floppy). Disk memory was used to store the operating system, object code, and data; but source code was kept on punched cards.

The console typewriter used an IBM Selectric mechanism, which meant one could change the type by replacing a hollow, golf-ball sized type element. There was a special type element available for APL, a powerful array-oriented programming language using a special symbolic notation. A row of 16 toggle switches on the console typewriter could be individually tested from within programs, using the Fortran statement IF (SENSE SWITCH i), for example.

Other available peripherals included:

Instruction set overview[edit]

Instructions had short (one-word) and long (two-word) formats. Most computational, load, and store instructions referenced one register (usually ACC) and a memory location. The memory location was identified, in the short format, by an 8-bit signed displacement from either the current address or one of the index registers; or in the long format, by a full 15-bit address, which could be indexed and specify indirection.

Most conditional transfers were based on condition indicators as set by a preceding operation, usually reflecting the contents of ACC. Transfers could be by skip (which assumed that the next instruction was short) or by branch.

Main Registers:
IAR = Instruction Address Register
ACC = Accumulator
EXT = Extension Register
XRx = Index Registers: x = 1,2,3 
      Implemented as memory words 1,2,3, not as hardware registers.

Condition indicators
+ Positive
- Negative
Z Zero
O Overflow
C Carry
E Even

1130 Instruction Set Mnemonics:
LD   = Load ACC                   STO  = Store ACC
LDD  = Load Double (ACC & EXT)    STD  = Store Double (ACC & EXT)
LDX  = Load Index                 STX  = Store Index
LDS  = Load Status                STS  = Store Status
A    = Add ACC                    AD   = Add Double
S    = Subtract ACC               SD   = Subtract Double
M    = Multiply                   D    = Divide
AND  = Boolean And                OR   = Boolean Or
XOR  = Boolean Exclusive Or
SLA  = Shift Left ACC             SLT  = Shift Left ACC & EXT
SLCA = Shift Left and Count ACC   SLC  = Shift Left and Count ACC & EXT
SRA  = Shift Right ACC            SRT  = Shift Right ACC & EXT
RTE  = Rotate Right ACC & EXT     XCH  = Exchange ACC and EXT
MDM  = Modify Memory
B    = Branch
BSC  = Branch or Skip on Condition (Modifier dependent)
       i.e. BP BNP BN BNN BZ BNZ BC BO BOD
BSI  = Branch and Store IAR
MDX  = Modify Index and Skip (Increment IAR one if a sign change or becomes zero)
WAIT = Halt                       NOP  = No Operation
XIO  = Execute I/O

1800 Additional Instruction Mnemonics:
CMP  = Compare ACC                DCM  = Double Compare ACC & EXT

Short instruction format (one 16 bit word):
                       1
Bits    0...45678......5
        OP---FTTDisp----

OP    is Operation
F     is format 0 = Short
TT    is Tag
Disp  is Displacement

Long instruction format (two 16 bit words):
                       1               1
Bits    0...456789.....50..............5
        OP---FTTIMod----Address---------

OP    is Operation
F     is format 1 = Long
TT    is Tag
I     is Indirect bit
Mod   is Modifier

Effective Address Calculation (EA):
          F = 0            | F = 1, I = 0     | F = 1, I = 1
          Direct Addressing| Direct Addressing| Indirect Addressing
-------------------------------------------------------------------
TT = 00 | EA = Displ + IAR | EA = Add         | EA = C/Add
TT = 01 | EA = Displ + XR1 | EA = Add + XR1   | EA = C/Add + XR1
TT = 10 | EA = Displ + XR2 | EA = Add + XR2   | EA = C/Add + XR2
TT = 11 | EA = Displ + XR3 | EA = Add + XR2   | EA = C/Add + XR3
-------------------------------------------------------------------
    Disp = Contents of displacement field
     Add = Contents of address field of instruction
       C = Contents of location specified by Add or Add + XR
Reserved memory

The lowest addresses of core memory had uses dictated either by the hardware or by convention:

Address Usage
/0000 By convention, contained the instruction B *-1, which would branch to itself indefinitely until an operator noticed that all the console IAR lights were dark and flushed the job, either by pressing Int Req or by rebooting.
/0001 XR1. The memory addresses of the index registers permitted direct moves between them, such as with LDX I1 2
/0002 XR2.
/0003 XR3.
/0008 The address of the handler for the Level 0 (highest priority) interrupt: the card reader "column ready" interrupt.
/0009 The address of the handler for the Level 1 interrupt, usually the 1132 printer. Handlers for this and lower interrupts would have to test a Status Word to determine which device had interrupted.
/000A=10 The address of the handler for the Level 2 interrupt.
/000B=11 The address of the handler for the Level 3 interrupt.
/000C=12 The address of the handler for the Level 4 interrupt.
/000D=13 The address of the handler for the Level 5 (lowest priority) interrupt.
/0020=32 First word of the scan field for the 1132 printer.
/0026=38 Last full word of the scan field.
/0027=39 Half used: 120 columns = 120 bits = seven 16-bit words plus 8 bits.

Programming[edit]

This section uses the Fortran convention that subprograms comprise subroutines (which stand alone in the Fortran CALL statement) and functions (which can be combined in arithmetic expressions and always return result values).

Subprograms[edit]

The 1130 had no support for a stack. Most subprograms were called with the instruction BSI (Branch and Store IAR). This deposited the value of IAR (the return address) at the destination address and transferred control to the next word. Subprograms returned to wherever they were called on that occasion using an indirect branch through that first word of the subprogram.

So a subprogram named SIMPL might be organized as follows:

SIMPL: DC     *-*    This is the entry point, filled with a zero initially.
       (whatever the routine does)
       B    I SIMPL  Return by an Indirect branch, to the address found in location SIMPL.
       END    SIMPL  Instructs the assembler that the source for routine SIMPLE is complete.

The subprogram would be called as follows:

       BSI  L SIMPL  Call SIMPL. L (Long) is needed if SIMPL is more than -128 or +127 words away.

The pseudo-operation CALL would typically be used.

As shown, a subprogram's entry point was DC *-*. This code resulted in a zero word, and the only point of writing it this way was as a visually distinctive note that a meaningful value (the return address) will be placed there at run time. The entry point need not be the first word of the subprogram. Indeed, the preceding word could be the start of a two-word direct branch instruction whose address field would be at SIMPL. Then, returns could be effected by one-word branches there: B SIMPL-1

When SIMPL is called, the BSI instruction replaces *-* with the address just past the BSI instruction. After SIMPL does whatever it is written to do, B I SIMPL branches not to SIMPL, but indirect through it, typically returning to just past the BSI instruction that called it.

Without extra arrangements to protect the return address, recursion would be impossible: If SIMPL called itself, or called a subprogram that called it, its original return address would be overwritten. Re-entrancy was problematic for the same reason: An interrupt service routine must refrain from calling any subprogram that might have been the code that was interrupted.

The caller of SIMPL might pass it parameters, which might be values or addresses of values. Parameters might be coded in-line (immediately following the BSI instruction) or might be placed in index registers XR1 and XR2. If parameters were placed in-line, SIMPL would modify its own return address so its final indirect branch returned beyond the parameters.

Integer functions of a single integer would expect the parameter in the accumulator and would return their result there. Floating-point functions employed the floating-point accumulator (a two word area set aside by the floating-point library, three words for extended precision), and so on.

The convention of coding 0 as the initial value at the entry point meant that if a programming error led to SIMPL returning before the first time it was ever called, execution would jump to memory location 0. As mentioned above, it was customary to have location 0 contain a branch to location 0. The 1130 would be stuck at location 0, and the IAR lights on the console would be entirely dark, making it clear the program had failed.

Linkage to library routines[edit]

For subprograms that would be called many times (for example, subprograms for floating-point arithmetic), it was important to reduce the size of each call to one word. Such "library routines" used the LIBF protocol. It was more complex than the CALL protocol described in the previous section, but LIBF hid the complexity from the writer of the assembly-language program.

Library routines were addressed through index register XR3. (Fortran programs would use index register XR1 for the addresses of parameters and the return address, but register XR2 was unused.) XR3 would be pointed to a sequence of three-word transfer vectors such that the first entry would be -128 words from XR3's value. The programmer would call the library routine using the LIBF pseudo-operation, which assembled not a direct BSI to the routine but a one-word indexed branch instruction (BSI 3 disp) whose displacement (-128, -125, and so on) identified the start of the routine's transfer vector.

The transfer vector was prepared by the linkage loader when it put together the program. A transfer vector to a library function named SIMPL took this form:

      DC       *-*            A word into which BSI stores the return address.
      B    L   SIMPL          Branch to the start of the library function.

The way SIMPL knew where its return address was is that, if SIMPL were declared a LIBF routine, the linkage loader would modify the code of SIMPL, placing the address of SIMPL's transfer vector entry at SIMPL+2. LIBF routines, unlike CALL subprograms, do not start with a DC directive to hold the return address (it is in the transfer vector) but with actual code, as follows:

SIMPL STX   1  RCVR1+1        Save the caller's value of XR1 at a nearby location.
      LDX  I1  *-*            The linkage loader changes the address word to point to the transfer vector.

Placing the address of SIMPL's transfer vector at SIMPL+2 left room for a one-word instruction to save the chosen index register, here XR1. Then the indirect LDX instruction points XR1 not at the transfer vector, but through it to the return address, or to any parameters stored in-line after the BSI. SIMPL then does whatever it was written to do, gaining access to any in-line parameters through XR1 (in which case it must increment XR1 for the return address), and returns as follows:

      STX   1  RETN+1         Store XR1 to prepare to use it as a return address.
RCVR1 LDX  L1  *-*            SIMPL's first instruction modified this address.  Now,
*                              restore the original value of XR1.
RETN  B    L   *-*            This instruction was modified two instructions ago; return.
Example

Suppose a LIBF-style call to SIMPL were at address 100. Then the return address would be 101, because BSI 3 disp is a one-word instruction. XR3 will point into the group of transfer vectors. If the transfer vector for SIMPL started at address 2000, then the BSI would be assembled with a disp so that XR3+disp = 2000. Executing the BSI stores 101 at location 2000 and jumps to location 2001. At 2001 would be a two-word long jump to the entry point of SIMPL, which the linkage loader might have placed at address 300.

The long jump transfers control to SIMPL. After the instruction at 300 stores XR1, the instruction at 301 is LDX I1 2000, the linkage loader having placed 2000 at location 302. This does not load 2000 into XR1; it is an indirect instruction, and loads the contents of 2000, which is 101, the return address for that call to SIMPL.

In the return sequence shown above, by the time control reaches RETN, the instruction there is B L 101, which returns to the caller. (If there were one or more in-line parameters at 101, SIMPL would have incremented XR1 to point to 102 or beyond, and this would be the destination of the B instruction.)

Variations

If SIMPL took parameters coded in-line following the BSI instruction, SIMPL could gain access to them with indexed addressing off XR1. The first could be obtained by LD 1 0, the second by LD 1 1, and so on. If the second parameter was the address of the actual parameter, then LD I1 1 would obtain its value. Before returning, SIMPL would increment XR1 past the n parameters with an instruction such as MDX 1 n so as to place the right value at RETN+1.

A LIBF routine that declined to restore the original value of XR1 could omit the above steps and return with a simple B 1 n to skip n in-line parameters. However, such a routine could not be called by other LIBF routines because it would disrupt the caller's use of XR1 for access to its own parameters and return address.

The complexity of LIBF saves memory for subprograms that are frequently called.[12] The LIBF linkage requires one word per invocation, plus three words for the transfer vector entry and extra code in the routine itself, whereas the CALL linkage requires two words per invocation because most CALLs will be to an address beyond the -128 to +127 word reach of the one-word opcode.

The register XR1 must point to the transfer vectors rather than a dispatch table of their addresses, because this would require that LIBF routines be called with an indirect BSI instruction. These instructions are two words long, so such a design would negate the code size savings of LIBF.

Code modification[edit]

The previous sections show that code and data were intermingled. It was common to modify the address fields of instructions and, in fact, to modify entire instructions.

By the Fortran compiler[edit]

The Fortran compiler produced self-modifying code when generating code for any subprogram that had parameters. The compiler built a table of every location where the subprogram referenced one of its parameters, and compiled as the first instruction in the body of the subprogram a call to a subprogram called SUBIN that used the table to modify the address field of every reference to a parameter to be the actual address of the parameter during the current invocation. SUBIN made these patches every time the subprogram was called.

When a Fortran program called a subprogram (see above), the addresses of any parameters appeared in-line following the call. For example, the Fortran statement CALL SIMPL(X) might compile into:

  BSI L  SIMPL
  DC     X      The address of X, on which SIMPL is to operate

Within the subprogram, parameters could be accessed by indirect indexed addressing as shown above in Variations, so that an integer parameter could be loaded into the accumulator with an instruction like this:

  LD  I1 0      Load the value of the first parameter (offset 0) into the accumulator

The compiler instead used direct addressing. When SUBIN ran, it obtained the address of X and patched the instruction to become:

  LD  L  X      Load the value of X into the accumulator

The advantages of SUBIN were as follows:

  • To obtain the operand's address an indirect indexed instruction required three memory cycles (the index register being in memory) while the direct access instruction required only one.
  • If SIMPL were to pass one of its parameters to any subprogram that expected to receive the address of its parameter (including all the LIBF routines for floating-point arithmetic), SUBIN was needed to supply the actual address of the original parameter.

The disadvantages of SUBIN were the time it required to run and the memory required for the table of references. The size of this table was the sum of 5, the number of parameters, and the number of references; if this sum exceeded 511, compilation would fail. For subprograms with many references to a parameter, the author of the subprogram might copy the parameter into a local variable.

By the user[edit]

Modifying entire instructions was a common technique. For example, although the 1130 had an OR instruction, the syntax of Fortran provided no way to write it. An integer function IOR could be defined, enabling logical OR to be part of a Fortran expression such as:

  M = 3*IOR(I,J) + 5

The Fortran compiler would place the addresses of I and J in-line and expect the result in the accumulator. Using IOR(I,J) in a Fortran expression would compile the following four words:

  BSI  L IOR    Two-word jump to the start of the IOR function.
  DC     I      A one-word in-line parameter: The address of I.
  DC     J      A one-word in-line parameter: The address of J.

In fact, the assembler IOR function did not compute I or J at all. Instead, it replaced the above four words with the following:

  LD   L I      Load accumulator with I (two-word instruction)
  OR   L J      OR accumulator with J   (two-word instruction)

After performing that transformation, it did not return past the end of the four-word block (which it had just modified). Instead, it branched to the exact address from which it had been called originally. The BSI instruction was no longer there; what was now there was the two instructions it had just written. They combined the two integers with the machine-language OR instruction and left the result in the accumulator, as required.

The call to IOR and the transformation of the four-word block happened at most once per program run. If the Fortran line illustrated above were executed again, it would run faster than it did the first time. Similar functions could be devised for other useful operations.

A function that self-modified, as IOR does, could not be used in a Fortran subprogram on any of the parameters to that subprogram (though it could be used to combine local variables) because it is incompatible with the SUBIN subprogram discussed above. IOR's transformation of its four-word calling sequence, shown above, moves the location of the address of variable I. On subsequent calls to the Fortran subprogram, the table of references to parameters would be in error and SUBIN would patch the wrong word, in this case placing the new address of I over the OR operation code.

Large Fortran programs[edit]

Data to be manipulated and the instructions that manipulated them had to reside together in core memory. The amount of installed memory (from 4,096 to 32,768 words) was a key limitation. Fortran provided several techniques to write large programs despite this limitation.

LOCAL subprograms

Fortran let any subprogram be designated as "LOCAL" (Load-on-Call). Each LOCAL subprogram was an overlay; it would be part of the disk-resident executable program but would only be loaded into core memory (if not already there) during the time it was called. So, for example, six LOCAL subprograms would require only as much core memory as the largest, rather than the total amount for all six. However, none of the six could invoke another, either directly or through intermediary subprograms.

Programs in phases

An entire Fortran program could pass control to a subsequent phase, exiting to the Supervisor with an instruction to load the follow-on phase into core memory. A large program might be split into three parts, separately compiled, called PART1, PART2, and PART3. Execution would be started by // XEQ PART1 and at a suitable point, PART1 would execute the Fortran statement CALL LINK(PART2) and so forth. The name of the successor program in the CALL could not be variable, but program logic could govern whether control was transferred to another phase, and which CALL LINK statement was executed. It was mentioned above that the Fortran compiler itself was written this way, with each phase of compilation achieved by a separate program.

COMMON data storage

Programs, such as Fortran programs, resided at low core memory addresses (just above the Supervisor). Fortran allocated space at the highest addresses for any variables and arrays declared COMMON. If a follow-on phase of the program contained a corresponding COMMON declaration, then information in this common area could be shared among phases. Phases could omit the COMMON declaration without problem, provided those phases were not so large as to have their program code invade the common area. COMMON storage not only shared data between phases; lower-memory COMMON variables could be used to pass data among a main program and subprograms within a single phase, though the data could be lost on moving to the next phase.

Programming examples[edit]

The examples can be executed on the IBM 1130 emulator available at IBM 1130.org.

Sample Assembler program deck[edit]

The following listing shows a card deck that compiles and runs an Assembler program that lists a deck of cards to the line printer.
The following code Copyright (c) 2006 Kym Farnik. Code published under MIT license. See: http://www.opensource.org/licenses/mit-license.php

 // JOB 
 // ASM
 *LIST
                     * LCARD.ASM - LIST A DECK OF CARDS TO LINE PRINTER
                     *
                     * COPYRIGHT (C) 2006 KYM FARNIK. 
                     * CODE PUBLISHED UNDER MIT LICENSE. 
                     *
                     * PROGRAM
                     *    NEW PAGE ON PRINTER
                     * A  READ A CARD
                     *    CONVERT FORMAT
                     *    PRINT A LINE ON PRINTER
                     *    GOTO A
                     *
                     START LIBF    PRNT1    GOTO NEW PAGE ON 1132
                           DC      /3100    PRINTER CHANNEL 1-NEW PAGE
                     *
                     NEXTC LIBF    CARD0    READ FROM 1442 CARD READER
                           DC      /1000    CONTROL TO READ
                           DC      CBUFF    STORE 80 COLUMNS
                     CINP  LIBF    CARD0
                           DC      0
                           B       CINP     LOOP UNTIL CARD IS READ
                     *
                           LIBF    ZIPCO    CONVERT CARD TO PRINTER
                           DC      /1100    UNPACKED IN, PACKED OUT
                           DC      CBUFF+1  INPUT BUFFER
                           DC      PBUFF+1  OUTPUT BUFFER
                           DC      80       CHARACTER COUNT
                           CALL    HLEBC    HOLLERITH TO EBCDIC
                     *
                           LIBF    PRNT1    PRINT 80 CHARACTERS
                           DC      /2000    CONTROL CODE TO PRINT
                           DC      PBUFF    PRINT BUFFER
                           DC      PERR     PRINT ERROR
                     POUT  LIBF    PRNT1    CHECK FOR PRINT COMPLETE
                           DC      0
                           B       POUT     LOOP UNTIL COMPLETE
                     *
                           B       NEXTC    READ NEXT CARD
                     *
                     * DATA
                     *
                     CBUFF DC      80       80 COLUMNS PER CARD
                           BSS     80
                     *
                     PBUFF DC      40       40 WORDS 80 CHARACTERS
                           BSS     40
                     *
                     PERR  DC      0
                           B    I  PERR     THIS RETURNS TO THE
                     *                       PRINTER ERROR HANDLER
                     *                       WHICH WILL TERMINATE THE PROGRAM
                     *
                           END     START    PROGRAM ENTRY POINT
 // XEQ
 TEST DATA 1
 HELLO WORLD
 TEST DATA 2

In this job, the assembler leaves the result of its assembly in the temporary area of the system disk, and the XEQ command executes the content of the temporary area. The odd-looking END START has two meanings: end of assembler source, and the name of the entry point of the routine, which has the label START.

Assembler source starts with column 21 of the card, not column one. In systems without a disk drive, the assembler would punch code into the start of the card just read (the card reader was actually a reader-punch, with the punch station after the read station) and then read the next card. To handle forward branches and the like, the assembler's second pass literally involved a second pass of the cards through the reader/punch. And should you need to change the source deck, you would have to duplicate the cards to obtain a deck with blanks at the start ready for the next try through the assembler.

By convention, buffers are preceded by a word count. The DC assembles a count word and the following BSS reserves the required number of words for the buffer. The card buffer requires 80 words, one for each card column. Driver CARD0 reads each card column literally, using 12 of the 16 bits in the buffer word to describe whether there is a punch in the corresponding row for that column. The pattern of punches typically describes a text character using the Hollerith code. The console keyboard also gives input to the program in the Hollerith code.

The printer routine, however, works with text in 8-bit EBCDIC with two characters per word, requiring a 40-word buffer. The program uses library routine ZIPCO to perform the conversion. The CALL HLEBC is not executed because HLEBC is not a subroutine but an IBM-supplied Hollerith-to-EBCDIC conversion table. The CALL statement provides the address of the table to ZIPCO and ensures that the linking loader includes the table in the program, thus it is the fifth parameter to ZIPCO. After the conversion, the program sends the converted output, now in buffer PBUFF, to the printer through driver PRNT1. Again, the program loops until the printer driver reports completion, then the program reads the next card.

This example contains no code to decide when to stop. A more complete program would check for cards that begin with //, which denotes the start of the next job. To stop the card reader as soon as possible, a program could check for the Hollerith code of / before even converting the card to EBCDIC.

Asynchronous I/O and performance

The call to CARD0 to read a card initiates that operation and immediately returns to the caller, which could proceed with other activity. However, the example program makes no attempt to overlap input and output using buffers; it simply loops back to CIMP to test afresh. After CARD0 has sensed the card reader's operation-complete interrupt, it returns one word further on, thus skipping the jump back to CIMP and leaving the loop.

The example routines do not run the I/O devices at top speed. Notably, the card reader, only a few milliseconds after reporting completion on reading a card, will commence its stop sequence, after which a new read command will have to wait to initiate another read cycle. The IBM 1402 reader could read 400 cards/minute at full speed, but just a little hesitancy in the read commands would halve its throughput or worse. A Fortran program could not complete even the simplest input processing in time, and so could not read cards at full speed. One common Fortran DO loop to read cards made the motor stop and start so frequently as to accelerate wear. With buffering, the card reader control could be overlapped with processing, and the reader could be run at full speed through large data decks, but memory for the more complex program and for buffers was often at a premium.

Even with assembler and double buffering, a program to list a deck of cards from the IBM 2501 reader (1,000 cards/minute) on the line printer could not keep up, as the translation from card hole patterns to EBCDIC for the printer as done by EBPRT was too slow; the more complex ZIPCO and HLEBC were needed instead, as in the example.

Sample Fortran IV program deck[edit]

The following listing shows a card deck that compiles and runs a Fortran program and Fortran subroutine for the IBM 1130 when running DM2.

 // JOB 
 // FOR
 *LIST SOURCE PROGRAM
 *ONE WORD INTEGERS
 C-------------------------------------------------------   
 C COMPUTE THE CRITICAL VALUES FOR A QUADRATIC EQN
 C 0=A*X**2+B*X+C
 C RETURNS DISCRIMINANT, ROOTS, VERTEX, FOCAL LENGTH, FOCAL POINT
 C X1 AND X2 ARE THE ROOTS
 C-------------------------------------------------------   
       SUBROUTINE QUADR(A,B,C,DISCR,X1,X2,VX,VY,FL,FPY)
       REAL A,B,C,DISCR,X1,X2,VX,VY,FL,FPY
 
 C DISCRIMINANT, VERTEX, FOCAL LENGTH, FOCAL POINT Y
       DISCR = B**2.0 - 4.0*A*C
       VX = -B / (2.0*A)
       VY = A*VX**2.0 + B*VX + C
       FL = 1.0 / (A * 4.0)
       FPY = VY + FL
       FL = ABS(FL)
 
 C COMPUTE THE ROOTS BASED ON THE DISCRIMINANT
       IF(DISCR) 110,120,130
 
 C -VE DISCRIMINANT, TWO COMPLEX ROOTS, REAL=X1, IMG=+/-X2
 110   X1 = -B / (2.0*A)
       X2 = SQRT(-DISCR) / (2.0*A)
       RETURN
 
 C ZERO DISCRIMINANT, ONE REAL ROOT
 120   X1 = -B / (2.0*A)
       X2 = X1
       RETURN
 
 C +VE DISCRIMINANT, TWO REAL ROOTS
 130   X1 = (-B + SQRT(DISCR)) / (2.0*A)
       X2 = (-B - SQRT(DISCR)) / (2.0*A)
       RETURN
 C
 C NEXT STORE SUBROUTINE ON DISK USING DUP
       END
 // DUP
 *DELETE             QUADR
 *STORE      WS  UA  QUADR
 // JOB
 // FOR
 *LIST SOURCE PROGRAM   
 *IOCS(CARD,1132 PRINTER)   
 *ONE WORD INTEGERS   
 C-------------------------------------------------------   
 C PROCESS DATA CARDS WITH A,B,C
 C UNTIL A=0
 C-------------------------------------------------------
 
       DATA ICARD,IPRT /2,3/
       REAL A,B,C
       REAL DISCR,XR1,XR2,VX,VY,FL,FPY
 
       WRITE(IPRT,901)
 901   FORMAT(' ------------------------------------------------------')
 
 C READ A B C, IF A=0 THEN EXIT
 100   READ(ICARD,801)A,B,C
 801   FORMAT(3F8.3)
 
 C     EXIT WHEN A IS ZERO
       IF (A) 110,9000,110
 
 C PRINT A B C 
 110   WRITE(IPRT,902)A,B,C
 902   FORMAT(' QUADRATIC A=',F8.3,' B=',F8.3,' C=',F8.3)
 
 C COMPUTE AND PRINT THE CRITICAL VALUES
       CALL QUADR(A,B,C,DISCR,XR1,XR2,VX,VY,FL,FPY)
       WRITE(IPRT,903) DISCR
 903   FORMAT(' DISCRIMINANT=',F9.4)
       WRITE(IPRT,904) VX,VY
 904   FORMAT(' VERTEX X=',F9.4,'  Y=',F9.4)
       WRITE(IPRT,905) FL
 905   FORMAT(' FOCAL LENGTH=',F9.4)
       WRITE(IPRT,906) VX,FPY
 906   FORMAT(' FOCAL POINT X=',F9.4,'  Y='F9.4)
 
       IF (DISCR) 120,130,140
 
 C -VE DISCRIMINANT, TWO COMPLEX ROOTS
 120   WRITE(IPRT,913) XR1, XR2
 913   FORMAT(' COMPLEX ROOTS =(',F9.4,'  +/-',F9.4,'I)')
       GO TO 200
 
 C ZERO DISCRIMINANT, ONE REAL ROOT
 130   WRITE(IPRT,912) XR1
 912   FORMAT(' ROOT  X =',F9.4)
       GO TO 200
 
 C +VE DISCRIMINANT, TWO REAL ROOTS
 140   WRITE(IPRT,911) XR1, XR2
 911   FORMAT(' ROOTS X1=',F9.4,'   X2=',F9.4)
 C --- GO TO 200
 
 C END OF QUAD
 200   WRITE(IPRT,901)
       GO TO 100
 
 C END OF PROGRAM
 C DATA FOLLOWS XEQ CARD
 9000  CALL EXIT   
       END   
 // XEQ
 +001.000+000.000+000.000
 +001.000+002.000+003.000
 +002.000+002.000+000.000
 +002.000+000.000-004.000
 +000.500+000.000-004.000
 +000.250+002.000-002.000
 -004.000+000.000-004.000
 +002.730-007.200-003.750
 +000.000+000.000+000.000

Sample APL\1130 session[edit]

The following image shows a simple APL \ 1130 session. This session was performed via the 1130 simulator available from IBM 1130.org
apl \ 1130 apl \ 1130 sample session
The above session shows a signon, addition of the integers 1 to 100, generation of an addition table for the integers 1..5 and a sign off.

Influence of the 1130[edit]

  • Brian Utley was the 1130s Project Manager during its development and introduction. Brian said at the third 11/30 party that before IBM Marketing named the 1130 it was known as the Small Engineering Computer System or SECS.[13] The initial architecture was 18 bits but was changed to 16 bits due to the influence of the System/360 development. The full dialogue of his 2005 presentation is available at IBM1130.org.
  • Notable software designer Grady Booch got his first exposure to programming on an IBM 1130:[14]

... I pounded the doors at the local IBM sales office until a salesman took pity on me. After we chatted for a while, he handed me a Fortran [manual]. I'm sure he gave it to me thinking, "I'll never hear from this kid again." I returned the following week saying, "This is really cool. I've read the whole thing and have written a small program. Where can I find a computer?" The fellow, to my delight, found me programming time on an IBM 1130 on weekends and late-evening hours. That was my first programming experience, and I must thank that anonymous IBM salesman for launching my career. Thank you, IBM.

  • LISP guru Guy Steele wrote a LISP interpreter for the IBM 1130 when he was in high school (Boston Latin School, which had an IBM 1130 for student use).[15][16] His code and documentation for LISP 1.6, along with a summary of current work in getting it to run under simulation, is available at IBM1130.org.
  • Chuck Moore wanted to call his new language "Fourth" but the IBM 1130 operating system was limited to five-character names, so it wound up being called FORTH.[17]
  • Dan Bricklin creator of the VisiCalc program got his start in programming when he learned and used the IBM 1130 as part of the National Science Foundation Computer/Math Summer Project for high school students, given at the University of Pennsylvania in 1966.[18]
  • An IBM 1130 with 8 kilowords of core was used for the world's first full-time Search for Extraterrestrial Intelligence research at The Ohio State University Radio Observatory.[19]
  • Charles Goldfarb, the father of SGML, describes a job installing a typesetting system based on an IBM 1130 that "eventually changed my career", driving him towards generic markup:[20]

The system was an IBM 1130 computer, a machine the size of a desk with 8KB of main memory, a 512KB disk drive, a Teletype CX paper tape reader and BRPE paper tape punch, and a Photon 713 photomechanical typesetter. The assignment was my first experience with managing a machine-readable document database: I learned to roll the punched paper tape carefully so that it could be stored neatly in cylindrical waste paper baskets.
In the meantime, though I didn't know about it, the roots of generalized markup were being planted. Historically, electronic manuscripts contained control codes or macros that caused the document to be formatted in a particular way ("specific coding"). In contrast, generic coding, which began in the late 1960s, uses descriptive tags (for example, "heading", rather than "format-17").

  • Alan Kay used the IBM 1130 in early GUI work for his Ph.D. thesis in 1969.[21]

Apocrypha[edit]

Speculation on why the product was given the number 1130 centered on the following possibilities:

  • That, since the 1130 was a small scientific machine, the number was chosen by multiplying 360 (as in IBM 360) by π.
  • That 11:30 was the time of day that product planners reached an impasse regarding what to call the product.
  • That the 1130 was IBM's 11th Computer Design, and it had 30 instructions.

Others have speculated that the existence of the IBM 1130 explains why no computer designated "11/30" ever appeared in the PDP-11 family of machines.[22]

See also[edit]

References[edit]

  1. ^ C. G. Francis, Director of Information, Data Processing Division (February 11, 1965). "IBM INTRODUCES POWERFUL SMALL COMPUTER". White Plains, New York: IBM. 
  2. ^ Utley, Brian (Jan 2005). (MP3). (Interview) http://ibm1130.org/party/v03. Retrieved 2012-01-02.  Missing or empty |title= (help)
  3. ^ "Press release:IBM introduces powerful small computer". International Business Machies. 11 February 1965. Retrieved 18 October 2012. 
  4. ^ :497
  5. ^ Larry Breed (August 2006). "How We Got To APL\1130". Vector (British APL Association) 22 (3). ISSN 0955-1433. 
  6. ^ Hedrick, G.E.; Robertson, Alan, "The Oklahoma State ALGOL 68 Subset Compiler". 1975 International Conference on ALGOL 68. Stillwater, OK, June 10–12, 1975.
  7. ^ Hedrick, G. E., "ALGOL68 instruction at Oklahoma State University", ACM SIGCSE Bulletin - Special issue eighth technical symposium on computer science education Homepage, Volume 9 Issue 3, Aug 1977, ACM New York, NY, USA
  8. ^ McJones, Paul, "Algol 68 implementations and dialects", Software Preservation Group, Computer History Museum
  9. ^ Emerson W. Pugh; Lyle R. Johnson; John H. Palmer (9780262161237). IBM's 360 and early 370 systems. MIT Press. 
  10. ^ "IBM 1130 Custom Feature Description - Attachment Channel RPQ Number 831552, Form A26-1579-0" (PDF). IBM System Reference Library (First ed.) (San Jose, California: IBM Corporation). October 1968. Retrieved 2009-08-10. 
  11. ^ IBM Corporation. "IBM Acchives: DPD Chronology (page 4)". Retrieved 10 Aug, 2011. 
  12. ^ IBM 1130 Assembler Language manual (Form C26-5927-4), page 24
  13. ^ Utley, Brian (2006-10-30). "Origin of the IBM 1130 Name". Retrieved 2007-01-16. 
  14. ^ Booch, Grady (2003-04-03). "Grady Booch polishes his crystal ball". IBM accessdate=2007-01-16. 
  15. ^ Steele, Guy L., Jr. (2005-11-24). "Thoughts on Language Design -- New challenges require new solutions". Dr. Dobb's Journal. Retrieved 2006-01-16. 
  16. ^ Steele, Guy L., Jr.. "Confessions of a Happy Hacker". Archived from the original on 2006-01-10. Retrieved 2006-01-16. 
  17. ^ Rather, Elizabeth; Colburn, Donald and Moore, Charles (March 1993). "The Evolution of Forth". Retrieved 2007-01-16. 
  18. ^ Bricklin, Dan (2002-08-23). "Memories while visiting the Bay Area and the Computer History Museum". Retrieved 2007-01-16. 
  19. ^ Dixon, Bob (2005-08-13). "SETI in the 1970s". The Big Ear. Retrieved 2007-01-16. 
  20. ^ Goldfarb, Charles (1996). "The Roots of SGML -- A Personal Recollection". Retrieved 2007-01-16. 
  21. ^ Kay, Alan C., "The Reactive Engine", Ph.D. dissertation, University of Utah, 1969."The graphics display routines, character generator and editor ran for a year on an IBM 1130 computer with a “home-brew” interface. Unfortunately, the 1130 was straining to just act as a glorified display buffer, and none of the algorithmic routines were implemented."
  22. ^ PDP-11/20 and /15

External links[edit]