Following discussion based on 16 bit internal data path width (ie.8088/8086
processors). Major variations occur with other chips that are capable
of addressing more memory.
There are two main classifications of memory:
- RAM (Random Access Memory) - volatile memory (can be
changed, lost when power off)
- ROM (Read Only Memory) - nonvolatile (generally safe
when power off)
Every byte in memory (primary and secondary) has a unique name (called
its address). An address is usually displayed as a 5 digit (16
bit) Hex number.
Bottom of primary memory has the address 00000 (hex)
Top has address FFFFF (hex)= 1048575 bytes(1 Mb)
Memory is arranged logically. The physical locations of the bytes may
be scattered around various parts of the 'mother board' and various
cards plugged in to it, but the CPU views primary memory as a contiguous
set of bytes.
Certain sections of primary memory contain vital routines and so are
designated ROM, others are for temporary storage of user programs and
data and are RAM. The addresses of vital routines are usually fixed,
whereas user programs may occupy different locations for successive
runs depending on what else is loaded into memory at the time.
generally, in hex we have
C0001 ----> FFFFF = ROM = upper memory
A0001 ----> C0000 = VIDEO RAM = upper memory
00000 ----> A0000 = RAM = Conventional Memory
Upper memory (ROM) is where a number of low level service routines
are stored permanently, including BIOS (Basic Input-Output System),
drive controller roms and the like.
Upper memory (VRAM) actually contains space for Video controller routines,
TSR's (ie. programs that Terminate but Stay Resident), some device drivers
and other user-loaded service routines. It may also house sections of
the operating system (much of which can be loaded high)
Conventional memory contains space for some of the operating system,
along with space for your application's programs, and work space.
When you buy more RAM for your computer these days, you are adding
to your computer's EXTENDED MEMORY. In order to use this memory, a program
(an extended memory manager) is required. Conventional DOS programs
cannot make use of extended memory.
Extended memory is usually accessible using modern operating environments
(and most of the Graphical User Interfaces). Windows 3.11 (as an example)
can utilize up to 16Mb of RAM. Win95 can use more, as can OS2, NT and
others.
On 80826's and up, the first 64K of Extended memory is called the HIGH
MEMORY AREA (from 1024K up to 1088K) which can be used to store parts
of DOS.
EXPANDED MEMORY is memory additional to conventional memory, usually
is found on a separate memory board, and is accessed by some programs
by an expanded memory manager program. These days, most computers do
not have EXPANDED memory (which is relatively slow) in favour of EXTENDED
MEMORY. For programs that require expanded memory, it is possible to
get your machine to use part of conventional memory as a substitute
for expanded memory, but this often impacts on performance of the system
as a whole.
Segmented Memory Addressing
Data, memory addresses the data comes from and control logic travel
to and fro around the motherboard on it's journey to be processed. Such
bit streams travel along BUSSES (bundles of very fine wires,
or clusters of circuit board connections). The width of a BUS (ie. how
many 'wires' are contained within a bus) partly determines how quickly
data can be transported around the machine.
If we can transport the address of a byte in memory, then that computer
can use that byte, if the address is un-transportable, then the machine
cannot 'see' that chunk of memory.
A 16 bit address bus complicates memory addresses. To represent a FULL
Megabyte, we require 20 bits for the address. With 16 bits, we can only
represent 65536 byte addresses ... whatabout the rest? (if we are dealing
with a Megabyte of primary memory, we are seemingly unable to transport
the addresses of 983040 bytes that live in upper memory alone).
A 'shorthand' scheme for referring to memory addressing has developed,
allowing us to refer to a full megabyte of memory (with extensions to
allow much larger memories to be accessed)
A paragraph = 16 bytes
It was realised that an address could be expressed in TWO parts:
- The SEGMENT= the number of 16 byte paragraphs above the
base of memory
- The OFFSET= the number of bytes above the last paragraph
The SEGMENT is sent as 4-digit HEX down the 16 bit address bus first
- and is stored on the CPU in the SEGMENT REGISTERS. Once a segment
arrives, the 16bit address bus is used to transport the OFFSET. The
CPU uses the previously transported segment as a reference starting
point in memory, and the offset tells the CPU how far above (how many
bytes) that memory location we are referring to.
Using this scheme, we can refer to 64K of bytes in memory without having
to change the segment - bytes in this range are called NEAR CALLS. If
a target byte falls outside the 64K area described by the current segment,
a NEW SEGMENT is requested - this is termed a FAR CALL.
Clearly, if a program does not need any more than 64K to 'live and
work' in, then it avoids the need to re-send segments and executes much
faster than one that continually requires far-calls.
segment : offset
4 hex digits : 4 hex digits
example 1 030F : 002A
= (3x256 + 15) paragraphs + (16 + 10) bytes
= 783 paragraphs + 26 bytes
= (783 x 16) + 26 bytes
= 12554 bytes
example 2 403C : 2410
= (4x4096+3x16+12x1)paras+(2x4096+4x256+16)bytes
= 16444 paragraphs + 9232 bytes
= 16444x16 + 9232 bytes
= 272336 bytes above base
Normalisation
Normalisation is writing the address with as many paragraphs as possible
- normalising an address maximises the number of bytes that can be referred
to above it, without performing a FAR CALL. Whereever possible, computers
transmit normalised addresses.
example 1 00A3 : 003C
= 00A3 : 0000
+ 003 : 000C
= 00A6 : 000C
= 00A6C (in 5 digit hex)
example 2 04CE : 011F
= 04CE : 0000
+ 011 : 000F
= 04DF : 000F
= 04DFF (in 5 digit hex)
example 3 0FAE : 1C53
= 0FAE : 0000
+ 01C5 : 0003
= 1174 : 0003
= 11743 (in 5 digit hex)
So What?
an address for anywhere in the 1 Mb primary memory space can be addressed
with a 20 bit address, by sending the segment (16 bits) and then the
offset (up to 16 bits).
Bit Manipulation
Computers work in binary - they use remarkably few operations to achieve
the complex things they are programmed to do.
3 simple operators: and (&) or (V) not (~)
NOT
(simply reverses the state of the bit/bits)
eg. not 1 = 0
~1 = 0
not 101 = 010
~101 = 010
not 10001110 = 01110001 etc..
AND
(binary operator conjunction)
eg. 1 and 1 = 1 1&1=1
1 and 0 = 0 1&0=0
0 and 1 = 0 0&1=0
0 and 0 = 0 0&0=0
101101
and 110111
= 100101 (note it is 'stacked' like an addition sum)
OR
(binary operator union)
eg. 1 or 1 = 1 1V1=1
1 or 0 = 1 1V0=1
0 or 1 = 1 0V1=1
0 or 0 = 0 0V0=0
101101
or 110111
= 111111 (note it is 'stacked' like an addition sum)
ORDER OF PRECEDENCE (order convention)
() ~ & V
examples:
if p = 1, q = 0, r = 1, then try to evaluate these:
(a) ~p&qVr; = ?
(b) pVq&~r = ?
(c) p&~pV(~qVr) = ?
SHIFTR (Shift right)
eg. 11001010 shr 1 = 01100101
eg. 00111011 shr 1 = 00011101
eg. 10000000 shr 1 = 01000000
conclusion: shr is integer division (ie. remainder disappears or rather
is 'caught' by another address)
shr1 = div by 2 (2^1)
shr2 = div by 4 (2^2)
shr3 = div by 8 (2^3)
SHIFTL (Shift Left)
eg. 76 = 01001100 shl1 = 10011000 = 152
eg. 55 = 00110111 shl2 = 11011100 = 220
00110111 shl3 = 10111000 = 184 ?????
conclusion:shl is integer multiplication, so long as no bits falloff,
the answer is sensible (the bits that 'fall' do not go unnoticed -the
CPU compensates).
XOR (disjunction)
1 xor 1 = 0
1 xor 0 = 1
0 xor 1 = 1
0 xor 0 = 0
11100101
xor 10110110
= 01010011
BASIC OPERATIONS
addition = or
subtraction = and not
multiplication= shl
division = shr
Byte Manipulation of PORTS
External access can be gained to the CPU, via a number of ports (a
'port' = a byte or two wide writable area). These are DIFFERENT to the
'plug hole' ports in the back of your machine, although these are often
called 'ports' as well.
Most connected devices have access ports, control ports and data ports
that reside somewhere in memory. If you know where the ports are in
memory, you can directly control the device by manipulation of their
ports (you can, for example, write to a printer by sending bytes to
a particular port address).
As an Example, the printer control port is a byte wide memory location,
and its bits control how the printer behaves. If you change the value
stored there, you directly control what your printer does. Most peripherals
(and many internal systems) have their own control and data ports somewhere
in memory - if you know where they are, you can do some interesting
stuff.
Suppose bit 3 of the printer control port controls the form feed function
(for example)- if it is a 1 then the paper scrolls a whole sheet, and
we want to activate it or change it from whatever it is to a 1 (ie.
SET the bit):
mask: 00001000 (note the '1' in bit 3)
port or mask results in bit 3 being made a 1, regardless
of what it was before (1V0=1V1=1)
suppose we want to disable the paper out warning beep (which is bit
6, say) - that is change the value in bit 6 from a whatever it is to
a 0 (CLEAR the bit)
mask: 01000000 (note the '1' in bit 6)
not mask = 10111111 (an un-mask)
port and not mask results in the bit in the unmasked
position being cleared regardless of
what was there (0&0= 0&1=0)
suppose we want to check if the printer is ON LINE (ie. ready to receive
information), and we knew that bit 1 was the printer status bit(QUERY
the bit)
mask: 00000010 (note the '1' in bit 1)
if port and mask produces a byte identical to the mask,
then the bit must be set, otherwise it is clear (1&1=1; 1&0=0)
CPU Operation - In Overview
the CPU basically performs the following task:
repeat
fetch an instruction from memory
decode the instruction
execute the instruction if able, complain if not (then interrupt)
until (interrupted or finished)
- the programmable registers store current place in instruction stream
(instruction pointer), what to do next (program counter), and intermediate
answers to calculation tasks
- registers store addresses along with data
- instructions consist of an opcode and addresses for operands if
needed - these are in ASSEMBLER language or HEXADECIMAL or BINARY
- status flags keep track of effects of operations (like overflow,carry,
negative answers ..)
Interrupts
An interrupt is a code that commands the attention of the CPU. Interrupts
are generated by either your hardware or the software that is running.
- High Priority - hardware (like clock tick, printer message,keyboard
control key, disk drive...)
- Low priority - software (calls to stored procedures, like how to
copy one byte to another address, how to divide ...)
Interrupts are prioritised before being sent to the CPU - only interrupts
with a higher priority than the task currently being done by the CPU
will actually interrupt it
When an interrupt actually does reach the CPU, first the CPU must look
up the code for the type of interrupt.
Some Common Interrupts
Interrupt |
Description |
Address |
Points to |
00 |
Divide by Zero |
00000 |
7845:00CE |
04 |
Overflow |
00010 |
0070:0756 |
05 |
Print Screen |
00014 |
F000:FF54 |
08 |
Clock Tick |
00020 |
23E2:0174 |
09 |
Keyboard action |
00024 |
2C3A:14BA |
0B |
COM2 |
0002C |
F000:210D |
0C |
COM1 |
00030 |
F000:210D |
0E |
Floppy Disk A: |
0038 |
2106:0439 |
0F |
LPT1 |
0003C |
0070:0756 |
19 |
Bootstrap Startup Routine |
00064 |
0070:18E0 |
On receipt of an interrupt, the processor chip is instructed to search
the lowest 1Kb of primary memory (called the INTERRUPT VECTOR TABLE,
shown in part above) for the memory location of the HANDLER ROUTINE
for dealing with the interrupt are stored, then it dives off into memory
and performs those instructions.
The first part a handler routine usually incl to write the entire contents
of the programmable registers onto the STACK (called pushing on to the
stack). Registers are pushed onto the stack so that they can be later
retrieved when the original task is to be re- started after the interrupt
has been adequately dealt with.
The STACK is a LIFO (last in first out) structure. At the end of an
interrupt, the register values are usually popped off the stack back
into the CPU to resume the job it was doing before it was interrupted.
The CPU does not know the difference between data and instructions.
Malicious (or careless) programmers can easily instruct the computer
to copy data all over instructions and even key sections of the operating
system, mouse drivers, videoRAM etc.. Virus writers party on.....