viernes, febrero 15, 2008

Ensamblador empotrado en código C

Por supuesto ustedes saben que se puede pinchar código en ensamblador (con la sintaxis de AT&T) directamente en los fuentes de C y luego compilarlo con GCC.

Si bien esto es muy útil sólo cuando realmente se quiere jugar a nivel profundillo en las cosas, aprender cómo funciona es bastante complicado. Para empezar hace falta tener conocimiento deCnte (jas jas jos jos) de C, por supuesto hace falta saber ensamblador y depende de para que queramos pinchar código totalmente no portable necesitaremos un nivel intermedio o avanzadillo xDD, me explico.

Si queremos simplemente optimizar rutinas escribiendo instrucciones concretas de procesadores concretos sólo necesitamos conocer lo básico, aunque sinceramente la parte de optimización se la dejaría al propio GCC y le metería el flag --march= (o algo así, man gcc).

La parte que necesita saber ensamblador más avanzadillo es cuando queremos jugar de verdad... o en nuestro caso empezar a jugar. Por ejemplo, ¿conocéis la instrucciones sidt y lidt? Para los que la conozcan nada que añadir... para los que no la conocéis... bueno, digamos que tendréis que aprender cosas sobre la arquitectura IA32, aaaahhhh tanto que creemos que sabemos y realmente no sabemos nada. Baste decirles que en el procesador no existen sólo los registros EAX, EBX... sino otros de propósitos específicos que sólo son accesibles en modo protegido o sea, básicamente por el SO... El registro IDT (o IDTR) es uno de ellos y lo que contiene es el puntero a la base de la IDT (Interrupt Descriptor Table) y dicho esto ya podéis ir imaginando lo que tiene, contiene los punteros a los manejadores de interrupciones. Por poner un ejemplo rápido, Linux realiza las llamadas al sistema (syscalls) con la instrucción int 0x80, pues en la posición 0x80 de esa tabla esta el puntero a la rutina que maneja las llamadas al sistema (llamada syscall_call). Se que es lioso pero chico, nadie dijo que aprender cómo funcionan las cosas fuera un camino de rosas (sin haberlo intentado me ha salido un pareado). A lo que ibamos, las instrucciones sidt y lidt lo que hacen es leer del registro (sidt) o escribir en el registro (lidt). La inicialización de los SOs en general escriben en este registro... así que ojito con estas cosas. Bueno, pues con esto queda explicado a que me refiero con "ensamblador avanzadillo", no hay que saberse el repertorio completo y que hace cada una (putas arquitecturas CISC), pero conocer mov, add y mult no es suficiente para disfrutar del bajo nivel :P.

Después de este desvarío momentaneo que me entró voy al meollo de esta entrada. Aprender a pinchar código en ensamblador en C siempre me ha resultado un coñazo, pero últimamente me veo en la necesidad (y ganas) de aprenderlo así que me puse a buscar un poco más decentemente que las otras veces y encontré un manual de un español al que le ocurrió lo mismo en su momento. Empecemos ya a llamar a las cosas por su nombre "Assembly in line" GCC tiene un manual, que no he encontrado, absolutamente completo de ello (y probablemente complejo) así que para empezar recomiendo el manual del hombre este. Desde aquí quiero agradecerle profundamente su trabajo.

Pues eso. Que si queréis aprender a pinchar ensamblador en C esto les servirá, pero primero aprendan algo de arquitectura porque para escribir en ensamblador ya pueden hacerlo directamente sobre un archivo .S, lo interesante aquí es usar "Extended assembly in line" que es lo que nos permite mezclarlo con C.

Happy Hacking!

No hay comentarios: