0% found this document useful (0 votes)
76 views14 pages

High Level Programming of Microprocessor

The document is a technical report on high level programming of microprocessors. It discusses: - The history of microprocessors and their use in computers and other electronic systems. - How high level programming languages like C, C++, Java allow programmers to write source programs using powerful operations that are later converted to many machine level operations. - The process of program translation, where a source program written in a high level language is compiled by a translator into an executable machine language program that can be executed by the processor.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
76 views14 pages

High Level Programming of Microprocessor

The document is a technical report on high level programming of microprocessors. It discusses: - The history of microprocessors and their use in computers and other electronic systems. - How high level programming languages like C, C++, Java allow programmers to write source programs using powerful operations that are later converted to many machine level operations. - The process of program translation, where a source program written in a high level language is compiled by a translator into an executable machine language program that can be executed by the processor.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 14

Report

HIGH LEVEL PROGRAMMING


OF MICROPROCESSOR.
DEPARTMENT: ELECTRICAL ENGINEERING

Name: Muneer Ahmed


Student Id: 413-2015
Subject: Technical Writing Report
Teacher Name: Dr Sufiyan Memon
CONTENTS PG, NO

INTRODUCTION: .................................................................................................................... 2

MICROPROCESSOR HISTORY: ................................................................................................. 2

HIGH LEVEL PROGRAMMING LANGUAGES ............................................................................. 2

SOURCE PROGRAMS: ............................................................................................................. 3

PROGRAM TRANSLATION ...................................................................................................... 4

PROGRAM EXECUTION .......................................................................................................... 5

INTERPRETER......................................................................................................................... 6

WHAT ARE INSTRUCTIONS AND HOW ARE THEY USED? ......................................................... 6

SMALL EXAMPLE: .................................................................................................................. 7

ARCHITECTURES AND ASSEMBLY LANGUAGES: ...................................................................... 8

NEED FOR HIGH LEVEL PROGRAMMING LANGUAGES AND COMPILERS: ................................. 9

COMPLEXITY OF PROGRAMS: ................................................................................................ 9

WHERE THE COMPILER COMES IN: ....................................................................................... 10

NEED FOR THE ASSEMBLER NOWADAYS: ............................................................................. 12

PORTABILITY: ...................................................................................................................... 12

INTERPRETED LANGUAGES: ................................................................................................. 13

1
INTRODUCTION:
Microprocessors are regarded as one of the most
important devices in our everyday machines called
computers. Before we start, we need to understand what
exactly microprocessors are and their appropriate
implementations. Microprocessor is an electronic circuit
that functions as the central processing unit (CPU) of a
computer, providing computational control.
Microprocessors are also used in other advanced
electronic systems, such as computer printers,
automobiles, and jet airliners

MICROPROCESSOR HISTORY:
Fair child semiconductors (founded in 1957) invented the first Integrated Circuit in 1959 that
marked the microprocessor history. In 1968, Gordan Moore, Robert Noyce and Andrew Grove
resigned from the Fair child semiconductors and started their own company: Integrated
Electronics (Intel). In 1971, the first microprocessor Intel 4004 was invented. A microprocessor is
also known as a central processing unit in which numbers of peripherals’ are fabricated on a
single chip. It has ALU (arithmetic and logic unit), a control unit, registers, bus systems and a clock
to perform computational tasks.

HIGH LEVEL PROGRAMMING LANGUAGES


It is rare for programmers to write programs in machine language like we did for the light bulb.
The executable files (the directly runnable machine language programs) for most applications
contain hundreds of thousands (or even millions) of machine language instructions. It would be
very hard to create something like that from scratch.
As an experiment, look through your hard disk with the file listing utility (the "Explorer" on
Microsoft systems.) Look at the size of the something.EXE files. There are about four bytes per
machine instruction on Intel processors, so divide by four to get the number of instructions.
Most programs are created using a high level programming language such as Java, C, C++, or
BASIC. With a high level language, a programmer creates a program using powerful, "big"
operations which will later be converted into many little machine operations.
For example, here is a line from a program in the language C:
int sum = 0;
This declares and initializes a variable to zero (a big operation).

