views:

482

answers:

13

Where in a computer does the abstract (letters on the screen) meet the real (electrical current passing through circuits in memory and processors). How did that evolution happen?

I'm talking deeper than assembler here, I think. Maybe a level deeper than processor instructions? At some point commands are actually interpreted by hardware, but I don't understand where/how that happens.

I didn't go to university, so didn't take a CS course or anything. Like many, I am a hobbyist turned "pro". As a result, there are many pieces of the jigsaw I think I'm missing. I know a little C++, and understand the concept of pointers etc (though I've not used them in anger much), however I've only ever worked at a high level. I'm not sure knowing this kind've stuff will help me or not, but it's sure interesting.

A: 

Machine code, I believe, is as low-level as one can go. It is directly understood by the processor and executed without an interpreter. The processor is built with a certain set of instructions which define the machine code for a given architecture (x86, PPC, ARM, etc.).

Everything from drawing letters on the screen to calculating pi is, at its most base level, run in machine code. Drawing letters on the screen is just a matter of creating some machine code which computes letter height, color, and pixel locations and plots them on a screen using a video output device.

Eric Smith
Nope. See mxyfc's answer: microcode goes below that. Though the story gets even more complicated in modern architectures...
Pontus Gagge
+3  A: 

There is actually one more layer below machine language that I have found out recently from a friend. It's called Microcode.

See this Wikipedia article for details: http://en.wikipedia.org/wiki/Microcode

maxyfc
A: 

You're getting it wrong.

Everything the computer does, be it showing letters on the screen or doing some computation, can be viewed at different (many) levels of abstraction, from the electrical current to the manipulation of abstract concepts like money on a bank account.

That said, building the circuit for a simple microprocessor is not that hard, an ALU, some registers and some control logic. Altera has this as advanced tutorials for the Cyclone II starter board, but I can't find it on the web.

starblue
+7  A: 

A processor operates what is known as a fetch-decode-execute cycle. Machine code instructions are fairly low-level (i.e. they don't do all that much in a single instruction). For example, adding two numbers would have a sequence of instructions with semantics like:

  • Load a pointer to the address of operand 1 into register 1
  • Load the value stored at the address stored in register 1 into register 2
  • Load a pointer to the address of operand 2 into register 1
  • Load the value stored at the address in register 1 into register 3
  • Add the contents of register 2 and register 3 and store it in register 4
  • Load a pointer to the destination into register 1
  • Store the contents of register 4 in the address specified in register 1

Within the processor is a special set of fast memory known as a 'Register File', which contains the memory that the processor uses to store data that it is working on at the time. The register file has several registers, which are uniquely identified. Instructions typically work on registers, especially on RISC architectures; while this is not always the case it is a good enough abstraction for the moment.

Typically a processor has to load or store data into a register to do anything with it. Operations such as arithmetic work on registers, taking the operands from two registers and placing the result into a third (for the benefit of the peanut gallery, I have used a 6502 - lets not confuse the issue ;-). The processor has special instructions for loading or storing data from registers into the machine's main memory.

A processor has a special register called the 'program counter' that stores the address of the next operation to execute. Thus, the sequence for executing an instruction goes roughly like:

  • Fetch the instruction stored at the current address in the program counter.
  • Decode the instruction, picking apart the actual operation, what registers it uses, the 'addressing mode' (how it works out where to get or store data) and some other bits and bobs.
  • Execute the instruction.

Executing the instruction will change the values in various registers. For example, a 'load' instruction will copy a value into a register. An arithmetic or logical (And, Or, Xor) will take two values and compute a third. A jump or branch instruction will change the address at the program counter so the processor starts to fetch instructions from a different location.

The processor can have special registers. An example of such is the program counter described above. Another typical one is a condition flags register. This will have several bits with special meanings. For example it may have a flag that is set if the result of the last arithmetic operation was zero. This is useful for conditional operations. You can compare two numbers. If they are equal, the 'zero' flag is set. The processor can have a conditional instruction that is only executed if this flag is set.

In this case, you could decrement a counter in a register and if it was zero, a condition flag is set. A conditional (branch on zero) can be used for a loop where you decrement a counter and exit the loop if the result of the decrement instruction is zero. On some processors (e.g. the ARM family) all instructions are conditional, with a special 'do always' condition for non-conditional instructions.

Some examples of typical processor instructions are:

  • Increment or decrement a register
  • Load or store the contents of a register into memory. You can also have the address to load or store offset by the contents of another register. This allows you to easily loop over an array of data by incrementing the other register.
  • Add, subtract, multiply, logical operations to calculate values. These take operands from two registers and place the result in a third.
  • Jump to another location - this moves the contents of the location into the program counter and starts to fetch instructions from the new location.
  • Push or pop values onto a stack.

This stackoverflow post has an example of a small snippet of compiled C code and the assembly language output from that snippet. It should give you an example of the sort of relationship between a high-level language and the machine code output that it compiles to.

The best way to learn this is to get an assembler and try it out. This used to be much easier on older, simpler computers like 8-bit micros of the 1980s. The closest thing to this type of architecture available these days are embedded systems. You can get a development board for an embedded processor like a Microchip PIC fairly cheaply. As this type of architecture has less baggage than a modern operating system there is less i-dotting and t-crossing to use system calls. This will make it easier to bootstrap an assembly language program on this type of architecture; the simpler architecture is also easier to understand.

Another option is to get an emulator such as SPIM. This will emulate a CPU and let you assemble and run programs on it. The advantage of such an emulator is that they will also have facilities for single stepping programs (much like a debugger) and showing the contents of the register file. This may be helpful in gaining insight as to what's actually going on.

ConcernedOfTunbridgeWells
But how does the machine code get interpreted by the cpu? It's basically still characters strung together to form keyword, yes?
Neil Barnwell
No, the assembly language is compiled (by an assembler such as MASM) into a binary code called machine code. When the machine reads an instruction, it picks it apart to work out what to do with it.
ConcernedOfTunbridgeWells
A: 

Well, if you know how the processor accesses memory then you already know the answer. Memory and other hardware are accessed in (almost) the same way, depending on wether the processor uses "memory mapped IO" or "IO mapped IO". In the first case, the processor just tries to read and write to a memory address - but there are no memory there - instead it's some other hardware device, but the processor really can't tell the difference. The latter case is very similar.

On the other hand, if you have no clue on how the processor accesses the memory, you should look up what an "address bus" and a "data bus" is to get you started.

danbystrom
+1  A: 

Well, the actual point where you meet hardware depends on what you are doing, of course. But to take your (excellent) example of "displaying text":

From abstract to hardware:

  • user types letters into her word processor (wp)
  • wp software first stores the letters in memory as part of the document being edited
  • wp software then tells the user interface library it uses that it wants to display the text being edited in a window (this happens continually, of course). The UI library will be system-dependent (the Windows API on MS Windows, X Windows or QT etc. on Linux, AWT/Swing on Java etc.)
  • The UI library will pass the data through a few more abstraction layers. In particular, it will perform rasterization (convert the information "show an A" into the pixel grid that represents an A)
  • Eventually, the information will be passed to the device driver of the graphic card. This is where we meet "real" hardware :-). Normally, the graphic card exposes "video memory", i.e. memory on the card that the CPU can write to. The graphic card driver (which runs on the CPU) will write the pixels for an A to video memory.
  • The graphic card's circuits will read the video memory and convert the data there into a video signal that goes out the video connector on the card and to the monitor.
  • The monitor will display what looks hopefully like an A :-)
