Al octavo bit

May 22, 2008

Steve Ballmer, a huevo!

Filed under: kiddies — kb @ 12:36 am

Acabo de ver un post sobre una conferencia de Steve Ballmer, uno de las “manos” de Microsoft desde sus inicios, atacado por una persona que asistia al lugar: a huevasos!!!

La entrada en youtube, francamente una locura pero si que es gracioso.

http://www.youtube.com/watch?v=tbUdjZASlWU

May 16, 2008

Aprende a programar

Filed under: kiddies — kb @ 12:04 pm

Una traduccion de la reflexion de cuanto tiempo lleva aprender:

http://loro.sourceforge.net/notes/21-dias.html

Mas informacion sobre el autor de este escrito en:

http://www.complang.tuwien.ac.at/anton/

April 16, 2008

Sobre la importancia de crear herramientas para crear herramientas:

Filed under: kiddies — kb @ 9:17 pm

>http://www.bestdiskrecovery.com/ngasm/Indian_Assembler.html

Investigando sobre construccion de ensambladores encontre una pagina sobre un ensamblador programado en la India, realmente me identifico con sus ideas y modo de pensar; sobre la importancia de conocer como crear herramientas para crear otras herraminetas.Al final lo importante es conocer como funcionan las cosas realmente, en computo existen tantas y tantas capas de abstraccion que es dificil ( tambien frustrante) no llegar a conocer realmente como funcionan las cosas para saber verdaderamente “la magia”.Saludos magos!

Ensamblador NASM por dentro

Filed under: systems programming — Tags: — kb @ 12:18 pm

Hace algun tiempo consegui 2 libros sobre “systems programming” :

  • Software de sistemas: Introduccion a la programacion de sistemas, por Leland L. Beck, Editorial Addison Wesley, ISBN: 0-201-64402-9
  • Systems Programmin, por John J. Donovan. Editorial MCGRAW HILL ISBN- 0-07-085175-1

Esta area una de mis pasiones sin duda, aunque nunca me habia dado cuenta, ya que estan grande que no sabia como etiquetarla. En fin al grano.

Hay muy pocar informacion sobre como programar un ensamblador, hasta ahora estos 2 libros nos dan una idea y teoria sobre como podemos empezar, aunque uno se enfoca en un ensamblador para arquitectura mainframe ( ibm 360) y el otro en un cpu imaginario, la verdad es que son ejemplos un poco viejitos y no dan algunos “trucos” que podemos hacer, para esto estudiamos un poco en ensamblador NASM:

En el codigo del nasm existen varios scripts en perl y algunos archivos .dat que son procesados por los anteriores para crear algunos archivos de salida en lenguaje C ( la mayoria son declaracion de vectores y estructuras)

El esquema que tienen realmente es ingenioso!!!

Primero que nada necesitamos una “base de datos” donde podamos tener relacionada la informacion sobre los codigos de operacion (opcodes) de TODAS las instrucciones del procesador.

—————————————-

~/src/nasm-0.98.38$ more insns.dat

; For a detailed description of the code string (third field), please
; see the comment at the top of assemble.c. For a detailed description
; of the flags (fourth field), please see insns.h.
;
AAA void \1\x37 8086
AAD void \2\xD5\x0A 8086
AAD imm \1\xD5\24 8086,SB
AAM void \2\xD4\x0A 8086
AAM imm \1\xD4\24 8086,SB

……

……

======================================

En el archivo insns.dat del nasm ( version 0.98.38) tenemos la “informacion” sobre cada instruccion, cuantos parametros ocupa, cual es el “size” de los parametros

En el archivo insns.h encontramos una estructura muy importante:

struct itemplate {
int opcode; /* the token, passed from “parser.c” */
int operands; /* number of operands */
long opd[3]; /* bit flags for operand types */
const char *code; /* the code it assembles to */
unsigned long flags; /* some flags */
};

El programa insns.pl procesa el insns.dat y genera varios archivos llenando varios vectores de estructuras las cuales seran utilizadas por la funcion de generacion de codigo del propio NASM.

~/src/nasm-0.98.38$ ls *.pl
insns.pl

~/src/nasm-0.98.38$ more insnsd.c
/* This file auto-generated from insns.dat by insns.pl - don’t edit it */

#include “nasm.h”
#include “insns.h”

Por cada instruccion se genero un valor entero por medio de un enum (archivo insnsi.h)