2
The machine operations that correspond to this big operation set up a part of main memory to
hold a number, store the number zero there, and arrange things so other parts of the program
can use it. It might take a hundred machine operations to do all this. Obviously, it is easier for a
human programmer to ask for all these operations using C.

SOURCE PROGRAMS:
Programmers create programs by writing commands in a high level language. A high level language
program consists of lines of text that have been created with a text editor and are kept in a file on the
hard disk.
For example, here is a complete program in C;
#include <stdio.h>
main()
{
int sum = 0;
sum = 2 + 2;
printf( "%d\n", sum );
}
This program could be saved on the hard disk in a file called addup.c. Like all files, it consists of a
sequence of bytes. Since it is a text file, these bytes represent character data. You can edit the file with a
text editor and print the file on a printer. It does not contain machine instructions. If the bytes are copied
into main memory, they cannot run as a program without some extra work being done.
A source program is a text file that contains instructions written in a high level language. It can not be
executed (made to run) by a processor without some additional steps.
A source program is also called a source file, source code, or sometimes, just source.
Usually a source program is translated into a machine language program. An application program called
a translator takes a source program as input and produces a machine language program as output.
A machine language program is also called an executable program, executable file, or sometimes,
just executable.
For example, the C program addup.c could be translated into an executable program. The executable
program might be called addup.exeand can be saved on the hard disk. Now the executable version of
the program can be copied into main memory and executed.
The word compile means the same thing as translate. So one can say that a source program is compiled
into an executable program.

3
PROGRAM TRANSLATION

1. The source program is created using a text editor.


o It contains instructions in a high level language.
o It contains bytes that represent characters.
o The source program is kept on the hard disk.
o The source program can not be run by the processor.
2. A translator (compiler) program translates the source program into an executable
program.
o The source program remains unchanged; a new executable program is created.
o The executable program contains machine instructions.
o A translator translates from a specific high level language (like C) into machine
instructions for a specific processor type (like Pentium).
o The executable program is also kept on hard disk.
3. The program is run by copying machine language from the executable program on disk
into main memory. The processor directly executes these machine language instructions.

4
PROGRAM EXECUTION

Once the source program has been translated into machine code (the executable program), the
machine code can be directly executed by the processor. This is like the light bulb's processor
directly executing its machine code. The source program is only a means to create the machine
code.
A student learning programming, or a programmer developing an application, creates source
programs and translates them (with a compiler) into executable programs.

5
INTERPRETER

WHAT ARE INSTRUCTIONS AND HOW ARE THEY USED?


As I already mentioned, instructions are very simple tasks that the processor can perform, each
one having its unique code. The circuit that makes up the processor is designed in a way to
perform the given operations according to the codes it loads from the memory. The numeric code
is often called opcode.
The operations that the instructions perform are usually very simple. Only by writing a sequence
of these simple operations, can you make the processor perform a specific task. However, writing
a sequence of numeric codes is quite tedious (though that’s how programming was done long
ago), so the assembly programming language was created. It assigns opcodes (the numeric code)
a symbol – a name that sort of describes what it does.
Given the previous examples, where number 35 makes the processor move data from one
memory cell to another, we can assign this instruction name MOV, which is a short for MOVe.
Number 48, which is the instruction that adds two numbers together gets the name ADD, and
12, which performs the OR logical operation, gets the name ORL.
The programmer writes a sequence of instructions – simple operations that the processor can
perform, using these names, which are much easier to read than just numeric codes. Then he
executes a tool named assembler (but often the term “assembler” is used also for the
programming language, though technically it means the tool), which will convert these symbols
to the appropriate numeric codes that can be executed by the processor.
However, in most cases, the instruction itself isn’t sufficient. For example, if you want to add two
numbers together, you obviously need to specify them, the same goes for logical operations, or
moving data from a memory cell to another: you need to specify the address of the source and
6
the target cell. This is done by adding the so-called operands to the instruction – simply one or
more values (numbers) that will provide additional information for the instruction needed to
perform a given operation. The operands are stored in the memory too, along with the
instruction opcodes.
For example, if you want to move data from a location with address 1000 to a location 1258, you
can write:
MOV 1258, 1000
The first number being the target address and the second the source (in assembly, you usually
write the target first, and the source as the second one, it’s quite common). The assembler (the
tool that converts the source to the machine code) stores these operands too, so when the
processor first loads the instruction opcodes, which will tell it that it must move data from one
location to another. Of course, it needs to know from which location to move to what destination,
so it will load the operand values from the memory too (they can be at addresses right after the
instruction opcodes), and once it has all the necessary data, it will perform the operation.