sleske
"wp software first stores the letters in memory", as the second step? I think you're sorley mistaken. A lot goes on between 'user types letters' and 'wp software stores letters in memory' like 'keyboard sends interupt signals to cpu'.
PintSizedCat
The first step should be "user presses key on keyboard" - a key press is going from hardware (kb) to hardware (screen/memory/disk).
Pete Kirkham
Also, why is the user femanine? seems a lot like sexism to me.
PintSizedCat
Yes, I omitted the stuff about keyboard input, as I wanted to show "one path", from memory model to monitor. But one could always write more... And if the user were masculine, it would also be sexism, wouldn't it? ;-)
sleske
A: 

This is not easy to answer in one sentence. Read a book about computer architecture, learn some assembly and I am sure you will understand how this happens.

Chrys
+2  A: 

I'd very much suggest that you read the book Code, it gives a detailed history of how the computer evolved from different systems.

It's very engaging and will explain to you how things evolved from morse code through to a simple adding machine and then on to some assembly. It should give you a picture of exactly how machine instructions are interpretted and used by the hardware of a CPU, memory, etc.

PintSizedCat
+1  A: 

This explanation may not be too academical but this is how i understand it (didn't go to university either).

The first step involves Boole's algebra that proved in the 19'th century that any mathematical operation can be expressed using a series of symbols and some associated operators. Thus the base 10 arithmetic with the common +, -, *, / operators can be expressed in using just two symbols (0, 1/ true, false) and logic operators (AND, OR etc) leading to the Boolean logic that is the mathematical foundation of digital computing.

The second step is Alan Turing's work that constructed a mathematical model of an imaginary machine that could process symbols. The naive description of a Turing machine would be any automaton that has memory (to store it's state), operates on a series of symbols that represent it's state and interprets another series of symbols that define the transition from one state to another.

The modern digital processor is an implementation of a Turing machine that uses Boole's logical algebra as the symbol and operator base (take a look at a How Stuff Works detailed explanation of Boole's logic at work). The reason for this is that the true/false logical states can be easily mapped to electrical signals (+ , -) and their associated operators can be implemented in transistor circuits that given a binary input (electrical signal) can output the result according to the boolean operators. So any modern computer is a machine that has memory to store it's state (encoded in binary electrical/magnetic form) and an array of circuits that accept electrical impulses and operators (the processor instructions) and output results accordingly at a very fast speed.

Thus every program written in any computer language is eventually translated by the compiler or runtime into a series of boolean operations for the processor to execute

AZ
+2  A: 

Lets assume that the most real is current and voltage (if you go deeper, you may find that even an electron is an abstraction). The first step of abstraction is to consider that a +5V voltage represent a bit set to '1' and a 0V voltage represents a bit set to '0'. With a switch, you can decide the value of your wire.

With a second wire and a second switch, you get two binary values. The most interesting to do with them is to combine their binary values with operations such AND, OR and NOT. Two concepts are involved here: transistor for the real and logic for the abstraction. With that, you can perform addition, substraction and many other operations on your two binary inputs. You can add more wires to represent values other than '0' and '1'. Going this way, you obtain an ALU.

Now it's time to include time. If you want several results from your ALU, you have to provide input data one at a time, thus needing a clock and a control unit for sequencing operations. You also need memory for storing input values and results, and input and output devices for commanding and observing. Going this way, you obtain a Von Neuman Architecture, which is the basis of almost all computer architectures.

Next abstraction level is when you decide, with appropriate electronics, that this particular bit in memory will stimulate that particular pixel of your LCD display.

mouviciel
A: 

On the road to Changtse.

Pete Kirkham
+1  A: 

You might find Charles Petzold's Code an interesting read:
http://www.amazon.co.uk/Code-Language-DV-Undefined-Charles-Petzold/dp/0735611319

Damian Powell