Você está na página 1de 9

CSC 5321: ADVANCED OPERATING SYSTEMS

INSTRUCTION FETCH & EXECUTE MODEL


FROM INTELS PERSPECTIVE

A program to be executed by a processor comprises of a list of instructions stored in memory. A


computer is built to execute instructions that are written in a very simple type of language
called machine language. Different types of computers have their own machine language, and
can execute a program only if it is expressed in that language. So to execute programs written
in other languages, they need to be first translated (compiled) into machine language. For
example, the following C language statement
a = b +c;

// Sum variable b & c and put the result into a

Will be translated to following assembly language:


load R3, b
load R4, c
add R3, R4
store R3, a

//
//
//
//
//

Copy the value of b from memory to register R3


Copy the value of c from memory to register R4
Sum the contents of register R3 & R4
Sum will be placed in register R3
Store the value of register R3 into memory cell a

The assembly instructions are in turn translated into machine instructions. When the CPU wants
to execute a program it first stores (by reading it from storage device) that program (in
machine language format, of course) in the computer's main memory (RAM or random access
memory). Along with the program, memory can also hold data that is being used or processed
by the program. Main memory consists of a sequence of locations. These locations are
numbered, and the sequence number of a location is called its address. An address provides a
way of picking out one particular piece of information from among the millions stored in
memory. The CPU executes a program that is stored as a sequence of machine language
instructions in main memory. It does this by repeatedly fetching an instruction from memory
and then executing that instruction. This process of fetch an instruction, executes it, fetch
another instruction, execute it, and so on forever -- is called the fetch-and-execute cycle.
As shown in Figure 1, our example assembly code is translated into machine language and
loaded into the main memory. The program counter (PC) will hold the address of the next
instruction to be executed (we are assuming that each machine instruction is encoded in such a
way that it takes 4 bytes each). So, as in Figure 1, when the first instruction is ready to be
executed (fetched from memory location and decoded) in the instruction register (IR), the PC is
pointing towards the next instruction (PC=PC+4) in-line to be executed. Let us now take a
detailed overview of the fetch and execution cycle.
To start off the fetch cycle, the address which is stored in the PC is transferred to the memory
address register (MAR). The CPU then transfers the instruction located at the address stored in
the MAR to the memory buffer register (MBR) via the data lines connecting the CPU to memory.
This transfer from memory to CPU is coordinated by the control unit (CU). To finish the cycle,
the newly fetched instruction is transferred to the IR and unless told otherwise, the CU
increments (by size of instruction) the PC to point to the next address location in memory. All
these require several clock cycle to finish. After the CPU has finished fetching an instruction, the
CU checks the contents of the IR and determines which type of execution is to be carried out

load
load
add
store

Memory
Address

Fetch &
Execute
Logic

PC

R3,
R4,
R3,
R3,

b
c
R4
a

3046 1011111000101010..1

3050

3050 1011111000110011..0
IR

3054 1111101010101010..1

load R3, b

3058 1010110001010101..1
CPU

Machine
language

RAM

Figure 1. The PC, IR and RAM


next. This process is known as the decoding phase. The decoding phase performs different
checks such as, whether the instruction is a privileged instruction, whether the processor have
proper access to execute that instruction, is it a trap instruction etc. If the decoding phase finds
any such anomalies, it will raise an exception. The CU will save the current PC value (so that
after the exception is handled, the program could resume execution at the place after the
exception raised instruction) and load the PC with the corresponding Interrupt Service Routines
(ISR) start address and move to the kernel segment, so that the exception could be handled in
the proper way. If everything is alright in the decoding phase then the instruction is now ready
for the execution cycle.
After the instruction is executed (the execution step is complex and detailed in its own context,
which we are not describing for simplicity), the CU checks for any interrupts happened? If no
interrupts are there to handle, then the next instruction will be fetched and the fetch and
execution cycle continues again. On the other hand, if there is an interrupt to handle, then the
CU will save the current PC value (so that after the interrupt is handled, the program could
resume execution at the right place where it was suspended) and load the PC with the
corresponding Interrupt Service Routines (ISR) start address and set the segment value to
kernel segment, so that the interrupt could be handled in the proper way (interrupt must be
handled in supervisor mode).
Figure 2 shows the flowchart for the generic fetch and execute cycle and Figure 3 shows one
for Intel Architecture. As Intel do not have any user/supervisor bit, the mode checking is
complicated and we only show few important checks that the fetch & execute cycle performs.
In case of a Trap instruction, there should be mechanisms by which the user program that
performs the Trap could get the control back. Intel uses instruction RTE (Return from
Exception) at the end of any Trap or exceptions, which recover the processs context and
change to user segment.

Start

Fetch an instruction from


a memory address, found
in the PC

Load the instruction to IR


Increment the PC, so that it
will now point to the next
instruction in memory

Decode instruction
in IR

Privileged
?

Yes

U/S bit=1
?

Save current PC

No

No
No

Any
Interrupt ?

Load PC with a predetermined value

Yes

Execute instruction
in IR

Set user/supervisor
bit to 1

Yes

Load PC with a predetermined value

Set user/supervisor
bit to 1

IN HARDWARE

