Subsecciones
El lenguaje de ensamblado en Linux
Porque claro, en otros sistemas operativos disponíamos de varios
ensambladores, todos más o menos compatibles entre sí o cuando menos con
sintaxis parecidas; en otros sistemas simplemente se dificulta la
programación en ensamble hasta límites insospechados para evitar que se
haga, y no habiendo posibilidades, no hay problemas...
Pero llegamos al Sistema Operativo de nuestros amores, Linux, y descubrimos
que, de partida, no tiene sintaxis Intel, sino AT&T... No entraré en una
discusión de qué sintaxis es mejor. En cualquier caso, y como opinión
personal, prefiero la sintaxis AT&T. Es la sintaxis tradicional de Unix,
es más portable (en el sentido de que para programar para otra
arquitectura sólo implica saber los nuevos códigos de operación y los nuevos
operandos con nombre -registros, etc...-, pero no nueva sintaxis.) y, una
vez que se acostumbra uno, es más fácil detectar errores por el propio
ensamblador.
La sintáxis de ensamblado de AT&T
La sintáxis de AT&T es poco más o menos como la de Intel, en el sentido
de que no cambia los nombres de los códigos de operación ni de los registros,
pero tiene algunas diferencias chocantes a primera vista:
- Los nombres de los códigos de operación (opcodes) llevan una letra
al final que indica el tamaño de los operandos. Aunque algunas veces se puede
inferir el tamaño de los operandos de ellos mismos, resulta una buena práctica
añadir esta letra al final. El sufijo (la letra en cuestión) es b si queremos
indicar operandos tamaño byte, w para tipo word, etc...
- En las instrucciones tales como mov, que llevan un operando origen
y otro destino, el orden en el que se colocan tras el código de operación es
el inverso a la sintáxis Intel. En ésta, primero se coloca el destino y
luego el origen. En la sintáxis AT&T se coloca primero el operando de
origen y luego el de destino. Las instrucciones que tienen más de un operando
de origen no tienen los operandos invertidos, al menos en arquitectura
i386. Esto también ocurre con las instrucciones de punto flotante debido
a como las genera el compilador de C.
- Los operandos inmediatos van precedidos por el símbolo $ en
AT&T, mientras que no llevan delimitadores en la sintáxis Intel.
- Los nombres de los registros van precedidos por el símbolo %,
mientras que no van delimitados en la sintáxis Intel.
- Los operandos de los saltos absolutos cortos van precedidos por el
símbolo emph*, mientras que no van delimitados en la sintáxis Intel.
- Los saltos largos se forman indicando section,offset, mientras
que en la sintáxis Intel se forman indicando section:offset.
Además, las instrucciones para salto largo se llaman ljmp y lcall,
y la de retorno largo se llama lret, en lugar de sus correspondientes
en sintáxis Intel, que son call far, jmp far y ret far.
- Por último, en principio se espera que un programa escrito en lenguaje
de ensamble en Unix tenga una sola sección (una sección viene a ser como un
segmento. Aunque no sea exacto, se puede considerar así.).
El programa ensamblador en Linux
Miramos el nombre de nuestro ensamblador, y reza GNU as... Un poco de
investigación nos lleva a saber que es el ensamblador por defecto, el que
usa nuestro bienamado GNU cc y todos los demás lenguajes de alto nivel.
En seguida dedicamos nuestros esfuerzos a buscar otro ensamblador en lugar
del GNU as, que tenga sintaxis Intel, que tenga un manual más pequeño, o
que no tenga manual llegado el caso (ya sabemos lo tedioso que resulta
leer...). Para nuestra satisfacción encontramos al menos tres alternativas:
- Realmode Assembler (as86).
- Netwide Assembler (NASM).
- Table driven Assembler (tdasm).
El primero de ellos, el as86 nos llena de felicidad: no tiene manual.
Además, y presumiblemente, sólo sirve para usar en modo real, pero no
importa, porque ¿quién es el loco que iba a programar en modo protegido?.
Desgraciadamente vemos al poco que la falta de documentación que tanto nos
tranquilizó en un principio es un grave problema a la hora de usarlo.
Además, parece haber más de una versión del as86: una oficial y
otra que según parece sólo se usa para ensamblar una pequeña parte de kernel.
El as86 existe practicamente sólo para eso: ensamblar una parte del código
de inicio del kernel. Personalmente no lo aconsejaría para usarse como
ensamblador de propósito general por cuanto carece de documentación. Así y
todo, se puede usar en modo protegido (el kernel de hecho lo hace) pero no
está pensado para eso... Y que quede claro: es un pequeño gran ensamblador.
El NASM y el tdasm son ensambladores algo más serios. Se han pensado para
desarrollar completamente en ensamblador y tienen sintaxis Intel. No he
usado personalmente el tdasm, pero sí he usado el NASM, y sin ser santo de
mi devoción he de reconocer que es un buen ensamblador con un buen soporte
de macros.
Todos estos ensambladore tienen dos cosas en común: la sintaxis Intel y el
código que generan, que es binario puro, no tiene formato. No es más que los
códigos de operación uno detrás de otro, sin cabeceras, etc...
Pero resulta que nosotros no vamos a usar ninguno de estos ensambladores, y
ahora veremos por qué.
Siguiente: ¿Por qué GNU as?
Superior: GNU as como ensamblador
Anterior: Introducción: ¿por qué lenguaje
Download this document: [src.tar.gz][ps.gz][html.tar.gz][dvi.gz]
Congreso HispaLinux 2000