Chapter 6 - System Software and Virtual Machines

(6.1) - Introduction

Operating the earliest automobiles was a complicated task: a driver would have to know all about the intricate details of the engine; how to set the throttle and the choke; how to crank the engine; and how to use the clutch and the gear shift levers to change speeds.

Operating the earliest computers was also a complicated task: a user would have to know all about the intricate details of the processor, how to convert data and instructions into sequences of 0-bits and 1-bits, and how to read the output as sequences of 0-bits and 1-bits.

Modern automobiles are much simpler to use and modern computers are also much simpler to use: we say they are user-friendly. A driver interfaces with the automobile through the dashboard. A user interfaces with the computer through the system software.

(6.2) - System Software

(6.2.1) - The Virtual Machine: System software manages the resources of a computer and makes them more accessible. It acts as an intermediary between the machine hardware and the user. Users interact with the machine through a virtual machine interface: they see a virtual machine or virtual environment instead of the actual machine itself (Fig. 6.1).

(6.2.2) - Types of System Software:

As an example of how system software is used, we consider the job of writing a program, running it, and saving its results in a data file. The steps are:
  1. Use a text editor to create program P in an English-like notation rather than binary.
  2. Use the file system to store program P on the hard disk.
  3. Use a language translator to translate program P into a machine-language program M and use the file system to store M on the hard disk.
  4. Use the loader to allocate memory space and load program M into memory.
  5. Use the scheduler to schedule and run program M.
  6. Use the file system to store the results of the program on the hard disk.
  7. If the program did not run correctly, use a utility called the debugger to help locate the error.
(6.3) - Assemblers and Assembly Language

(6.3.1) - Assembly Language: Machine language is complicated and hard to use:

Users of the earliest computers quickly realized the shortcomings of machine language and developed assembly language (a people-oriented version of machine language) and an assembler (a computer program to translate assembly language into machine language.)

Figure 6.4 illustrates the process of assembly language programming: the programmer writes a source program in assembly language; the source program is sent through the assembler to create an object program in machine language; and then the object program is loaded into memory and executed by the hardware to create the output.

The advantages of writing in assembly language are: using symbolic operation codes in place of numeric codes; using symbolic memory addresses in place of numeric addresses; and pseudo-operations to provide useful services like generating data. Each instruction in assembly language has a format like:

label: op code mnemonic address field --comment

The comment field is ignored by the assembler: it can be used to write an explanation of what the instruction is doing or just left blank. The label field is only necessary when some other instruction refers to this instruction or data item. Figure 6.5 shows the instruction set for a typical assembly language (the figure is identical to Figure 5.19):

Binary OpcodeOperationMeaning
0000LOAD XCON(X) --> R
0001STORE XR --> CON(X)
0010CLEAR X0 --> CON(X)
0011ADD X R + CON(X) --> R
0100INCREMENT X CON(X) + 1 --> CON(X)
0101SUBTRACT X R - CON(X) --> R
0110DECREMENT X CON(X) - 1 --> CON(X)
0111COMPARE X if CON(X) > R then set GT to 1, else 0
if CON(X) = R then set EQ to 1, else 0
if CON(X) < R then set LT to 1, else 0
1000JUMP XJump to location X
1001JUMPGT X Jump to location X if GT = 1
1010JUMPEQ X Jump to location X if EQ = 1
1011JUMPLT X Jump to location X if LT = 1
1100JUMPNEQ X Jump to location X if EQ = 0
1101IN XInput an integer into location X
1110OUT XOutput an integer from location X
1111HALTStop program execution

As an example, the assembly-language code to calculate A = B + C - 7 is:

LOADB-- Register R = B
ADDC-- R = B + C
SUBTRACTSEVEN-- R = B + C - 7
STOREA-- A = B + C - 7
.
.
.
HALT--Don't run into the data
A:.DATA0
B:.DATA0
C:.DATA0
SEVEN:.DATA7 -- The constant 7