static struct itemplate instrux[] = {
{I_AAA, 0, {0,0,0}, “\1\x37″, IF_8086}, //AAA tiene cero parametros,su valor es 0×37

“\1 valor hex= 0×37

{I_AAD, 0, {0,0,0}, “\2\xD5\x0A”, IF_8086},
{I_AAD, 1, {IMMEDIATE,0,0}, “\1\xD5\24″, IF_8086|IF_SB},
{I_AAM, 0, {0,0,0}, “\2\xD4\x0A”, IF_8086},
{I_AAM, 1, {IMMEDIATE,0,0}, “\1\xD4\24″, IF_8086|IF_SB},
{I_AAS, 0, {0,0,0}, “\1\x3F”, IF_8086},
{I_ADC, 2, {MEMORY,REG8,0}, “\300\1\x10\101″, IF_8086|IF_SM},
{I_ADC, 2, {REG8,REG8,0}, “\1\x10\101″, IF_8086},

Ademas se genera un archivo donde tenemos una estructura por cada instruccion de modo que especificamos cuantas “formas” tiene una instruccion.

/* This file auto-generated from insns.dat by insns.pl - don’t edit it */

#include “nasm.h”
#include “insns.h”

AAA tiene solo una forma

static struct itemplate instrux_AAA[] = {
{I_AAA, 0, {0,0,0}, “\1\x37″, IF_8086},
ITEMPLATE_END
};

AAD tiene 2 formas
static struct itemplate instrux_AAD[] = {
{I_AAD, 0, {0,0,0}, “\2\xD5\x0A”, IF_8086},
{I_AAD, 1, {IMMEDIATE,0,0}, “\1\xD5\24″, IF_8086|IF_SB},
ITEMPLATE_END
};
AAM tiene 2 formas
static struct itemplate instrux_AAM[] = {
{I_AAM, 0, {0,0,0}, “\2\xD4\x0A”, IF_8086},
{I_AAM, 1, {IMMEDIATE,0,0}, “\1\xD4\24″, IF_8086|IF_SB},
ITEMPLATE_END
};

El elemento ITEMPLATE_END es esta definido para ser una marca de fin, de modo que posteriormente la funcion que genera el codigo pueda, en base al codigo de operacion, el tipo de parametros y la posicion de cada uno seleccionar una de las entradas en el vector instrux_AAA ( en el ejemplo para AAA).

De la forma anterior unicamente se necesita programar la logica para “leer” lo que indica la entructura instrux. Por lo que se puede ver, el proposito de cada campo en la estructura es la siguiente:

struct itemplate {
int opcode; /* cada instruccion tiene definido un posible token que el parser reconocera

int operands; /* indica el numero de operadores */
long opd[3]; /* bit flags for operand types */
const char *code; /* el numero hexadecimal una vez ensamblado*/
unsigned long flags; /* banderas, posiblemente para indicar en que modo del procesador es valido*/
};

Asi, estas estructuras forman parte basica de NASM, ya en ellas se puede descargar la logica/complejidad para especificar que numeros hexadecimales( y por tanto binarios) corresponden a cada instruccion en ensamblador asi como cuantas formas posibles tiene cada una.

Pf, veremos si podemos especificar algo como esto para el jmmix assembler :)

April 10, 2008

JMMIX

Filed under: jmmix — Tags: , , — kb @ 2:31 am

I began to write my own version of Knuths’ MMIX, if DEK had time to design MMIX at least i can write my own emulator where to code his programs.

First i put the full opcode list at http://kbradero.neuroaio.biz/src/jmmix/tab_mmix.l and wrote a few scripts http://kbradero.neuroaio.biz/src/jmmix/*.sh to write all MMIX opcodes.

http://kbradero.neuroaio.biz/src/jmmix/opcode.h /*opcodes are enum values */

Here you can compare opcode.h with the list values : http://www-cs-faculty.stanford.edu/~knuth/mmop.html

April 9, 2008

MMIX y el arte de programar computadoras de D. E. Knuth

Filed under: kiddies — kb @ 6:46 pm

Compre los volumenes 1-3  de la serie del mitico Don Knuth “The art of computer programming”, tengo  una copia viejita del volumen 1 sin embargo me fue imperdonable no tener el resto de los volumenes, creo que los podre leer completos   en un par de  ciclos solares.

Por ahora  estoy tratando de implementar un “emulador”  MMIX, imagino que debe haber alguno ya, sin embargo DEK ha pasado una vida escribiendo esa serie de libros y merecen el respeto suficiente como para escribir mi propio emulador donde probar y resolver los problemas de sus libros.

Unicamente me resta quejarme de lo costoso del libro “MMIXWARE:  A Risc computer for the third millenium”  un unico ejemplar cuesta  casi lo mismo que los vol. 1-3 del TAOP.

March 16, 2008

Retrocomputing# echo > program.exe ?

Filed under: kiddies — kb @ 10:48 pm

Para empezar el blog no estaria mal hacerlo con el loader que programe en la semana. Desde el compienzo de la humanidad ( por lo menos en lo que se refiere a la computacion ) todo se programaba directamente en codigo maquina ( ojo, no ensamblador) es decir directamente en binario o bueno lo que esa casi lo mismo en hexadecimal.

Pues bien con el pasar de los tiempos la comptuacion ha avanzado y en las clases ya no se ense;an esas cosas, algunos piensan que la computacion es algo que conforme pasa el tiempo deben avanzar y que es un desperdicio investigar lo que se usaba antes, esto para mi es un error.

La computacion al igual que las matematicas se basa en reglas fundamentales que deben cononcerse, sin embargo ya no es posible preguntar a nadie como se programa directamente en codigo maquina, aunque todo mundo lo utiliza pues es donde realmente ocurren las cosas.

