Native Binary
Computers operate in binary and can only process binary, so all instructions given to them must be in binary.
A typical binary instruction might look like:
Hexadecimal
Unsurprisingly human beings find this incredibly difficult to understand, so in order to read the binary system better, programmers use hexadecimal editors to view binary data.
The above binary data looks like the following in hex:
This is slightly more readable for humans, but still not much use.
Hexadecimal converters
If we were to run the file through a hex to ascii convertor, we might get a little more information about what the file is, but not much!
We can start to see that there is a string “Hello World” and it lives in a helloworld.py file, but there no other readable information.
Why?
Because the rest of the information is a native instruction to the computer (written in a format that only that build of computer can process. The instruction in this instance, simply tells the computer to output “Hello World” to the standard output, which happens to be the monitor.
Whilst computers can only process machine code, we need to be able to give instructions to a computer in a format that both:
- Humans can read
- The machine can process
For this we use assembly language – halfway between machine code and human code.
Every machine is built to a certain type of architecture (Celeron, Pentium, Core I-5, etc) and so every machine architecture has it’s own assembly language.
Why do we need high level languages?
You might now be thinking “Why don’t we all program in assembly language?”. It would save having to add another layer on top of assembly language, after all!
The problem is that assembly language is specific to that particular architecture, which would mean that any program you write would only work on that specific type of machine!
In order to get around this we have another layer on top – high level languages’. These languages are usually not architecture specific and so if you write a program it can be used on many different types of machine architecture.
These are the programming languages that we as coders use!
Abstraction
High level languages use a number of different abstractions. Examples of extractions include:
- Lists
- Functions
- Classes
Abstractions allow humans to write code the resembles a normal human thought process and so improves:
- Coding speed
- Code reusibility
- Code readability
Portability / Platform independence
Languages such as Python and Java can be used across multiple architectures and operating systems.
Modular implementation
High level languages allow the coder to import / add modules, which improves coding speed and allows coders to use features that otherwise they would not be able to use.
Compilers
As mentioned previously:
- Assembly languages are specific to a particular architecture.
- High level programming languages are designed to work on multiple architectures.
Therefore if programs written in a high level language are to be executed on a computer, they must first be translated in to the assembly language specific to that computer. This is the job of the compiler.
Assembler
Assemblers convert assembly language code in byte code ( binary)
Interpreters
Interpreters convert high level language to Byte code at run time.
Advantages of interpreted languages
Disadvantages of interpreted languages
Less efficient at execution time, meaning less useful for :
3D games
Complex
Why do we need IDEs?
When computers were first released, most programmers simple typed their code using simple text editors, such as notepad. These text editors can still be used to edit code, but editors designed specifically for coding have a number of useful features that help speed up and improve your code. These editors are known as IDEs.
Click below to explore the key features of IDEs.
Error checking / highlighting tools
Syntax highlighting
Syntax Highlighting changes the colour of components of code, depending on their function. This makes code more readable and makes it easier to spot errors in the code.
Run-time environments
Run time environments allow the coder to run small sections of code line by line. This is extremely useful for:
- Trying out new modules and code you haven’t used before. You get to see the results of the code live.
- Debugging code – you can print out variables line by line to help find out where errors are happening. This is especially useful for finding logical errors.
Code suggestion and auto-completion
Code suggestion is useful if you can’t remember exactly what a function is called. It also reduces coding errors when typing in variable names, as it displays variables that have been created.
Code tidying is useful if you are updating or maintain large code files. It allows the coder to hide sections of code, making it easier to navigate around the file.
Boiler plate auto-creation
Some languages and packages require a certain amount of repetitive code to be typed whenever a new file is created. IDEs can often create this boiler plate on behalf of the coder, speeding up development time and reducing errors.
Challenge 1
Create a python file and create a function inside of the file that asks the user for their name and says ‘hello name‘ back to them. Save and run thee python file.
What type of execution did python use – compiled or interpreted?
Challenge 2
In the bash console compile your Python file using the following command:
python -m py_compile myfile.py
Have a look in the folder and see if you can see your file!
ls
Run your code in the interpreter using:
python3 myfile.pyc
What type of execution did python use this time – compiled or interpreted?
Challenge 3
Download the following hex editor:
Download your compiled file ( the pyc version) to your computer and open in it viewer.
Locate the – Hexadecimal code, and the plain text. Can you recognise any bits?
Challenge 4
Open a bash console on PythonAnywhere in the same folder as your helloworld.pyc file.
load up Python 3 using the python3 command.
Decompile the helloworld.py file by using the following commands:
import dis, helloworld
dis.dis(helloworld)