.DATA is a pseudo-op to generate a data item.

(6.3.2) - Examples of Assembly Language Code: The following pseudocode uses a conditional operation to print the larger of two values, x and y:

Get the value of x
Get the value of y
If x > y then
Print the value of x
Else
Print the value of y

This pseudocode can be written in assembly language as follows:

.BEGIN-- Marks the start of the program
INX-- Input X
INY-- Input Y
LOADY-- Load Y into register R
COMPAREX-- Compare X to Y
JUMPGTPRINTX-- Jump if X > Y
OUTY-- Didn't jump so print Y
JUMPDONE-- and go to end
PRINTX:OUTX-- X > Y so print X
DONE:HALT-- Stop
X:.DATA0
Y:.DATA0
.END-- Marks the end of the program

The next example uses a loop to solve the following problem: Read in a sequence of non-negative numbers, one number at a time, and compute a running sum. When you encounter a negative number, print out the sum of the non-negative numbers and stop.

The pseudocode is:

Step 1: Set the value of Sum to 0
Step 2: Get the value of the first number, N
Step 3: WhileN is non-negative, execute steps 4 and 5
Step 4: Add the value of N to Sum
Step 5: Get the value of the next number, N
Step 6:End of the loop
Step 7:Print out Sum
Step 8:Stop

The assembly language code is:

.BEGIN
CLEARSUM
AGAIN:INN -- Start of loop
LOADZERO -- Test sign of N
COMPAREN
JUMPLTNEG
LOADSUM -- N non-negative so add it to SUM
ADDN
STORESUM
JUMPAGAIN -- and repeat the loop again
NEG:OUTSUM -- N < 0 so print SUM
HALT-- and stop
SUM:.DATA0 -- Running sum goes here
N:.DATA0 -- Input values go here
ZERO:.DATA0 -- The constant 0
.END

(6.3.3) - Translation and Loading: Before the running-sum program in the previous section can be executed it must be translated by the assembler into machine language and then loaded into memory by the loader.

Translating from one language to another can be quite a difficult task if the vocabulary, grammar, and syntax of the two languages differ greatly. Since assembly language is so close to machine language the assembler is a relatively simple piece of system software. The assembler must:

Converting the symbolic op codes to binary can be done using the binary search algorithm of section 3.5.3 on an alphabetized table of the symbolic op codes.

Opcode Table
Symbolic OpcodeBinary Opcode
ADD0011
CLEAR0010
COMPARE0111
DECREMENT0110
HALT1111
IN1101
INCREMENT0100
JUMP1000
JUMPEQ1010
JUMPGT1001
JUMPLT1011
JUMPNEQ1100
LOAD0000
OUT1110
STORE0001
SUBTRACT0101

Converting symbolic addresses to binary requires two passes over the source code: during the first pass the assembler builds a symbol table containing each label with its corresponding binary address and during the second pass the assembler looks up entries in the symbol table to get the appropriate addresses.

As an example we consider the running sum program in section 6.3.2. During Pass 1, the assembler reads in the assembly language while maintaining a location counter:

ASSEMBLY LANGUAGELOCATION
.BEGIN
CLEARSUM0
AGAIN:INN 1
LOADZERO 2
COMPAREN3
JUMPLTNEG4
LOADSUM5
ADDN6
STORESUM7
JUMPAGAIN8
NEG:OUTSUM9
HALT10
SUM:.DATA011
N:.DATA0 12
ZERO:.DATA0 13
.END

Also, during Pass 1, the assembler builds the Symbol Table for the program containing each label with its location:

Symbol Table
SymbolLocation
DecimalBinary
AGAIN10001
NEG91001
SUM111011
N121100
ZERO131101

The assembler might alphabetize the Symbol Table so Pass 2 can use the binary search algorithm:

Symbol Table
SymbolLocation
DecimalBinary
AGAIN10001
N121100
NEG91001
SUM111011
ZERO131101