Muchos estudiantes e incluso profesores de informatica en su vida han habierto un programa ejecutable compilado para intentar saber cual es su estructura, limitandose a decir “es simplemente codigo maquina, lo que entiende el ordenador”

Debido a lo anterior programe un programa, este lee un archivo y sea lo que fuere su contenido lo guarda en memoria para luego ejecutar esos bytes guardados en memoria.

Veamos un programa muy sencillo, es tan solo una funcion la cual simplemente retorna el valor en hexadecimal 0xbf ( un byte pues son 2 numeros hexadecimales),

Lo compilamos con gcc -c y luego desensamblamos el archivo objeto usando objdump -d


kb@cobalto:~/src/loader/load$ cat retorna.c
unsigned char retorna(){
return 0xbf ;
}
kb@cobalto:~/src/loader/load$ objdump -d retorna.o

retorna.o: file format elf32-i386

Disassembly of section .text:

00000000 :
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: b8 bf 00 00 00 mov $0xbf,%eax
8: 5d pop %ebp
9: c3 ret
kb@cobalto:~/src/loader/load$

kb@cobalto:~/src/loader/load$ wc -c retorna.o
701 retorna.o (<– cuantos caracteres tiene el archivo recuerda que 1 caracter=1 byte)

Las 2 primeras instrucciones guardan el estado de los registros en la pila y luego inicializan la misma pila, luego dejan el valor 0xbf en el regostro acomulador en la arquectura intel de 32 bits : registor eax ( reax en x86_64), los 2 ultimos instrucciones causan el restaurar el valor de los registros que previamente se habian guardado en la pila para despues retornar a la funcion o programa que llamo a la funcion,

Pongamos atencion en la segunda columna sacado con el objdump -d; la segunda columna muestra los codigos hexadecimales tambien llamados opcodes o codigos de operacion que tienen asignadas las instrucciones en ensamblador del lado derecho ( tercera columna) es decir estos numeros que por cierto estan en hexadecimal son los numeros que realmente entiende el microprocesador de la computadora!.

Nuestro objetivo sera escribir directamente en un archivo aparte los opcodes correspondientes a la funcion que escribimos, de forma que ese archivo unicamente contenga esa informacion a diferencia del archivo que genera el compilador que contiene mucha informacion aparte del propio codigo que traducio, como seria el caso de la version de compilador, librerias utilizadas, etc, es por ello que el archivo retorna.o tiene 701 bytes!

Ahora veamos utilzaremos un editor hexadecimal como el hexedit para escribir los opcodes en un archivo, una ves que los escribamos podemos verlo con un visor como el hexdump:

~/src/loader/load$ hexdump retorna.bin
0000000 4855 e589 bfb8 0000 c900 90c3 9090 9090
0000010
kb@cobalto:~/s

Cuando el hexedit nos muestra el archivo, lo presenta exactamente en el orden en que estara antesde ejecutarse, es decir cuando lo copiemos en memoria, sin embargo el hexdump nos lo muestra como se organiza en disco, es decir la baja de cada 2 bytes se guarda primero y luego la parte alta, es decir

lo que en memoria seria 55 89, el hexdump te lo muestra como 89 55 , es decir cuando se copia a memoria se “jala” primero punta de la izquieda de modo que la punta derecha ( el 55) queda abajo en los bytes con menor direccion o lo que es lo mismo al principio.

Ahora, tecnicamente lo que hace el loader es copiar todo el archivo a un vector ( creado con malloc) y luego por medio de un apuntador a funcion salta a ese vector donde de hecho ya hay codigo ejecutable copiado del archivo.

Esto me ayuda en la prueba inmedianta y sin tanto rodeo de la programacion directamente en hexadecimal, claro con el proposito de probar un ensamblador que estoy programando, aunque claro ese sera objeto de otra entrada en este blog.

Este loader es una prueba de concepto, antes de ejecutar el codigo, lo muestra, luego salta a ejecutarlo para despues comparar lo que retorna la funcion en codigo maquina ( contenido de retorna.bin), al final escribe ok o nok si una variable es igual al numero hexadecimal bf o 0xbf

kb@cobalto:~/src/loader/load$ ./loader retorna.bin
Opcodes to exec:
55  48  89  e5  b8  bf  0  0  0  c9  c3  90  90  90  90  90
End opcodes
direccion de exec_code =0×804a008
direccion de proc = 0×804a008
ok
eax =salida = bf
kb@cobalto:~/src/loader/load$

El compilador por defecto realiza la comunicacion entre las funciones y las variables asignadas mediante el registor eax.

Hay que revizar el codigo del loader para darse cuenta que no hay ninguna linea de load.c en que se asigne el valor 0xbf  a la variable salida.

Yo recomiendo compilar  load.c  asi : gcc  load.c -g -o loader  y luego utilzar el debugger gdb para hacer una prueba paso a paso ( step instruccion)

Powered by WordPress