8 minuto(s) de lectura

Empiezo hilo explicando como guarda el pc la info :).

Lo primero que tienes que entender es que todo está basado en el funcionamiento del famoso transistor. ¿Qué es? Pues se podría hacer un hilo solo para este y te quedarías corto pero voy a explicar solo lo que nos interesa. 👇

1 / 38

Es un componente electrónico que deja pasar más corriente o menos, entre dos zonas, según la corriente que "inyectemos" en una tercera (hay mucha mierda de química y física por detrás interesante :O ). Os pongo un gif con su representación y os lo explico abajo.

Funcionamiento transistor 2 / 38

Bueno veréis esas 3 "zonas" como "colector", "base" y "emisor". Básicamente si recibe corriente por la base deja que fluya corriente desde el colector al emisor (dirección de la flechita). ¿Parece estúpido verdad? ¿Qué ganamos con esto? ¿Por qué no meter esa corriente a mano?

3 / 38

Pues una característica que tiene es que se puede ajustar para que solo funcione en 2 estados: corte o saturación (es decir, o no pasa nada o pasa todo) y a la entrada se le pueden meter componentes que añaden retrasos de tiempo o cambian periódicamente. Por lo que le da vidilla

4 / 38

Como seres humanos necesitamos representar ese todo o nada sobre el papel, lo escribimos como 0 o 1 y ¡Boom! lógica digital. Ahí tenemos el motivo de porque todo está en binario, no tenemos otra forma de guardar valores en estos componentes y poder recuperarlos.

5 / 38

Ahora tenemos una forma de guardar 2 valores distintos, ¿Pero para que nos sirve eso? Recuerda que nuestros números solo tienen 10 valores distintos 0-9 (sistema decimal), así que muy distinto no es, hacemos igual, dar importancia según la posición. :D

6 / 38

Ahora se vienen las mates, voy a poneros este ejemplo. Tenemos un número con varios dígitos y según la posición que ocupen tendrán un valor u otro.

Descomposición de entero en binario 7 / 38

No voy a explicar como pasar de un sistema a otro en profundidad, es básicamente ir dividiendo entre 2 y guardando los restos hasta que el último cociente sea 0 o 1, un coñazo. Ya tenemos números en nuestros transistores, ahora esta todo rodado ¿verdad? :D

8 / 38

Mas o menos, pero guardar dígito a dígito es un rollo, mejor agruparlos, además habrá que entenderse con el vecino. Las máquinas tienen que trabajar con un número fijo de bits, sus componentes no son infinitos, aquí es donde llega nuestro amigo el nipple (agrupaciones de 4 bits).

9 / 38

¿Pensabas que iba a decir byte verdad? Paciencia. Al agruparse 4 bits se pueden representar 16 valores distintos, desde 0000 hasta 1111 (combinatoria yay!), ahí es donde se inventó el sistema de representación "hexadecimal" cuyos valores van desde 0 a 9 y siguen de A a F.

10 / 38

Ahora toca el byte, el byte son 2 nibbles (8 bits agrupados). ¿Por qué un byte? Pues resulta que los primeros procesadores de intel trabajaban con 8 bits simultáneos, no hay una lógica. ¿Por qué no representar cada valor del byte? Porque un byte puede tener 256 valores distintos.

11 / 38

Y luego sigo que me toca hacer un rato de práctica, esto va a ser tremenda turra... Tengo que explicar como se guardan números enteros, negativos, decimales, texto, ficheros... F.

12 / 38

¿Qué significa que trabajaba con 8 bits? Pues que el procesador hace cálculos matemáticos con 8 bits simultáneos (parecen pocos verdad, el número más grande es 255), si necesitan más solo tienen que extender al siguiente byte (por así decirlo).

13 / 38

La memoria del ordenador (ram o disco) guarda la info en bytes. Habrás oído eso de los 32 o 64 bits, es porque los procesadores modernos hacen operaciones con esa cantidad (4 u 8 bytes, a esto se le llama "palabra").

¿Vale, ahora que pasa con los números negativos? 👇

14 / 38

La primera opción es usar el bit más a la izquierda y ponerlo a 0 si es positivo o a 1 si es negativo (pues no xD). Estamos perdiendo bastante capacidad con esto, lo que se hace es el famoso "complemento a 2", es cambiar todos los bits a de 0 a 1 o de 1 a 0 y sumarle 1 a todo.

15 / 38

¿Por qué? Bueno, puedes buscar información, pero básicamente es una operación que permite guardar números positivos y negativos fácilmente sin perder rango. Una demostración de esto en C, podemos ver que se usan 32 bits para los nº, los "enteros" en C usan este tamaño de palabra.

Demostración en C número entero negativo 16 / 38

Bueno, no es preciso entender el código, sólo ver el resultado de abajo. Con esto ya quedaría explicado el tema de enteros, ahora vendría explicar los números decimales (o de "coma flotante" que es como se conoce en informática :D). Para ello se usa un estándar que se lama IEE754

17 / 38

Así es un número representado de esta forma, aquí si se guarda el bit de signo :). Y es una movida, no es difícil de entender pero tiene más chicha. Aquí tenéis un enlace para jugar con la explicación: https://h-schmidt.net/FloatConverter

Diagrama de bloques IEEE 754 18 / 38

Lo resumiré en que el exponente son potencias del estilo 2^n-127 y en la mantisa 2^1/(pos*2) si no me equivoco, pero vamos, es un poco lío. Existen números flotantes de precisión simple (32 bits) o precisión doble (64 bits). En programación se suelen conocer como float y double.