Pass 2 of the assembler runs through the assembly language again and generates the binary machine language program using the Opcode Table to generate the binary opcode of each instruction and the Symbol Table to generate the binary address of each instruction.

Figures 6.11 and 6.12 show flowcharts for the two passes of the assembler.

The loader reads the object file, stores the machine-language instructions and data in the appropriate places of the RAM, and then sets the PC to the address of the first instruction in the program.

(6.4) - Operating Systems

A user issues a system command to tell the computer to perform some service like translate a program, load a program, run a program, etc. A system command might be a line of text typed into a terminal or it might be a menu item or icon selected by a mouse. The operating system is the software that examines the command and activates other system programs to perform the desired service.

(6.4.1) - Functions of an Operating System: The User Interface: The operating system (OS) runs in the processor whenever there is no other piece of user or system software running in the processor: it waits for the user to input a command (via the keyboard, the mouse, or some other input device.) When a legal command is received, the OS activates and schedules the appropriate software to process the command. Examples of OS commands are:

Operating systems started with text-oriented user interfaces: the OS would display a prompt character on the screen to signal the user that it is waiting for a command; the user would use the keyboard to enter a command; and the OS would process the command when the Return key was hit. Now the typical OS uses a graphical user interface (GUI) with icons and menu items displayed on the screen which the user selects using a mouse.

System Security and Protection: The OS must prevent unauthorized users from using the machine so a person is not allowed to use the machine until he/she logs on with an authorized username and password.

The OS must also prevent authorized users from performing unauthorized actions so different users are given different privileges with respect to each file: e.g., several users may be able to read the file but only a few are given permission to write to the file.

Efficient Allocation of Resources: The typical I/O operation might require several milliseconds to execute so the OS tries to keep the processor busy performing other useful tasks. It maintains three classes of programs:

If the program in the Running class initiates an I/O operation the OS moves it to the Waiting class and moves some other program from the Ready class to the Running class. A program in the Waiting class is moved to the Ready class whenever its I/O operation completes.

The Safe Use of Resources: The OS should prevent deadlock. As an example of deadlock suppose a system has one tape drive and one printer and two programs, A and B, make the following requests:

Program AProgram B
Step 1: Reserve the tape driveStep 1: Reserve the printer
Step 2: Reserve the printerStep 2: Reserve the tape drive
Step 3: Print a tape file Step 3: Print a tape file
Step 4: Release the printer and tape drive. Step 4: Release the printer and tape drive.

If Program A reserves the tape drive and Program B reserves the printer then each program will wait forever for the other program to release the second resource it wants to reserve.

(6.4.2) - Historical Overview: The earliest computers had no operating systems: each programmer would waste much computer time standing by the machine trying to debug a program.

In the mid-fifties batch operating systems became available: to debug a program a programmer would insert print statements around places in the code where bugs were suspected and submit a batch job on a deck of cards with job control language cards as well as code and data cards (see Figure 6.19) Machine usage was much better since programmers would examine their printouts off-line to find the bugs.

In the mid-sixties multiprogramming operating systems became available: memory holds many user programs at one time so if one program needs to wait for an I/O operation the processor can execute other programs. To make sure a user program doesn't clobber any other program or the OS, each user program is given an upper bound and a lower bound on the memory addresses it can access. To make sure a user program can't change its bounds or do other illegal actions, the instruction set has certain privileged op codes that only the OS can execute.

In the seventies time-sharing systems became popular: the central computer would be coupled to a number of terminals so several users could submit jobs and interact with them simultaneously (Figure 6.20).

As personal computers became faster and cheaper during the eighties they replaced the "dumb" terminals of the time-sharing systems. Since each PC could also compute as well as handle the functions of a terminal, the central computer of the time-sharing system became less and less important. There is still a need for centralized servers so local area networks (LANs) are now the norm (Figure 6.21).

A network operating system creates the virtual environment one sees today (Figure 6.22).


Kenneth E. Batcher - 9/30/2006