IPT - A Virtual Approach IPT A Virtual Approach by Peter Whitehouse
Quick Links:
Hardware Home
Information and Intelligent Systems Social and Ethical Implications Human Computer Interaction Software and Systems Engineering eXercise Files Course Outline and Assessment A-Z of Geeky Acronyms Terrace Work Program 2004 Sillybus FAQ = Frequently Asked Questions Help


Primary Memory

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)

DOS 5 memory model

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 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 (~)


(simply reverses the state of the bit/bits)

      eg.  not 1 = 0
              ~1 = 0
         not 101 = 010
            ~101 = 010
    not 10001110 = 01110001     etc..


(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

       and 110111
         = 100101   (note it is 'stacked' like an addition sum)


(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

        or 110111
         = 111111   (note it is 'stacked' like an addition sum)

ORDER OF PRECEDENCE (order convention)

() ~ & V


   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

    xor 10110110
     =  01010011


   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:

      fetch an instruction from memory
      decode the instruction
      execute the instruction if able, complain if not (then interrupt)
   until (interrupted or finished)
CPU and Memory
  • 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 ..)


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.....


©Copyright t 1992..2018+. Edition 26.150117
Creative Commons License
This work is licensed under a
Creative Commons Attribution-NonCommercial-ShareAlike 2.1 Australia License