SMALL EXAMPLE:
Let’s look at some short code and describe what it does. Please note that it's pseudocode, it's not
made for a specific architecture or language and various symbols can differ, the principle
however, remains the same.
MOV A, 2000
LOOP:
ADD A, #5
JNL A, #200, LOOP
MOV 2001, A
The first instruction will move the number from the memory cell with address 2000 to a register
A – it’s a temporary location, where the processor stores numbers. It can have many registers
like this. The second line contains something called a label: it’s not an instruction, it’s simply a
mark in the source code that we may use later (you’ll see how).
On the third line, there’s an ADD instruction, which adds two numbers together. The operands
are register A and number 5 (the # mark before tells the assembler that it’s number five, not a
number in the memory cell with address 5). And remember? We stored the value from memory
location 2000 in the A register, so whatever the value is, this instruction will add the number 5 to
it.
The following instruction is called a conditional jump: the processor will test some condition and
based on the result, it will jump or not. In this case, the condition is whether a given number is
not larger than another one (JNL = Jump (if) Not Larger). The number being compared is the
number in register A, with the number 200 (again, mark # means that it’s a direct number, not a

7
number from the memory location with address 200). In this case, the number in A is smaller
than 200 (thus not larger than 200 – condition is true), the processor will make a jump at the
instruction specified by the third operand, and this is where our label comes in: the assembler
tool (the translator) will replace “LOOP” with the memory address of the instruction right after
this mark.
So if the number is smaller, the processor will jump back to the instruction ADD and again add
value 5 to the number A (which is already larger from the previous calculation) and then get back
to the JNL instruction. If the number is still smaller than 200, it will jump back again; however, if
it is larger, then the condition won’t be true anymore, so no jump occurs and the following
instruction gets executed. This one moves value from register A to the memory cell with address
2001, basically storing the resulting number there. It’s important to add, that the memory cell
with address 2000 still contains the original value, because we created a copy of it in register A,
we didn’t modify the original.
This piece of code doesn’t really have much of a purpose; it’s simply for demonstration and also
for some hypothetical architecture. Real-world programs are composed of hundreds, thousands,
even hundreds of thousands of instructions.

ARCHITECTURES AND ASSEMBLY LANGUAGES:


I already mentioned the term architecture before: it describes features of certain processors. It
describes what simple operations the processor can perform (some may be able to perform only
a dozen of them, some hundreds of various operations), and what opcodes each instruction has.
It also specifies a lot of other things: what and how many registers (small storage places directly
in the processor itself, where the programmer can temporarily store data) it has, how it can
communicate with other chips and devices, like memory, chipset, graphics card, and other
features of its function.
This means that every processor has its own assembly language, because the instructions it has
are different. Thus, assembly language (or simply assembler, though it’s technically not correct)
is not just one language, it’s a whole set of languages. They’re all quite similar, but differ in what
instructions are there, what are the operands and some other features specific to the processor.
However the basic principle is the same (unless it’s one of my WPU experimental processors :-) )
among them, so if you understand principle of one assembler for a given architecture, learning
others will be a cinch.
So it’s important to understand: assembly language is always meant to be used with a specific
architecture. For example, most personal computers use an architecture called x86, or in the case
of 64-bit systems and applications, its extension x64, so if you wanted to program for this
architecture, you would use the x86 assembly language. Many mobile devices use an architecture
called ARM, so if you have programmed these processors in assembler, you would use the ARM

8
NEED FOR HIGH LEVEL PROGRAMMING LANGUAGES AND
COMPILERS:
There were two big pressing issues that led to the high level programming languages that you
most probably already know. First, creating complex programs requires dividing them into a lot
of simple instructions, so to achieve more complex actions, you need to write a lot of instructions:
this is both tedious and time consuming, not to mention that it’s more difficult to understand.
The second issue was already mentioned: a program written for one architecture won’t work on
another one without a complete rewrite. High level languages solve both these problems.

