dijous, 2 d’abril del 2009

História vertical de la programació.

Bé, això pretén ser una introducció a la programació. Els conceptes bàsics i que ningú es molesta a explicar: d'on surten les coses que hi ha avui dia i per què són així.

Turing i Von Neumann

Al principi de tot hi ha la màquina de Turing... però això és molt molt molt enrere en el temps. Això, de fet, és de la segona guerra mundial. La màquina de Turing és una màquina "teòrica" que compleix certes característiques matemàtiques i és capaç de resoldre problemes NP-Complets donats temps i memòria ilimitats.

Parres a part, el que ens interessa és que existeix un model de màquina que resol problemes matemàtics: aquest fou l'invent i contrivució de Turing. La veritat és que el que és la màquina de Turing és una cosa complicada, per això ens la saltem i passem al que és la salsa en sí: un ordinador amb una arquitectura Von Neumann.

Vaig massa a saco? M'ho sembla a mi? Estic parlant d'história, no és realment important saber tot això per saber programar, però va bé tenir una mica de cultura general, i ara ja teniu paraules per buscar a la Wikipedia, així que us deixo el trevall per a vosaltres. El que si que explicaré és l'arquitectura de Von Neumann. Simplement perquè, malgrat avui dia s'hagi evolucionat, els ordinadors continuen funcionant igual. O al menys, comportant-se igual.

Von Neumann en sério

Un ordinador amb arquitectura Von Neumann té la següent estructura:
  • Una memòria.
  • Uns dispositius d'entrada/sortida (teclat, pantalla, modem, etc.......)
  • Un processador.
L'element més important és el processador, que s'explica també ràpid. Té els següents elements:
  • Registres (llocs on guardar dades)
  • "Una" unitat de control
  • "Una" ALU (unitat aritmetico-logica)
Bé. Comencem a explicar els conceptes:
  • ALU. Una màquina de fer càlculs. Tu li fas entrar numeros per una banda i un codi dient-li què n'ha de fer amb aquests nombres i la ALU treu la operació feta per l'altra banda. Evidentment, només pot fer operacions senzilles: sumar, restar, multiplicar, -dividir-, comparar dos nombres (i dir quin és el més gran o si són iguals) i m'atreviria a dir que amb aixó n'hi ha prou.
  • Unitat de control: el cerbell de la màquina. Aquesta és la que dirigeix la màquina i controla les coses. Com ho fa? Més senzill del que ens pot semblar. Llegeix una instrucció d'un dels registres (un especial) i la executa. Què vol dir executar una instrucció? En general, hi ha poques variants:
    • Llegir una dada de la MEMÒRIA i desar-lo en un registre
    • Llegir una dada d'un registre i guardar-lo a la MEMÒRIA
    • Agafar dades de registres i fer una operació a la ALU, guardant el resultat en un registre
    • Moure dades dels dispositius d'entrada als registres
    • Moure dades dels registres als dispositius de sortida.
    Vistes les operacions bàsiques, ja no sembla gran cosa, veritat? Simplement el que es fa és "codificar" cada instrucció amb un número i quan la Unitat de Control llegeix aquest número l'executa.
Fàcil, no?

Com funciona, un trasto així?

Tu li poses a la memòria un programa. Què és un programa? Doncs un programa té 2 parts principals: Dades i Instruccions. En general, posaràs a la memòria aquestes parts en 2 zones separades, per tal de no liar-la massa. Un cop has posat el programa a la memòria, li poses "play" i la màquina comença:
1 - Li dones on de la memòria comença el programa. Aquest numeret es guarda en un registre que s'anomena PC, de Program Counter, o contador del programa.
2 - La unitat de control agafarà la instrucció que hi hagi al lloc de la memòria que li digui el PC i se la posarà al seu registre.
3 - Incrementarem el PC, per tal de que "apunti" a la seguent instrucció.
4 - La unitat de control executarà la instrucció que li digui el seu registre i tornarem al pas 2.

Molt bé. Ara tenim una màquina que executa un seguit de instruccions i acaba, probablement, deixant un resultat a la pantalla (dispositiu de sortida). Falta, però un element important. Qué passa si la feina que hem de fer és una mica més complexa que seguir passos un rere l'altre? Si hem de prendre "decisions"? Necessitem un tipus d'instrucció que no hem mencionat fins ara: la instrucció de "salt".

Aquesta instrucció és també senzilla: Simplement, hem de canviar el nombre que hi ha al PC per el que nosaltres volguem per tal que la següent instrucció que la nostra màquina executi no sigui exactament la següent en la memòria, sinó la que nosaltres volguem. A més aquest salt es pot fer condicional. Vol dir, podem comprovar 2 nombres, i si un és més gran que l'altre, saltar i si no ho és, continuem com anàvem.

I per què sapigueu tot només falta explicar la pila d'execució però... no cal. És complicat i tampoc afegeix res essencial, simplement fa certes coses una mica més senzilles i no deixa de ser una mena de salt complicat.

O sigui, ens saltem aquest troç i avancem al llenguatge ensamblador.

