Intro, ground rules. One in-class exam and one final.
The last hour of each class will be devoted to a lab; the first several labs will be on the Python language.
Topics:
Computers are good for:
Early arithmetic:
abacus,
logarithms, slide rules (~1600), mechanical calculators (later)
Jacquard loom, 1801: the first mechanical device controlled by a "program" (stored on cards).
Ned Lud and the Luddites, 1811: oops
Charles Babbage (1791-1871) and the mechanical Analytical
Engine. Babbage began work on the Analytical Engine in 1822 and
continued for the rest of his life. It was to be a gear-driven
computer; early versions were application-specific. Alas, mechanical
gears have enough "slack" that Babbage's plans were difficult to
implement.
Lady Ada Lovelace was Babbage's chief programmer (and in some sense the world's first programmer) The two of them realized that the machine could do much more than simple arithmetic and control. Ada in particular understood they were working on a general-purpose computer that could, with enough resources, compute anything, and that computation could be symbolic rather than purely numerical. Ada even proposed that the machine might compose music.
Both Ada and Babbage led somewhat tragic lives.
Ada's name might be given in full as Ada Augusta Byron King, countess of Lovelace There is not complete agreement on how in modern times to refer to her, but "Ada" is common even if it is not exactly parallel to "Babbage".
Hollerith cards & 1890 census: Hollerith's Tabulating Machine Company produced machines that assisted with simple recordkeeping, sorting, and tabulating. Through a sequence of mergers, this company became IBM.
1936: Alan Turing developed the conceptual computer later known
as a Turing machine. This was completely abstract; they were entirely
impractical (and not intended to be practical). This did establish the
core features needed for computing, though: conditional instructions
and lots of memory.
Analog computers: electronic circuits that, when you provided a
set of inputs (eg as voltages) would generate an output voltage that
represented the value you were looking for. (There were also many paper
analog computers, or "nomographs": you found your inputs on the axes,
and found your result at an appropriate intersection point.
John Atanasoff in 1939 began using electrical signals to build
digital computers to solve specific problems (eg linear equations with 29 unknowns). He did not build a general-purpose stored-program computer.
About the same time, Konrad Zuse was building a similar machine,
but using relays instead of tubes.
This resulted in failure. However, Zuse had the brilliant idea of having the program be stored
within the computer itself,
so the machine was not limited to those
tasks for which it was hardwired. Ada may also have understood this
principle. This changes the computer from "hardware designed to solve
problem X" to "hardware designed to solve any problem, provided you can
supply a program".
Neither group (Atanasoff or Zuse) really completed their work.
(Atanasoff's computer did do some computations, but it proved
inflexible. However, the importance of an electronic machine to perform
complex calculations should not be underestimated.)
Aiken, at Harvard, built a working electromechanical machine a few years later, the Mark I. This was the first real working general-purpose computer; it became operational in mid-1944.
1943: Turing & others at Bletchley Park, England, built Colossus:
an all-electronic machine for decrypting German messages. It did not, however, do basic arithmetic.
Mauchly & Eckert's group built the all-electronic ENIAC
(Electronic Numerical Integrator And Computer); it became operational
in 1945. However, ENIAC was programmed by configuring a complex
array of patch cords and switches.
Understanding this limitation, Mauchly & Eckert moved on to
the EDVAC, which incorporated an idea generally attributed to John von
Neumann (who was part of their group): the
idea of storing the program in memory, in the same memory space
as was used for data (not, of course, overlapping). The computer would
fetch and "execute" each instruction stored in memory in turn. This
meant adding to the CPU an entire mechanism for fetching, decoding, and
interpreting instructions, but subsequent history has made it clear
that this was the Right Idea. This strategy is often called the von Neumann computer.
EDVAC eventually worked, but a group in Manchester, England started later and got their stored-program computer working first.
Somewhere around then the CEO of IBM, Thomas J Watson, is alleged to have
said that worldwide there would be a demand for at most five
"computers":
"I think there is a world market for may be five computers."
– Thomas Watson, chairman of IBM, 1943.
But at the time, a "computer" was a person
who did arithmetic for a living! So the story is probably apocryphal.
Transistors were invented in 1947, appeared in "real" computers in 1957.
At that time transistors were discrete components.
Transistor radios typically had five of them.
From ~1948 to 1959, computers slowly evolved into general
programmable machines routinely used by businesses and
scientific/engineering groups.
1948: magnetic drum, precursor to disk
1948: An Wang invents "core" memory; marketed in 1951
1949: magnetic tape
1951: Rand introduces the UNIVAC, the first 'mass-produced' computer.
1952: IBM introduces Model 701, their first electronic computer
(later the 704, and 7000 series)
1956: disk memory, the size of a refrigerator. Later the size will be reduced
to that of a washing machine. ;-)
1957: IBM releases the first Fortran compiler
Dale & Lewis call 1951-1959 the era of First-Generation Software. Programming was done in machine code. Eventually, assemblers were introduced that could generate machine code from more-or-less human-readable assembly code, a textual representation of the binary machine code. There was a one-to-one correspondence between lines of assembly code and individual machine instructions.
1959: Available computer languages include Fortran, Cobol, Algol, Lisp.
However, lots of programming was still done in assembly code.
The early Fortran compilers did an amazing job at generating machine
code almost as fast, or sometimes faster, as hand-crafted assembler
code. Programmers were constantly concerned that high-level languages
were not fast enough.
1959-1965 was the era of Dale & Lewis's Second-Generation Software.
1965: IBM/360, and OS/360
The 8-bit byte is born
In some sense the 32-bit IBM/360 was one of the first "modern" systems,
though it has steadily evolved. The IBM/370 was introduced, for
example, in 1970, and the system evolved into the IBM/390 in 1990.
Other competitors in existence in 1965 have largely disappeared.
Standard System/370 features included support for multiple processes
and tasks, and virtual memory. Descendants were still in widespread use
in 2000, when IBM introduced the 64-bit 'zSeries architecture' that
gradually replaced the 32-bit versions. The 'z' is meant to stand for
zero downtime, ie 100% reliability (achieved through redundancy).
The IBM/360 essentially ushered in the era that Dale and Lewis identify as Third-Generation Software.
Tools included loaders to load programs into memory, and linkers to
combine programs with libraries. A central third-generation feature was
that programs now almost always ran under the direction of an operating system, even though early OS's were relatively primitive.
The main way of working with an IBM/360 was through batch mode: one
submitted ones job, and later (the delay varied from a few minutes to
overnight) received the printout. Early job submission was through
punch cards. This was known as "batch processing".
A contemporary of IBM in the 1960's was Digital Equipment
Corporation, or DEC. They produced minicomputers intended for
scientific/engineering/industrial use, beginning in 1963 with the PDP-5
and then the PDP-8 in 1964. These were odd-sized-byte machines; the
PDP-11 in 1968 was DEC's first 8-bit-byte machine. PDP-11's were very
popular. Originally the size of a four-drawer file cabinet, they
eventually shrank to PC-size but the 16-bit address space made them
obsolete by ~1985.
1965 also saw the beginning of work on MULTICS, an early
time-sharing OS. It was apparently never terribly popular, though it
did work. It is best known for giving rise to UNIX (as a deliberte
attempt to find an alternative to MULTICS).
1971: first integrated-circuit (single chip) microprocessor.
gave rise to computers, calculators, and all sorts of other devices.
Early batch systems handled one process at a time. In order to
maximize utilization of the expensive CPU, relatively early systems
were capable of storing multiple programs in memory at a time and multitasking:
when one program was waiting for data from the disk, it would be
suspended, and another program would run. This was considered to be non-preemptive: your program only gave up the CPU "voluntarily".
Towards the end of this era, "interactive time-sharing" became more prevalent. This involved preemptive multitasking:
a timer would interrupt the CPU every 10-100 milliseconds and the CPU
would (under the direction of a part of the OS called the scheduler)
suspend the process that had been running and resume another one. This
allowed the CPU to appear to be executing several processes
simultaneously. At first this was done so that several batch jobs could
be worked on simultaneously, but then evolved into time-sharing where
several users worked continuously at terminals, running programs by
issuing commands. This feature was extremely popular
with early computing researchers. IBM had TSO for this ("Time Sharing
Option"); MULTICS and UNIX incorporated this from the beginning.
Time-sharing goes back to 1957; John McCarthy's group implemented it
on an IBM 704 that year based on a paper by Bob Bemer. The final
version, CTSS, the (in)Compatible Time Sharing System, was released in
1961. The Dartmouth Time Sharing System was released in 1964; it was
very influential.
The first Unix system was begun at Bell Labs in 1969 by Dennis
Ritchie and Ken Thompson, who were dissatisfied with the MULTICS
approach. An important feature of UNIX was that it was the first OS to
largely be written in a high-level language (called C); prior OSs were
written almost entirely in assembler. The Unix date/time of 0
represents the last second of December 1969.
Linux is a unix-like kernel with the GNU open-source tools.
Dale & Lewis fourth generation:
1971-1989. During this period, "structured" programming in high-level
languages became ubiquitous. The standard office applications (word
processors, spreadsheets, databases) emerged. Bitmapped graphical
displays emerged.
1976: Apple computer
1981: IBM PC
1984: Apple macintosh
The first one was developed ~1963.TI marketed one beginning 1967; not too successfully. Early calculators had circuit boards and several Integrated Circuits (ICs).
1971: Ted Hoff at Intel designed a single-chip calculator chip for Busicom. Hoff had two choices:
Let's follow up on this:
Typical CPU: executes a sequence of instructions stored in
memory. Execution is in sequence, unless JUMP instruction is
encountered. Some instructions have an ARGUMENT: this can be a memory reference or
a number. Early computers had a single register or accumulator
that held the current value; all operations were done to this
accumulator value (computers shortly added more than one register, but
then bits in the instruction had to be allocated to specifying which
register).
In chapter 7 of Dale & Lewis, the Pep/7 virtual machine is
presented. There is a single accumulator; all operations are performed
with respect to this. Some simplified examples:
LOAD addr // load the contents of memory location "addr" into the accumulator
STOR addr // store the contents of the accumulator at the specified location
ADD addr // add the quantity at the specified address to the accumulator
ADD #5 // Add the value '5' to the accumulator
CLEAR // sometimes AND #0, sometimes LOAD #0
TEST // not actually used in Pep/7
BR addr
BREQ addr
// branch to the specified addr if the accumulator is zero
Actually, Pep/7 uses LOADA, STORA, ADDA, and uses a second operand
of 'i' or 'd' (immediate or direct) to specify in a LOAD or ADD whether
we're treating the following number as an address or the literal
quantity.
Generally speaking, an 8-bit machine has an 8-bit bus (formerly buss); that is, 8 bits at a time can be transferred to and from memory and peripherals. Similarly 16-bit and 32-bit.
The more immediate bit-sizing concern, however, is addressable
memory. Each byte in RAM is numbered, starting at 0. A memory address
generally has to fit into one "word" (approximating the bus size). A
16-bit address space maxes out at 216 = 64KB of memory (the
first 16-bit-address machines had less than that). This puts a pretty
hard ceiling on how much data a program can store in memory, or even
how big the program itself can be. The IBM/370 had 24-bit-addressing,
for a maximum memory size of 224 = 16 megabytes. The world then moved rapidly to 32-bit addressing, which can address 4 GB.
Most servers purchased today are 64-bit-address systems, though that
wasn't true five years ago. Generally database systems are the first
adopters, as they like to keep essentially the entire database in RAM.
The original IBM PC had effectively 20 bits of address space, or 1
megabyte. However, most machines were originally shipped with about 16
KB, and MS-DOS memory-mapped the BIOS in at address 640KB. This was
originally seen as "we'll never get there", but towards the end of the
PC era everyone was struggling with ways to work around the "640KB
limit". Bill Gates is supposed to have said, "640KB should be enough
for anybody", but I'm not aware of concrete evidence.
How are we going to store things in a computer?
binary integers: 23 v 10111 v 00010111
Dividing into units: related to management of "memory"
bytes
words
Memory (RAM)
binary integers
floating-point and negative integers
Memory (disk)
not directly ADDRESSABLE
divided into sectors, clusters (physical v logical sectors)
ASCII