COMPLEXITY OF PROGRAMS:
Let’s imagine that you want to perform a more complex calculation, for example, you want to
calculate the result of A = 2 + ( 7 – 3 ) * 2. However, the processor doesn’t support anything like
that, it can only perform very simple operations. So if you want to write code in assembly, you
need to split this calculation into simple operations that the processor supports. For a
mathematic expression, this is done the same way you would do it if you were calculating the
expression manually in math class, for example: first you need to calculate the value in the
parentheses (subtract 3 from 7), then multiply the result by 2, and finally add it to number 2. The
result will be stored in register A. So the assembly code would look like this (the “;” starts a
comment - not part of the code, just a remark of what it does):
SUB #3, #7 ; Subtract 7 from 1 and store the result in register A
MUL A, #2 ; Multiply value in register A (containing the result of previous operation)
; by two and again, store the result in register A
ADD #2, A ; Add the result of previous operation (in register A) to the number 2
; and store it in the register A, so A now contains the result

MOV B, 202 ; Move the value from memory address 202 to register B
MOV A, 201 ; Move the value from memory address 201 to register A
SUB A, B ; Subtraction (@201 - @202) and store the result in A
MOV B, 203 ; Move the value from memory address 203 to register B
MUL A, B ; Multiply the value from previous calculation with number at the address 203
stored in B
MOV B, 200 ; Move the value from memory address 200 to register B
ADD A, B ; Add value in A (( @201 - @202 ) * @203) to B (@200) and store the result in A
MOV 250, A ; Store the result in the memory cell with address 250

9
WHERE THE COMPILER COMES IN:
Okay, so here’s a question: if you can split expressions and tasks into a series of simple
instructions and if you can assign memory locations for variables, why can’t it be done by a
program? And that’s exactly what the compiler does. The programming language specifies what
kind of statements you can write and how, and the compiler must support them. So you can
simply write the following code (it’s C-like code):
int a, b, c, d, e;
a = 2;
b = 7;
c = 3;
d = 2;
e = a + (b - c) * d;

When you compile this code, the compiler will analyze (parse) this code and it will find that you
want five variables. You don’t have to decide which memory cells will be assigned to these
variables: it’s all handled for you. For example, the compiler might decide that contents of the
variable named “a” will be stored in a memory cell with address 200, “b” in 201, and so on. The
compiler keeps track of these assignments, so wherever you use the given variable, it will make
sure that the proper memory address is used. In reality, the process is often a bit more complex
than this, but the principle remains the same.