O passem abans per el "codi binari"?

Codi Binari 101

Tothom sap que existeix aquest "codi binari", però qué és? Doncs no és res més que una altra manera de contar. M'explicaré. Nosaltres tenim 10 nombres diferents. És per això que fem servir nombres decimals. Conceptualment ho tenim molt senzill: començem amb el 0, després el 1, 2, 3 i fins al 9. Quan no en tenim més, afegim un 1 al principi i tornem a començar, quan ens tornem a quedar sense, sumem un nombre al principi i au!

El codi binari és exactament el mateix, però amb només 2 nombres: el 0 i el 1. Així els primers nombres són: 0, 1, 10, 11, 100, 101, 110, 111, 1000, 1001, 1010, 1011, 1100, 1101, 1110, 1111 que és el 15.

Matemàticament, podem veure que cada dígit incrementa exponencialment el seu valor quan més a l'esquerra és.

En decimal, 1.234 val 1 * 10^3 + 2 * 10^2 + 3 * 10^1 + 4 * 10^0 = 1000 + 200 + 30 + 4
En binari, 1101 és 1 * 2^3 + 1 * 2^2 + 0 * 2^1 + 1*2^0 = 8+4+1 = 13

Bé, ara es veu clar que el binari no és altra cosa que contar d'una altra manera. Desmitificar és important. Lletres? Assignem lletres arbitrariament a nombres i hem acabat. L'ASCII és la base de quasi tot el que es fa servir. Wikipediejeu.

I per què binari? Simple: fer operacions en binari és relativament fàcil. En el sentit de fer circuits elèctrics que sumin i restin nombres binaris. Què vol dir, sumar i restar nombres binaris? En un ordinador actual, agafar una ristra de cables, que representen 1ns i 0s estàn encesos o apagats, i fer que una altra ristra de cables s'ensenguin o apaguin en conseqüència.

Llenguatge màquina, llenguatge ensamblador.

Què tenim? Una màquina que va agafant nombres, els interpreta (hem construit la màquina de tal manera que sapiguem quin número vol dir quina operació) i fa operacions. A més aquesta màquina és capaç de llegir nombres que li donguem (cada vegada que apretem una tecla, li estem enviant un nombre, ell ja sap quina tecla és per el nombre que llegeix) i tornar-nos nombres en conseqüència del que digui el programa.

Bé, podem escriure programes directament en els nombres. És una matada que es coneix com a llenguatge màquina. Saber quin número correspon a quina instrucció és complicat i el que és pitjor, canvia amb una facilitat esferaidora de màquina a màquina. No és practic. Per què no fem una cosa? Creem un programa que llegeixi unes certes paraules i les converteixi a llenguatge màquina. No hauria de ser molt complicat; només cal que vagi llegint caràcter a caràcter (nombre a nombre, li assignem una lletra arbitràriament a cada nombre) i quan en tingui uns quants sabrà quina paraula li estem demanant, ergo, quina instrucció volem que faci, i "escrigui" aquesta instrucció a la sortida. I que aquest programa vagi repetint el procés i... ja tenim un ensamblador!

No ens enganyem, el llenguatge més bàsic de programació és el llenguatge màquina. Però com que no li tenim respecte i el llenguatge ensamblador no és més que una traducció directa d'aquest a un idioma "comprensible", l'obviarem i direm que el llenguatge ensamblador és el més bàsic.

Aquest llenguatge ensamblador té l'avantage de ser més fàcil de trevallar-hi i més fàcil de recordar les instruccions, però continua arrossegant problemes del llenguatge màquina. Entre elles, la dependència amb la màquina. Què passa? Màquines similars tenen llenguatge ensamblador similar, i no és gaire difícil passar d'un a altre, al menys, no tant com amb llenguatge màquina.

Compiladors

Per saltar-nos el problema de haver de programar cada vegada les coses per cada màquina on les volguem fer servir vàrem inventar el què s'anomena llenguatges de 3a generació [màquina = primera, ensamblador segona]. Aquests llenguatges són una mica més complexos que l'ensamblador i tenen una sintaxi força més complicada, però en el fons són tot instruccions del mateix tipus i amb poques coses bàsiques. Aquests llenguatges (el més important, el C, però no és pas el primer que va aparéixer, ni molt menys) es passen a ensamblador normalment abans de ser passats a llenguatge màquina per uns programes anomenats compiladors. Aquests compiladors són programes certament més complexos que els ensambladors, doncs no és una traducció directa i moltes vegades canvien el codi per, tot i acavar fent el mateix, ho facin millor que com originalment es feia.

I fins aquí aquesta primera part de la história de la programació. Espero haver estat entenedor i rebre algún comentari amb opinions, preguntes, etc...

Próximament les evolucions a partir de C; paradigmes de programació (funcional, orientat a objectes, scripts, etc...)

continua en História vertical de la programació II

1 comentari:

  1. M'agrada com està explicat!!!
    ho fas de forma interessant! continua així!!! ànims!!!
    espero la segona part del culebrot!!!!!

    ResponElimina