An Overview of Computer Hardware: Next
An Overview of Computer Hardware: Next
Systems Programming
Although the variety of computer system configurations is forever changing, as (new) component types employ different standards for their
interconnection, it is still feasible to discuss a simple computer model, and to discuss components' roles in operating systems.
The Central Processing Unit, or CPU, undertakes arithmetic and logical computation, and directs most
input and output services from memory and peripherals. There may be multiple processors in a
system, each executing the operating system or user/application programs.
Main Memory, or RAM (random access memory) is used to store both programs and data. Processors
read and write items of memory both at the direction of programs (for data), and as an artifact of
running programs (for instructions).
Peripheral Devices, Secondary Storage, or input/output modules, and their I/O controllers, move data
to and from the computer system, usually to provide longer-term, persistent storage of data (disks,
tapes),
A communications bus, or system bus, connects the processor(s), main memory, and I/O devices
together, providing a "highway" on which data may travel between the components. Typically only one
component may control the bus at once, and bus arbitration decides which that will be.
The role of the operating system in managing the flow of data to and
from its I/O devices is challenged by the wide variety of devices (Figure
11.1, over).
While waiting for a slow device to complete its I/O transfer, the
processor may be able to undertake other activities.
Processor Registers
As well as special logic to perform arithmetic and logic functions, the processor houses a small number of very fast memory locations, termed processor
registers.
Data in registers can be read and written very rapidly (with a typical access time of 1-3ns). If the required data is available in registers, rather than main
memory, program execution may proceed 10-500X faster.
Register types
Registers are generally of two types:
user-accessible registers -
are accessible to programs, and may usually be read from and written to under program control. Programs written in an assembly language, either by
a human programmer or generated by a compiler for a high-level language, are able to read and write these registers using specific instructions
understood by the processor which usually accept the names of the registers as operands.
Data registers hold values before the execution of certain instructions, and hold the results after executing certain instructions.
Address registers hold the addresses (not contents) of memory locations used in the execution of a program, e.g.
the memory address register (MAR) holds the address of memory to be read or written;
the memory buffer register (MBR) holds the memory's data just read, or just about to be written;
index registers hold an integer offset from which a sequence of memory references are made; and
a stack pointer (SP) holds the address of a dedicated portion of memory holding temporary data and other memory addresses.
hold data that the processor itself maintains in order to execute programs, e.g. the instruction register(IR) holds the current instruction being executed,
and the program counter (PC) holds the memory address of the next instruction to be executed.
Special registers reflect the status of the processor. The processor status word (PSW) reflects whether or not the processor may be interrupted by I/O
devices and whether privileged instructions may be executed, and it uses condition bits to reflect the status of recently executed operations: did an
arithmetic operation overflow, did an arithmetic operation perform a carry, did we just attempt a division by zero, did the last comparison instruction
succeed or fail?
Processors place constraints on how some registers are used. Some processors expect certain types of data to reside in specific registers. For example,
some registers may be expected to hold integer operands for arithmetic instructions, whereas some registers may be reserved for holding floating-point
data.
As a result of executing a program, processors update many of the address registers implicitly. For example, instructions to push and pop data values to
and from the stack automatically modify the contents of the stack pointer.
(An excellent, albeit expensive, text introducing computer system organisation in depth is Computer Organization and Design, Fifth Edition: The
Hardware/Software Interface, by David A. Patterson and John L. Hennessy. Morgan Kaufmann Publishers, 5th edition, October 2013.)
We also expect memory to be able to provide the necessary data, as quickly as possible, when called upon. Unfortunately, there is a traditional trade-off
between cost, capacity, and access time:
the faster the access time, the greater the cost per bit,
the greater the capacity, the smaller the cost per bit and, the greater the capacity, the slower the access time.
For example, a contemporary home computer system may include a modest amount of cache memory (1MB) to deliver data as quickly as possible to the
processor, a larger main memory (8GB) to store entire programs and less- frequently required data, and long term, persistent storage in the form of a hard
disk (1TB), or SSD (256GB).
Bits are organised into larger groupings to store values encoded in binary bits. The most basic grouping is the byte: the smallest normally addressable
quantum of main memory (which can be different from the minimum amount of memory fetched at one time). In modern computers, a byte is almost
always an 8-bit byte, but history has seen computers with 7-, 8-, 9-, 12-, and 16-bit bytes.
A word is the default data size for a processor. The word size is chosen by the processor's designer and reflects some basic hardware issues (such
as the width of internal or external buses). The most common word sizes are 16 and 32 bits; historically words have ranged from 16 to 60 bits.
It is very common to speak of a processor's wordsize, such as a 32-bit or 64-bit processor. However, different sources will confuse whether this
means the size of a single addressable memory location, or the default unit of integer arithmetic.
Some processors require that data be aligned, that is, 2-byte quantities must start on byte addresses that are multiples of two; 4-byte quantities must
start on byte addresses that are multiples of four; etc. Some processors allow data to be unaligned, but this can result in slower execution as the
processor may have to align the data itself.
However, it is important to realise that the processor can interpret a sequence of bits only in context: on its own, a sequence of bits means nothing.
4 ASCII characters,
a 32-bit integer,
2 x 16-bit integers,
1 floating point value,
the address of a memory location, or
an instruction to be executed.
No meaning is stored along with each bit pattern: it is up to the processor to apply some context to the sequence to ascribe it some meaning.
For example, a sequence of integers may form a sequence of valid processor instructions that could be meaningfully executed; a sequence of processor
instructions can always be interpreted as a vector of, say, integers and can thus be added together.
Critical errors occur when a bit sequence is interpreted in the wrong context. If a processor attempts to execute a meaningless sequence of instructions, a
processor fault will generally result: Linux announces this as a "bus error". Similar faults occur when instructions expect data on aligned data boundaries,
but are presented with unaligned addresses.
However, another program could read the bytes from /bin/ls and interpret them in other ways, e.g. as 32-bit integers:
prompt> od -l /bin/ls
0000000 1179403647 65793 0 0
0000020 196610 1 134518416 52
0000040 66628 0 2097204 2621447
0000060 1638426 6 52 134512692
0000100 134512692 224 224 5
0000120 4 3 276 134512916
0000140 134512916 19 19 4
0000160 1 1 0 134512640
or as ASCII characters:
prompt> od -c /bin/ls
0000000 177 E L F 001 001 001 \0 \0 \0 \0 \0 \0 \0 \0 \0
0000020 002 \0 003 \0 001 \0 \0 \0 220 226 004 \b 4 \0 \0 \0
0000040 D 004 001 \0 \0 \0 \0 \0 4 \0 \0 \a \0 ( \0
0000060 032 \0 031 \0 006 \0 \0 \0 4 \0 \0 \0 4 200 004 \b
0000100 4 200 004 \b 340 \0 \0 \0 340 \0 \0 \0 005 \0 \0 \0
0000120 004 \0 \0 \0 003 \0 \0 \0 024 001 \0 \0 024 201 004 \b
0000140 024 201 004 \b 023 \0 \0 \0 023 \0 \0 \0 004 \0 \0 \0
0000160 001 \0 \0 \0 001 \0 \0 \0 \0 \0 \0 \0 \0 200 004 \b