Software I

Software #

…here’s where you come into the picture. In the last section on hardware we discussed how processors were designed - now we’ll dig into how programmers like you can put these processors to work!

Smart people have designed very easy ways to tell computers what to do, but here is a look at all the work that is in between your programming language and the 1s and 0s that a processor eventually reads!

Binary #

Computers think in binary. Binary is literally just 1s and 0s.

You can also think of binary as true and false or on and off.

One Instruction At A Time #

Let’s pretend when you woke up in the morning your brain thought like this:

0 - WAKE UP ROUTINE

AddressInstruction
1Open your eyes
2Sit up in bed
3Look at the clock
4Read the time (NOW)
5Remember the time you need to wake up (TARGET)
6Compare these two times
7If NOW is past TARGET, get ready for school!
8If NOW is before TARGET, go back to sleep for 10 minutes
9Restart at instruction 1

This is exactly how processors think: procedurally (that’s fancy for one thing at a time, and one action after another.)

You may think that sounds dumb, but Computer Engineers have figured out how to make processors that can process tens of billions of instructions per second.

When writing programs for processors to run, we can’t tell them directly “is the sun up?” or “how cold will it be next Tuesday?” - they have no idea about anything. They need to be given everything they need to solve a problem.

We do this by providing instructions for the processor to read and run.

…let’s take a peek at the brain that reads these instructions first!

A Simple MIPS Processor #

Depending on the design of the processor, the binary (zeroes and ones) instructions we give a processor will look a lot different. Just like people speak English and French, processors speak MIPS and ARM and X86 assembly language.

Conceptually, let’s begin from a simple processor1 we mentioned on the previous page. This guy is designed to read MIPS instructions.

Since you probably aren’t familiar with processor anatomy, I’ll point out a few important bits to you:

  • PC - Program Counter - Like the waking-up routine above, the Program Counter keeps our place in the program and can be reset to a different place, like back to 1 if we were to snooze.
  • Instruction Memory holds your program. To the right of this, you can see each instruction broken up as it is read and sent to different parts of the CPU.
  • Registers are like your short term memory. You can keep a few things here to reference quickly.
  • ALU - Arithmetic Logic Unit - Is like your deep memory. It takes quite a while to pull things from here, so usually you save whatever you want from here into a register.

Machine Code #

The point of showing you all this: When we are giving our very lowest level instructions to a computer, we are directly referencing these parts with instructions like:

  • Get memory address 89 and move it to register 3
  • Add the contents of register 2 and register 3 into register 4
  • Save register 4 into memory address 90

The computer sees these instructions like this:

  • 001000 10011010100000000000000100
  • 000010 00000000000000000100000001
  • 000000 10001100101000000000100000
  • 100011 10011010000000000000100000
  • 000100 01000000000000000000000101

How do we know which 1’s and 0’s to give to the machine?

Assembly Language #

Luckily, we don’t need to write machine code directly.

For every processor, the designer will have also designed an instruction format that lets users know how to command and control a processor.

For each instruction type, there will be a variety of functions we can tell the processor to perform.

What I show here is not a complete assembly language, but (explanation here)

assembly code:    add $s0, $s1, $s2
                      rd   rs   rt

machine code:     000000 10001 10010 10000 0000 100000
                  op     rs    rt    rd         funct 

From http://www.cs.kzoo.edu/cs230/Resources/MIPS/MachineXL/InstructionFormats.html

Low-Level Programming Languages #

Luckily, we don’t need to write assembly languages directly.

C:                a  =  b  +  c
                  rd    rs    rt

assembly code:    add $s0, $s1, $s2
                      rd   rs   rt

machine code:     000000 10001 10010 10000 0000 100000
                  op     rs    rt    rd         funct 

High-Level Programming Languages #

Luckily, we don’t need to write low-level languages directly.

(+ 1 2)

Overview #

flowchart TD
    subgraph Editor
        direction LR
        EI[Ideas] -- write --> ES[Source Code]
    end
    subgraph Compiler
        direction LR
        A[Source Code] -- compile --> B[Assembly Language]
        B -- compile --> C[Machine Instructions]
    end
    subgraph Processor
        direction LR
        D[Machine Instructions] -- execute --> E[Results!]
    end 
    Editor -- a text file --> Compiler
    Compiler -- machine instructions --> Processor 

  1. MIPS assembly language programming tutorials (link↩︎