Software is built in layers of abstraction from the hardware level (kernel) to the operating system level to user applications. Programs are written in programming languages and compiled into machine-readable code. Software is developed using techniques like modularization with functions and separation into multiple source files. Key concepts include variables, conditionals, loops, functions, and organizing code across files with headers.
2. Lecture 1
Software Fundamentals
Definition of Software:
Programs that are stored in the computer and instruct it how to behave
Software Model
Software is built up in layers. These layers of ‘abstraction’ mean that the
user will never have to directly interface with the hardware, or even be aware
of it.
The layers can be visualised in the following way:
User Software
Applications
OS
Kernel
Kernel - The core of the system that interfaces with the hardware
The kernel is the central component of the operating system and manages the
system resources - memory, processors and devices.
The Linux kernel was written in 1991 by Linus Torvalds and is an ‘open
source’ OS kernel (released under the GNU General Public License). The
source code for the kernel, written in the C programming language, is
constantly being updated by a worldwide community of thousands of
developers. The current version is 2.8.23 and contains support for hundreds
of different devices and platforms.
Lecture 1: Software Fundamentals
BIT204: Software Design – James Uren
2
4. OS - The main piece of software that controls the fundamental operation of
the computer
The OS (Operating System) is the
layer between the kernel and the
user and application software. Early
OS’s e.g. MS-DOS had a text
interface (command line) that could
be used to build user software and
load applications.
Modern operating systems
have a GUI (Graphical
User Interface). Microsoft
Windows (most recently
version ‘Vista’) and
MacOS X (10.5 Leopard)
are the most common
examples. Linux
distributions include
Fedora (now Core 9 from
RedHat), Ubuntu, Caldera
and Debian and are all
based around the same
kernel.
The OS and the kernel are
referred to as ‘system software’
Applications – Software that the user uses
Pieces of application software are tools that run within the framework of the
operating system. Examples are word processors, spreadsheets, databases,
computer games. Applications may be distributed with the OS, sold with a
licensing model, or available for free download as Freeware.
User Software – Software that is written by the user within an application
Applications may be configured or programmed to perform specific tasks.
Examples are ‘macros’ in Microsoft Office applications, or data capture and
analysis in LabView, a graphical programming tool.
Note that this is different to the user designing application software, discussed
in more detail later.
Lecture 1: Software Fundamentals
BIT204: Software Design – James Uren
4
5. Software Layers
Software is normally designed with an abstraction layer model. This is often
implemented with libraries of software functions (e.g. Dynamic Link Libraries,
DLLs) that provide an API (Application Programming Interface) for the
programmer to communicate with lower levels of software or the operating
system.
Software Design and Programming
Computers can be programmed to perform tasks and provide functionality for
users. Computer programs are written in a programming language that is
then compiled into machine code that the processor can understand.
Each line of machine code consists of an instruction (op-code) and an
address in memory to operate on (operand). Example instructions might be
ADD, MOVE or BRANCH (move to another place in the program).
Modern processors still operate with a tape model outlined by Turing, the
Turing Machine:
In this model the program is stored on the tape and the read head looks at
each instruction and address in turn and performs the appropriate action.
Machine code can be written directly in assembly language (often called
assembler), where each mnemonic is converted to the machine code
equivalent. More often software is written in a ‘higher level language’ that
uses more meaningful expressions and programming structures. Examples of
higher-level languages are Visual Basic, C, Java etc.
Software Development Lifecycle
In 1970 Royce proposed the waterfall model for software development:
Lecture 1: Software Fundamentals
BIT204: Software Design – James Uren
5
6. • Specify the requirements of the software
• Design the software architecture
• Implement the software
• Test and debug the software to verify its operation
• Maintain and document the software
Programming Constructs
A program is a sequence of commands that are executed by the processor in
turn. To make programming easier the software is written in a higher-level
language that is converted (or ‘compiled’) into the command sequence
(machine code) that the processor can understand.
C is a higher-level language and all higher-level languages follow basic rules
of structure and syntax. If there are any errors in the code the compiler will
inform the programmer and prevents them from running faulty on the device.
Variables
Information in software is stored in variables where each variable represents
an allocation of the machine’s RAM memory. To store a single whole number
that could be between –32768 and +32768, for example, it is necessary to
declare a 16-bit (2-byte) integer x, say, to hold that value. All variables must
be declared before they are used in the code. The code for this declaration in
C would be as follows:
int x;
Lecture 1: Software Fundamentals
BIT204: Software Design – James Uren
6
7. We are then free to use that integer variable, with name x, by assigning it a
value in the following way:
x = 2; // “let x equal two”
Or increment the value held in it:
x = x + 1; // this can also be written a x++
The new x equals the old x plus one, so in this case it would now contain the
value three.
The // denotes a code comment and anything after it on that line will be
ignored by the compiler. It is good practice to use comments to describe the
function of the code. Any code contained within /* and */ will also be ignored.
It is important that the compiler knows the ‘type‘ of variable (in this case ‘int’
for integer) so the correct amount of memory can be allocated to it, and
prevent two variables of different types being swapped or combined (this is
called a ‘type mismatch’).
There are a number of different variable types. The most common are listed
below:
short x; // an 8-bit integer e.g. 100
int x; // a 16-bit integer e.g. 1000
long x; // a 32-bit integer e.g. 100000
float x; // a floating-point number e.g. 5.243
char x; // an ASCII character e.g. ‘K’
These variable types can also be signed or unsigned (the default is signed).
With the example of the integer x (a number in the range -32768 to +32768), if
we were to declare it unsigned:
unsigned int x;
then the value of x could now be in the range 0 to +65536.
Conditionals
A conditional is a decision point in the software flow. If some condition is true
then one section of code is run; otherwise a different section is run.
if (x < 10)
{
x = 12;
}
else
{
Lecture 1: Software Fundamentals
BIT204: Software Design – James Uren
7
8. x = 13;
}
The condition is inside the parenthesis ( ), and the code sections that are
written between curly brackets { }. In this case we ask if the value held in the
variable x is less than 10.
Loops
It is often necessary to perform the same task a number of times, and to
achieve this the section of code to be repeated is placed within a loop. The
simplest form of loop is a ‘while’ loop that will repeat the section of code while
some condition is true.
x = 0; // initialise x to 0
while (x < 10) // repeat as long as x < 10
{
x++; // increment x
}
// carry on
So a while loop also has a condition associated with it, and as soon that
condition is false (x is not less than ten in this case) we will break the loop and
carry on executing the rest of the program. In this example since x starts at
zero and is incremented by one each time round the loop, the loop will
execute exactly ten times before the condition is false. This provides a way of
performing some task a set number of times.
The same effect can be achieved using a ‘for’ loop.
for (x = 0; x < 10; x++)
{
// here enter the code to repeat
}
// carry on
The ‘for’ line states: Let x equal zero. Loop while x is less than ten, increment
x by one each time.
Source Files
The code is split into source (.c) files and header (.h) files. All the code
described above is source code, but as well as this, headers are used
containing the declarations and definitions for the program. The main source
Lecture 1: Software Fundamentals
BIT204: Software Design – James Uren
8
9. file in the piece of software (normally named main.c) contains the start and
end point of the program.
int main()
{
// your program
}
Functions
To keep the code as concise and tidy as possible, it is useful to generate
blocks of code that can be used a number of times in different parts of the
program, or provide some single useful function. The former is known as a
sub-routine and is defined in the following way:
void DoSomething() // the name of the function
{
// the function code is written here
}
The ‘void’ tells the compiler this is a sub-routine.
Then in the main program (or from within another function) the routine can be
‘called’ without needing to write all the code again:
int main()
{
DoSomething(); // this will run the code
// written above
// ...
DoSomething(); // this will run the code again
// without needing to re-write it.
}
This will also mean that if the code inside the routine needs to be changed, it
will only need to changed once in the original definition.
Functions can also be ‘passed’ values and ‘return’ a result, so for example an
averaging function might be written as follows:
float Average(int a, int b)
{
return (a + b) / 2;
}
Lecture 1: Software Fundamentals
BIT204: Software Design – James Uren
9
10. Note that the ‘void’ is replaced ‘return type’ in a function and here it needs to
be a float because the average of two integers is not necessarily a whole
number.
This could then be called from main():
int main()
{
int x;
x = 0;
while ( Average(x, 10) < 7 )
{
DoSomething();
x++;
}
}
This while loop will call the sub-routine DoSomething() five times, because as
x increases from zero the average of x and ten also increases (5, 5.5, 6, 6.5,
7…).
Headers and Multiple Files
It is good practice to arrange the functions into multiple files and group them
in a sensible way. For example, the Average function in the previous section
could be grouped with other calculations (Sum, Sin etc) into a source file
called math.c. To link this file to main.c, create a header file, math.h, that
declares which functions are contained in the source.
The header math.h could hold for example:
#ifndef __MATH_H__
#define __MATH_H__
float Average(int a, int b);
int Sum(int a, int b);
float Sin(float x);
float Cos(float x);
float Tan(float x);
#endif
The # lines are necessary to ensure the file is not duplicated a number of
times throughout the program.
Then the source file, math.c would include the header and then describe the
actual code:
Lecture 1: Software Fundamentals
BIT204: Software Design – James Uren
10
11. #include “math.h”
float Average(int a, int b)
{
return (a + b) / 2;
}
int Sum(int a, int b)
{
return a + b;
}
// etc...
In the main program, it is now only necessary to include the header and
main.c will have access to all the functions in math.c:
#include “math.h”
int main()
{
int x;
x = Sum(4,5) + Average(15,12) + Sin(180);
}
There are a number of useful header files already available (math.h is one of
them) and to use them simply include the file in the following way:
#include <math.h>
Lecture 1: Software Fundamentals
BIT204: Software Design – James Uren
11