MOV 200, #2 ; Move number 2 to the memory location 500, which corresponds with
variable "a"
MOV 201, #7 ;b=7
MOV 202, #3 ;c=3
MOV 203, #2 ;d=2
This is hopefully simple enough; each assignment corresponds to a processor instruction (I’ve
written them in assembly language, the compiler will of course generate the appropriate numeric
codes for each instruction – the machine code). However, when it comes to the last statement,
which assigns the result of the expression “a + (b - c) * d” to the variable “e”, it can’t be done
using a single instruction as you’ve seen before. However, all you need to do is to write this
expression and the compiler will read it and do the splitting into a series of simple instructions
itself, without you even knowing about it (until now at least :-) ). For example, it might generate
the following instructions:
MOV B, 202 ; Move the value from memory address 202 (variable "c") to register B
MOV A, 201 ; Move the value from memory address 201 (variable "b") to register A
SUB A, B ; Subtraction (b - c) and store the result in A
10
MOV B, 203 ; Move the value from memory address 203 (variable "d) to register B
MUL A, B ; Multiply the value from previous calculation with value of variable "d" stored in
B
MOV B, 200 ; Move the value from memory address 200 (variable "a") to register B
ADD A, B ; Add value in A (( b - c ) * d) to B (a) and store the result in A
MOV 250, A ; Store the result in the memory cell with address 250 (variable "e")
I think it needs no explaining that it’s much easier to simply write “e = a + (b - c) * d” instead of a series of
instructions and the same principle applies to everything. A high level programming language allows you
to express the actions to be performed in a more clear, easier, and understandable manner, and the
compiler will take care of converting this into a series of simple instructions the processor understands,
and will handle all other details for you. This is called abstraction and solves the program complexity
problem: you can write and manage much more complex programs, because you don’t have to bother
with all the details: they’re taken care of for you automatically. It might be important to mention
how some basic programming constructs are handled. For example, the “if” statement. Let’s
consider the following C code:
Hide Copy Code
if(a > 2)
b = 3;
else
{
b = 5;
c = 8;
}
a = 8;
The processor doesn’t understand what the “if” statement is, however it has a conditional jump
instruction: it will jump to another instruction if a condition is true. So this fragment will be
translated to the following assembly code:
Hide Copy Code
MOV A, 200 ; Move the value of variable "a" (address 200) to register A
LGR #2 ; If value in register A is larger than number 2, store number 1
; in the register A, if not, store number 0 in register A
JZ ELSE ; If value in A (result of the comparation) is zero,
; jump at the instruction after the "ELSE:" label,
; instead execute the following instruction
MOV 201, #3 ; Move number 3 to memory location 201 (variable "b"), b = 3
JMP END ; Skip to the "END:" label so the instructions of the else clause are not executed
ELSE:
MOV 201, #5 ; b = 5;
MOV 202, #8 ; c = 8;
11
END:
MOV 201, #8 ; a = 8

NEED FOR THE ASSEMBLER NOWADAYS:


You might be wondering: if the compiler can handle all these things for you, what’s the point of
knowing assembler today? There are several answers: first, the compiler might not always
generate optimal instructions: some actions can be done using fewer instructions in a less
standard way that the compiler doesn’t know of. This is a problem when you need to squeeze
every bit of performance; in such cases, you can write instructions for the performance critical
parts yourself, ensuring that it works exactly the way you want it to.
This might be even a bigger problem when programming for small embedded devices with limited
resources, where you can’t simply afford any overhead (more instructions that are actually
needed and suboptimal ways to solve things). Another reason is limitations of the compiler:
you’re limited only by what it supports, if you want to use some features of the processor that
the compiler can’t generate instructions for, for example, new special instructions, you’ll need to
write them yourself.
Knowledge of assembly is an absolute must if you want to analyze existing software, hack (alter
its behavior) or crack it. As you already know, program is composed of series of simple
instructions – numeric codes that represent various actions. It’s easy to disassemble an existing
program when you don’t have its source code: the numeric codes are simply replaced with their
appropriate names, resulting in an assembly language code, so if you want to analyze and modify
them, you must know assembly language.
It’s much more difficult to decompile the program – convert it back to its high level source code:
this needs extensive analysis of the instructions and their structure, and the resulting source code
will be still very far from the original: important things like names of variables, functions, and
comments are lost during compilation (not necessarily for all languages), because they’re simply
not needed by the processor: all it needs is memory address, which is just a number.

PORTABILITY:
The second major problem of assembly programming is portability: to transfer your program to
another platform with a different processor architecture, you need to rewrite it completely in
the assembly language for the target platform. Using a high level language solves this problem
quite easily. The code in the high level language is usually platform independent: it’s the compiler
that generates the appropriate instructions, not you.
So if you want your code to run on a PC with x86 architecture, you give the sources to a compiler
that generates instructions for x86. If you want to make binary (machine code) for a mobile

12
device with ARM architecture, you give the same source code to an ARM compiler and it will
generate instructions for that architecture, without you needing to do anything. This of course
requires that a compiler exists for the given architecture; if there is no compiler for a particular
architecture, then you’ll be left with assembly programming, unless you write the compiler
yourself.

INTERPRETED LANGUAGES:
So far, we only dealt with something that’s called native code: languages that create native code
result in instructions that are directly executed by a given processor. If you create a binary file
(containing these raw instructions for a given processor), it will only work on a given architecture;
if you want to use it on another, you’ll need to compile it for that architecture: generate the
appropriate machine code that the processor of a given architecture understands.

13

You might also like