19 / 38

Después de tanto lío de matemáticas de las que habrás pasado llega la hora del texto, te presento ASCII. Es una codificación que se creo para asignar números a caracteres y se usaban 7 bits en total. Con esto puedes obtener 128 caracteres diferentes.

Tabla de valores ASCII 20 / 38

¿Por qué 7 bits y no 8 que son un byte? Bueno, realmente eso vino después pero sí, se han sacado otras que lo amplían: https://es.wikipedia.org/wiki/Codificaci%C3%B3n_de_caracteres.

Como introducción a los ficheros, el más simple que existe se llama fichero de texto plano y no es más que un conjunto de bytes ASCII

21 / 38

En linux tenemos un comando que sirve para mostrar los bytes en hexadecimal de cualquier fichero (xxd), aquí os pongo un ejemplo del contenido de un fichero de texto plano. Podéis ver que cada 2 dígitos hexadecimales son una letra, el valor que podéis comparar en la tabla ASCII.

Ejecución del comando xxd sobre un fichero de texto plano 22 / 38

Bueno, ¿significa eso que todos los ficheros están formados por carácteres en ASCII? Pues no, existen ficheros que tienen valores binarios puro en formatos muy distintos, hay un comando en linux para decirte de que tipo de fichero se trata (file), y es bastante útil.

23 / 38

En windows según la extensión se asocia a un tipo u otro, a linux la extensión le da igual, mirad dos ejemplos, el de un fichero de texto normal y una imagen quitándole la extensión para ver qué pasa:

Comando file sobre texto plano Comando file sobre fichero sin extensión reconociendo el formato 24 / 38

¿Cómo lo sabe? Pues porque los ficheros suelen tener una una cosa llamada "número mágico", es un valor de 2-4 bytes que se pone al principio de cada fichero, que identifica de forma única el tipo de fichero, ¡a veces incluso son carácteres legibles! Os lo demuestro:

mostrando magic number de fichero con xxd 25 / 38

Seguro que leéis algo familiar 😏. ¿Y como es capaz de representarse con todo eso una imagen?, pues cada tipo de fichero se tiene que tratar de una forma, existen desde las estructuras más simples a las más complejas. Aquí hay diagramas muy chulos :D: https://github.com/corkami/pics/tree/master/binary

26 / 38

¿Queréis que lo demuestre? Pues mirad, existe otro comando en linux para editar binarios puros "hexedit", vamos a quitarle el número mágico a ver qué pasa. Incapaz de decir otra cosa que no sea "data" 😎

Alterando el magic number de un fichero con hexedit Resultado de ejecutar file sobre fichero png con el magic number alterado 27 / 38

De hecho, técnicas como esta de borrar el número mágico hay gente que las hace para borrar el encabezado de particiones de disco cifradas y que la policía no sepa que tipo de cifrado están usando, pero eso es tema aparte 😇.

28 / 38

Por cierto, los ficheros en texto plano son el tipo de fichero más simple que existe porque ni siquiera tienen número mágico, si has vuelto a atrás para comprobarlo no te asustes, es normal. Con esto no me refiero a los "word", esos si tienen estructura compleja.

29 / 38

En fin, supongo que llega la hora de hablar de ejecutables, en linux se llaman ELF y tienen número mágico también. Aprovecho para presentaros otro comando útil de linux "strings", te saca todas las frases legibles de un fichero independientemente del formato.

Introducción a fichero ELF Comando strings sobre fichero elf 30 / 38

Vale, ¿y cómo es una máquina capaz de ejecutar un programa? Lo intentaré simplificar pero realmente la estructura de un ejecutable es bastante compleja, me centraré en las instrucciones, independientemente del lenguaje de programación, necesitas que el pc entienda lo que le digas

31 / 38

Para eso tienes que "transformar" tu lenguaje en el suyo a través de un proceso que se llama compilación y el programa que lo hace compilador, no es más que un traductor a grandes rasgos. El número de operaciones que entiende una máquina es bastante limitado.

32 / 38

Del ejemplo anterior podemos ver el código en C y el código despues de compilar. Un churro inmenso de bytes incapaces de leer por una persona, el compilador coge tu código (independiente de la máquina que tengas) y lo convierte para que lo reconozca tu máquina.

Código fuente básico en C Comando xxd sobre fichero compilado ELF 33 / 38

Las operaciones que puede ejecutar un procesador se representan mediante bytes puros y se llaman opcodes, el lenguaje más cercano a estos se llama "ensamblador" y cada tipo de máquina tiene su propio lenguaje ensamblador. Y casi cada instrucción de este tiene un opcode asociado.

34 / 38

Eso quiere decir que entre otras muchas cosas un ejecutable tiene las instrucciones (muy ligadas a ensamblador) dentro de este fichero, se puede hacer una operación inversa y convertir a ensamblador, a esto se le llama desensamblado y es útil para realizar ingeniería inversa.

35 / 38

Es decir, cuando queremos ver el funcionamiento de un programa sin tener acceso al código fuente, podemos intentar ver su código empaquetado. Aquí muestro un desensamblado del código anterior una vez compilado (con el programa radare2):

decompilado de función main con radare 36 / 38

Y creo que lo dejaré ahí, podría extenderme más pero pff, es demasiada info. Cada 2 tuits se podrían ramificar en otro hilo la verdad, no se yo si se pillarán las cosas pero bueno. Aquí lo dejo hasta que me apetezca hacer otro hilillo. ¡Adiós! 🙃

37 / 38

Estaría mejor un video jugando con la terminal :)

38 / 38