IN HARDWARE

Save current PC

Figure 2: Generic Instruction Fetch & Execution Cycle

Start
Privileged
?
Fetch an instruction from a
memory address, found in
the PC

Yes

PC Address >
PAGE_OFFSET
?

No

Is it in Kernel
Segment?
?

No

U/S bit =1
?

Yes

Load the instruction to IR

Increment the PC, so that it


will now point to the next
instruction in memory

Yes

Destination=
mode register
?

Is it in Kernel
Segment
?

Yes

No
Decode instruction
in IR

No

Its a
TRAP
?

Yes

No

No

Any
Interrupt ?

Execute instruction
in IR

Yes

Save current PC

Set U/S bit


to 1

Load PC with a predetermined value

Set current segment =


kernel segment

IN HARDWARE
Figure 3: Instruction Fetch & Execution Cycle in Intel Architecture

When the computer is powered up, the CU in the


CPU will start the fetch and execute cycle and will
continue to do so, until the computer is powered
down. After the computer is turned on, the
processor is suffering from amnesia; there is
nothing at all in the memory (PC) to execute. Of
course the hardware makers know this will
happen, so they pre-program the processor to
always look at the same place (physical address
0xfffffff0) in the system BIOS (Basic Input Output
System) ROM (a read only, persistent memory
chip, Figure 4) for the start of the POST (Power
on Self Test) program. So, when the system is
powered on, the PC is pre-loaded with that Figure 4. A BIOS chip in the motherboard
hardwired address. So the instruction on that
location will be loaded into IR and the PC will be incremented and the fetch and execute cycle
will continue. This way all the instructions listed afterwards in the BIOS will be executed by the
processor. The instructions in BIOS normally do various tests to check that all essential
hardware components are fine and initialize them, and will then start the operating system
booting process. It will choose a boot device (floppy, CD, Hard disk, USB etc.) in the order listed
in the BIOS. If no available boot device is found, it will print an error message and will halt. The
BIOS instruction will read the first sector of the available boot device. The first sector of the
boot device is called the boot sector. The boot sector contains a small program (boot loader,
such as LILO or GRUB or Operating systems own boot loader) whose responsibility is to read
the actual operating system from the disk and start it. So, when the boot loader is completely
loaded into RAM, the last BIOS instruction will be a jump instruction, that will jump to the first
instruction of the boot loader and puts that into the PC. So, execution is now transferred to the
boot loader and the fetch and execute will now continue from the first instruction of the boot
loader. Figure 5 shows this overall picture.
RAM
Boot
Prog.

ROM
Power Up

POST

Loader

BIOS

OS

Boot Device

CMOS
Hardware Process
Data Flow

Figure 5: Intel System Initialization

After the loader completely loads the Linux kernel into the memory, it will first uncompress itself
as the Linux kernel is installed compressed. This is due to several reasons but the important
reason is that copying a small compressed kernel is much faster then copying a big
uncompressed kernel. After that, the kernel does the following tasks to create a proper
environment for user programs to run:
Checks what hardware is there and configures some of its device drivers
appropriately.
Enable virtual memory/paging support.
Do memory layout analysis and initializations.
Initialize and enable interrupts.
Do other initializations, such as, scheduling, timers etc.
Mount root file system.
Create the first kernel thread (init) that performs operating system environment
initializations.
Go into the idle loop, which is the loop executing when nothing else is to be
scheduled.
After all that the system is truly running and ready for user commands and user tasks. It will
then print a prompt so that user can login to the system and run their processes.
Figure 6 shows the overall sketch of the system booting process in Linux.

Boot Process with Linux (Kernel 2.4.x)


Power On

STARTUP

BIOS POST

Boot loaders, such as


LILO or GRUB

Either

Linux boot loader in file:


arch/i386/boot/bootsect.S

Compressed kernel head:


arch/i386/boot/compressed/head.S

KERNEL
STARTUP

Startup initialization in file:


arch/i386/boot/setup.S
Uncompressed kernel head:
Kernel source:
arch/i386/kernel/head.S
Kernel source: init/main.c

ENVIRONMENT
INITIALIZATION

idle loop
Kernel source:
arch/i386/kernel/process.c
Nothing
to do

init thread
Kernel source: init/main.c

Ready to
rock & roll

Figure 6: PC boot process and kernel source code accessed during booting.

References:
1. The Fetch and Execute Cycle: Machine Language, http://math.hws.edu/javanotes/
c1/s1.html.
2. Operating Systems, Gary Nutt, Addison Wesley Publication, Third Edition, 2004.
3. Operating Systems, William Stallings, Prentice Hall Inc., 1995.
4. The Linux System Administrator's Guide, Version 8, Lars Wirzenius, http://www.tldp.org/
LDP/sag/sag.pdf.
5. Linux Red Hat 9 Reference Guide, http://www.redhat.com/docs/manuals/linux/RHL-9Manual/pdf/rhl-rg-en-9.pdf.
6. Linux Kernel 2.4 Internals, Tigran Aivazian, http://www.moses.uklinux.net/patches/lki.html.
7. The Linux/i386 boot protocol, Linux Redhat Source Code, Documentation/i386/boot.txt.