{"id":339,"date":"2026-03-06T21:47:39","date_gmt":"2026-03-06T21:47:39","guid":{"rendered":"https:\/\/hackcuba.net\/?p=339"},"modified":"2026-03-06T21:47:39","modified_gmt":"2026-03-06T21:47:39","slug":"hablemos-de-compilacion","status":"publish","type":"post","link":"https:\/\/hackcuba.net\/?p=339","title":{"rendered":"Hablemos de compilaci\u00f3n&#8230;"},"content":{"rendered":"\n<p>Para todos nosotros, los compiladores son programas que traducen un c\u00f3digo fuente a un c\u00f3digo objeto. Estos traductores han permitido que los lenguajes puedan alcanzar mayores grados de abstracci\u00f3n y claridad en su sintaxis. Estamos ajenos a c\u00f3mo el CPU realiza lo que necesitamos; el c\u00f3digo compilado es el encargado de explic\u00e1rselo. El objetivo de este art\u00edculo es introducirnos en el proceso de compilaci\u00f3n, c\u00f3mo funciona a grandes rasgos y cu\u00e1les son sus principales caracter\u00edsticas.<\/p>\n\n\n\n<!--more-->\n\n\n\n<h2 class=\"wp-block-heading\">[C\u00f3DIGO FUENTE] -&gt; (COMPILADOR) -&gt; [C\u00f3DIGO OBJETO]<\/h2>\n\n\n\n<p>El proceso de compilaci\u00f3n est\u00e1 dividido en diferentes etapas con prop\u00f3sitos individuales, pero que juntos alcanzan la tarea final: traducirnos nuestro c\u00f3digo. El c\u00f3digo objeto o final no tiene que ser espec\u00edficamente c\u00f3digo m\u00e1quina, puede perfectamente ser un lenguaje intermedio como el Byte Code de Java o el MSIL de .NET. He dividido el trabajo en las etapas que conforman la compilaci\u00f3n.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1<small>ra<\/small>: An\u00e1lisis Lexicol\u00f3gico o Lexicogr\u00e1fico::<\/h2>\n\n\n\n<p>Todo lenguaje est\u00e1 formalizado por una gram\u00e1tica, que define cu\u00e1les son las caracter\u00edsticas del mismo. Define, por ejemplo, cu\u00e1les son los caracteres terminales: operadores, delimitadores, palabras claves, caracter\u00edsticas de los identificadores, etc. El Analizador Lexicol\u00f3gico o Lexer, se encarga de convertir todo el c\u00f3digo fuente en una secuencia de <em>tokens<\/em>, que no son m\u00e1s que esos caracteres terminales. Los ejemplos siguientes nos ayudar\u00e1n:<\/p>\n\n\n\n<p>C\u00f3digo fuente 1: <code>int a := 25;<\/code><br>Cadena de <em>tokens<\/em>: <code>INT,ID,ASIG,CONST,SEMICOLON<\/code>.<\/p>\n\n\n\n<p>C\u00f3digo fuente 2: <code>int b:= (a*2)+4;<\/code><br>Cadena de <em>tokens<\/em>:<code> INT,ID,ASIG,LP,ID,MULT,CONST,RP,PLUS,CONST,SEMICOLON<\/code>.<\/p>\n\n\n\n<p>Las comas las puse para aclararlo un poco, pues el Lexer s\u00f3lo devuelve una secuencia de <em>tokens<\/em> y se come todos los espacios, cambios de l\u00edneas, comentarios y tabulaciones que escribimos en nuestro c\u00f3digo original. Hay lenguajes como Python que son indentados (ver referencias), donde las tabulaciones y saltos de l\u00edneas cumplen un objetivo; pero en la mayor\u00eda de ellos podemos escribir todo un programa en una sola l\u00ednea.<\/p>\n\n\n\n<p>El Lexer tambi\u00e9n trabaja con el Gestor de Errores, que acumula todos los errores en el c\u00f3digo detectables por el compilador: los llamados errores en tiempo de compilaci\u00f3n. El Lexer es capaz de detectar todo lo que no es v\u00e1lido para la gram\u00e1tica, como identificadores que empiezan con un n\u00famero y operadores indefinidos (<code>3 +(4@5)<\/code> \/\/ la arroba no pinta nada). La Tabla de S\u00edmbolos se encarga de ir acumulando todos los campos o identificadores que se definan en el programa; luego, cuando el Lexer encuentre lo que \u00e9l supone que sea un identificador, lo agrega a la Tabla.<\/p>\n\n\n\n<p>El resultado final del Lexer es, como dijimos, una secuencia de <em>tokens<\/em>, pero \u00e9stos pueden a su vez contener atributos. Por ejemplo, el <code>ID<\/code> guarda su nombre, <code>CONST<\/code> puede ser num\u00e9rico o secuencia de caracteres; luego guarda su tipo y el valor que contiene.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2<small>da<\/small> Etapa: An\u00e1lisis Sint\u00e1ctico::<\/h2>\n\n\n\n<p>Este analizador tambi\u00e9n se conoce como Parser y es el encargado de reconocer si el orden de los <em>tokens<\/em> es correcto, adem\u00e1s de generar \u00e1rboles de an\u00e1lisis sint\u00e1cticos. El an\u00e1lisis sint\u00e1ctico se especifica mediante una gram\u00e1tica libre de contexto.<\/p>\n\n\n\n<p><a href=\"file:\/\/\/home\/h0ax\/Hacking%20&amp;%20Programacion\/Rebista%20BlackHat\/BlackHat%2019\/_imgs\/0x660017.png\" target=\"_blank\" rel=\"noreferrer noopener\"><\/a><\/p>\n\n\n\n<p>Jerarqu\u00eda gramatical Chomsky<\/p>\n\n\n\n<p>Es imprescindible hablar un poco de las gram\u00e1ticas si queremos ver c\u00f3mo funcionan los compiladores. Una gram\u00e1tica est\u00e1 compuesta por objetos terminales (son los identificadores, constantes, operadores&#8230;), objetos no terminales (son expresiones booleanas, aritm\u00e9ticas&#8230;) y un conjunto de reglas que transforman una secuencia de terminales y no terminales en otra. El estudioso Noam Chomsky (amigo de Cuba, ha salido en las Mesas Redondas analizando cuestiones pol\u00edticas) defini\u00f3 una jerarqu\u00eda de gram\u00e1ticas para clasificarlas de acuerdo a la estructura de sus reglas.<\/p>\n\n\n\n<p>Las Gram\u00e1ticas Libres del Contexto son aquellas cuyas reglas tienen la siguiente forma:<\/p>\n\n\n\n<p><code>A-&gt; x<\/code>, donde <code>A<\/code> es un No terminal y <code>x<\/code> es una secuencia de terminales y no terminales cualesquiera.<\/p>\n\n\n\n<p>Entrando en nuestro problema nuevamente, un lenguaje de programaci\u00f3n est\u00e1 definido por una gram\u00e1tica -en muchos casos libre del contexto. Las reglas no son m\u00e1s que la sintaxis de los mismos, por ejemplo:<\/p>\n\n\n\n<p><code>&lt;<em>asignaci\u00f3n<\/em>&gt; -&gt; &lt;<em>variable<\/em>&gt; &lt; := &gt; &lt;<em>expresi\u00f3n<\/em>&gt;<\/code><\/p>\n\n\n\n<p>Donde <code>&lt;<em>asignaci\u00f3n<\/em>&gt;<\/code>, <code>&lt;<em>variable<\/em>&gt;<\/code> y <code>&lt;<em>expresi\u00f3n<\/em>&gt;<\/code> son no terminales, luego tienen a su vez otras reglas que los derivan, y <code>&lt;:=&gt;<\/code>, que es un terminal. El hecho de definir los lenguajes de esta manera nos permite estructurar un programa en forma de \u00e1rbol, llamado \u00e1rbol de derivaci\u00f3n.<\/p>\n\n\n\n<p>Dada la siguiente gram\u00e1tica veremos c\u00f3mo la flecha roja del ejemplo genera el \u00e1rbol de derivaci\u00f3n para <code>A:= A+B<\/code>:<\/p>\n\n\n\n<p><code>&lt;<em>sent_asig<\/em>&gt; -&gt; &lt;<em>var<\/em>&gt; := &lt;<em>expresi\u00f3n<\/em>&gt;<br>&lt;<em>expresi\u00f3n<\/em>&gt; -&gt; &lt;<em>expresi\u00f3n<\/em>&gt; + &lt;<em>t\u00e9rmino<\/em>&gt; | &lt;<em>expresi\u00f3n<\/em>&gt; - &lt;<em>t\u00e9rmino<\/em>&gt;|&lt;<em>t\u00e9rmino<\/em>&gt;<br>&lt;<em>t\u00e9rmino<\/em>&gt; -&gt; &lt;<em>t\u00e9rmino<\/em>&gt; * &lt;<em>factor<\/em>&gt; | &lt;<em>t\u00e9rmino<\/em>&gt; \/ &lt;<em>factor<\/em>&gt;|&lt;<em>factor<\/em>&gt;<br>&lt;<em>factor<\/em>&gt; -&gt; ( &lt;<em>expresi\u00f3n<\/em>&gt; ) |&lt;<em>var<\/em>&gt; | &lt;<em>num<\/em>&gt;<br>&lt;<em>var<\/em>&gt; -&gt; A | B | C | D | ... |Z<br>&lt;<em>num<\/em>&gt; -&gt; 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9<\/code><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"400\" height=\"225\" src=\"https:\/\/hackcuba.net\/wp-content\/uploads\/2026\/03\/0x660018.gif\" alt=\"\" class=\"wp-image-340\"\/><\/figure>\n\n\n\n<p>Trata ahora de generar el \u00e1rbol siguiente, correspondiente a la sentencia <code>C:=D-E*F<\/code>:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"235\" height=\"214\" src=\"https:\/\/hackcuba.net\/wp-content\/uploads\/2026\/03\/0x660019-1.png\" alt=\"\" class=\"wp-image-341\"\/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">3<small>ra<\/small> Etapa: An\u00e1lisis Sem\u00e1ntico (AS)::<\/h2>\n\n\n\n<p>Toda gram\u00e1tica tiene una sintaxis y una sem\u00e1ntica propia. La sintaxis son las reglas que determinan c\u00f3mo se deben escribir las oraciones en el caso de los lenguajes comunes, y la sem\u00e1ntica le da el significado a estas composiciones. El AS es el encargado de interpretar lo que estamos escribiendo, verificando lo siguiente:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Verificar que las variables han sido declaradas previamente cuando se usan.<\/li>\n\n\n\n<li>Comprobaci\u00f3n de tipos en las expresiones.<\/li>\n\n\n\n<li>Comprobaci\u00f3n de los par\u00e1metros de una funci\u00f3n. El tipo de los par\u00e1metros deben coincidir entre el llamado y la definici\u00f3n.<\/li>\n\n\n\n<li>Elecci\u00f3n de la funci\u00f3n u operador en caso de sobrecarga o polimorfismo.<\/li>\n<\/ul>\n\n\n\n<p><a href=\"file:\/\/\/home\/h0ax\/Hacking%20&amp;%20Programacion\/Rebista%20BlackHat\/BlackHat%2019\/_imgs\/0x660020.png\" target=\"_blank\" rel=\"noreferrer noopener\"><\/a><\/p>\n\n\n\n<p>Cuando no se cumple lo anterior, se emiten errores al Gestor de Errores que ya vimos anteriormente. El AS es el encargado de construir el \u00c1rbol de Sintaxis Abstracta (ASA), dado el \u00e1rbol hecho por el Parser.<\/p>\n\n\n\n<p>A la izquierda de la figura hay un \u00e1rbol de derivaci\u00f3n hecho por el Parser y a la derecha un ASA hecho por el Analizador Sem\u00e1ntico. Como podemos percibir, el ASA es m\u00e1s espec\u00edfico que el \u00e1rbol de sintaxis logrado por el Parser, pues adiciona a los nodos del \u00e1rbol atributos que describen su funci\u00f3n y elimina algunos innecesarios.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">4<small>ta<\/small> Etapa: Generaci\u00f3n de C\u00f3digo Intermedio::<\/h2>\n\n\n\n<p>El c\u00f3digo intermedio tiene varios usos. Puede ser un lenguaje de alto nivel diferente (generalmente C), para el cual ya existe un compilador eficiente. Esta soluci\u00f3n se aplica com\u00fanmente a lenguajes declarativos como Prolog y Haskell.<\/p>\n\n\n\n<p>La segunda -y de gran importancia en el c\u00f3digo intermedio- es que sirve de plataforma para varios lenguajes y diferentes tipos de computadoras. Por ejemplo, si queremos escribir en cinco lenguajes unos programas para correrlos en tres arquitecturas de computadoras diferentes, necesitamos 5*3 compiladores. Si tenemos un c\u00f3digo intermedio, necesitamos cinco para llevar cada lenguaje a \u00e9ste y otros tres para convertirlo en el c\u00f3digo de m\u00e1quina espec\u00edfico. Comparamos 5*3 con 5+3 y quedamos convencidos; \u00bfse imaginan como ser\u00eda con todos los lenguajes que soporta .NET (C#, VB, J#, C++, Python&#8230;)?<\/p>\n\n\n\n<p>El c\u00f3digo intermedio tambi\u00e9n posibilita el polimorfismo entre lenguajes. La idea es dise\u00f1ar un carro en Visual Basic y su conductor en C#, pues como ambos terminan en IL (<em>Intermediate Language<\/em> de .NET) son claramente compatibles.<\/p>\n\n\n\n<p>Existen muchos c\u00f3digos intermedios, como el Byte Code de Java, el MSIL de Microsoft, o el mismo C. No me propongo definir ninguno en espec\u00edfico, pues creo que nos llevamos la idea de qu\u00e9 se trata. Son independiente de la m\u00e1quina (hasta cierto punto), no tienen en cuenta caracter\u00edsticas como la arquitectura del procesador, el n\u00famero de registros del mismo o la funcionalidad de estos. Son lenguajes de alto nivel, pero m\u00e1s orientados a la generaci\u00f3n de c\u00f3digo m\u00e1quina.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">5<small>ta<\/small> Etapa: Optimizaci\u00f3n de C\u00f3digo Intermedio::<\/h2>\n\n\n\n<p>Muchos compiladores dividen todo el proceso en <em>Front End<\/em> y <em>Back End<\/em>. El primero es la parte que analiza el c\u00f3digo fuente, comprueba su validez, genera el \u00e1rbol de derivaci\u00f3n y rellena los valores de la tabla de s\u00edmbolos. Toda esta parte es independiente a la plataforma para la que se compila. La segunda etapa, <em>Back End<\/em>, se encarga de generar el c\u00f3digo m\u00e1quina.<\/p>\n\n\n\n<p>A partir de ahora estamos en <em>Back End<\/em>, trabajando en base a una plataforma espec\u00edfica (puede ser Intel, Mac, o cualquier otra). Idealmente, los compiladores deben producir c\u00f3digo objeto tan bueno como el producido a mano por un programador experto. En la realidad, este objetivo raramente es alcanzado. Sin embargo, el c\u00f3digo puede ser mejorado en tiempo y espacio usando algoritmos eficientes.<\/p>\n\n\n\n<p>Concluyendo, la idea es mejorar el c\u00f3digo objeto final preservando el significado original del programa, realizando s\u00f3lo optimizaciones seguras. Las optimizaciones est\u00e1n alrededor de mejorar la velocidad de ejecuci\u00f3n y disminuir tanto el tama\u00f1o del programa como sus necesidades de memoria.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">6<small>ta<\/small> Etapa: Generaci\u00f3n de C\u00f3digo Objeto::<\/h2>\n\n\n\n<p>Ahora nos toca generar el c\u00f3digo ensamblador y tomaremos como ejemplo el de la tecnolog\u00eda i383. En otras palabras, las representaciones intermedias dejarlas a nivel de <code>MOV<\/code>, <code>ADD<\/code> y <code>goto<\/code>.Vamos a ver dos ejemplos solamente y de forma muy abstracta, pues esta etapa es sumamente compleja.<\/p>\n\n\n\n<p><strong>Intermedio:<\/strong><br><code>if &lt;<em>condici\u00f3n<\/em>&gt;<br>then &lt;<em>sentencia1<\/em>&gt;<br>else &lt;<em>sentencia2<\/em>&gt;<\/code><\/p>\n\n\n\n<p><strong>Ensamblador:<\/strong><br>;resultado de condici\u00f3n lo guardo en tmp<code><br>if tmp == false goto label_false<br>&lt;<em>c\u00f3digo de sentencia1<\/em>&gt;<br>goto label_fin<br>label_false:<br>&lt;<em>c\u00f3digo de sentencia2<\/em>&gt;<br>label_fin:<\/code><\/p>\n\n\n\n<p><strong>Intermedio:<\/strong><br><code>A = B+C;<\/code><\/p>\n\n\n\n<p><strong>Ensamblador:<\/strong><br><code>MOV ebx, BYTE PTR [B]<br>MOV ecx, BYTE PTR [C]<br>ADD ebx,ecx<br>MOV [A], ebx<\/code><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusiones::<\/h2>\n\n\n\n<p>El c\u00f3digo que genera todo el <em>Back End<\/em> normalmente no se puede ejecutar directamente, sino que necesita ser enlazado por un programa enlazador (ver en referencias: <em>linker<\/em>). No obstante, ya todo el trabajo duro qued\u00f3 aqu\u00ed.<\/p>\n\n\n\n<p>Como pudimos apreciar, compilar es una tarea larga que toma cierto tiempo para el CPU. Pero buenos compiladores nos reducen el margen para futuros errores en tiempo de ejecuci\u00f3n y nos optimiza el c\u00f3digo; luego vale la pena esperar que hagan su trabajo.<\/p>\n\n\n\n<p>No quiero terminar sin hablar de ANTLR, no es m\u00e1s que una de esas herramientas que nos ayuda en la creaci\u00f3n de compiladores. Posee caracter\u00edsticas que lo recomiendan para construir una herramienta procesadora de lenguajes, por ejemplo: a diferencia de otras herramientas, que solamente se encargan de una de las fases del proceso antes mencionadas, ANTLR se encarga del an\u00e1lisis lexicogr\u00e1fico y del sint\u00e1ctico -adem\u00e1s de dejar parte del trabajo hecho para el sem\u00e1ntico. Genera c\u00f3digo para C++, Java, Phyton y C# y, lo mejor, es independiente de la plataforma.<\/p>\n\n\n\n<p>El proceso completo de compilaci\u00f3n quedar\u00eda de la siguiente manera:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"444\" height=\"258\" src=\"https:\/\/hackcuba.net\/wp-content\/uploads\/2026\/03\/0x660021.png\" alt=\"\" class=\"wp-image-342\" srcset=\"https:\/\/hackcuba.net\/wp-content\/uploads\/2026\/03\/0x660021.png 444w, https:\/\/hackcuba.net\/wp-content\/uploads\/2026\/03\/0x660021-300x174.png 300w\" sizes=\"auto, (max-width: 444px) 100vw, 444px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Para saber m\u00e1s&#8230;<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"http:\/\/en.wikipedia.org\/wiki\/Compilation_%28programming%29\" target=\"_blank\" rel=\"noreferrer noopener\">Wikipedia::Compilaci\u00f3n<\/a><\/li>\n\n\n\n<li><a href=\"http:\/\/en.wikipedia.org\/wiki\/Compiler_%28computing%29\" target=\"_blank\" rel=\"noreferrer noopener\">Wikipedia::Compiladores<\/a><\/li>\n\n\n\n<li><a href=\"http:\/\/es.wikipedia.org\/wiki\/Enlazador\" target=\"_blank\" rel=\"noreferrer noopener\">Wikipedia::Enlazador<\/a><\/li>\n\n\n\n<li><a href=\"http:\/\/en.wikipedia.org\/wiki\/ANTLR\" target=\"_blank\" rel=\"noreferrer noopener\">Wikipedia::ANTLR<\/a><\/li>\n<\/ul>\n\n\n\n<p>Escrito por Krlo [<a href=\"mailto:blackhat4all@gmail.com?subject=para Krlo\">blackhat4all@gmail.com<\/a>]<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Para todos nosotros, los compiladores son programas que traducen un c\u00f3digo fuente a un c\u00f3digo objeto. Estos traductores<\/p>\n","protected":false},"author":2,"featured_media":119,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[59,18,36],"tags":[88,116,58,38],"class_list":["post-339","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-codigos","category-programacion","category-proyecto-blackhat","tag-codigos","tag-compilacion","tag-programacion","tag-proyecto-blackhat"],"_links":{"self":[{"href":"https:\/\/hackcuba.net\/index.php?rest_route=\/wp\/v2\/posts\/339","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hackcuba.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/hackcuba.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/hackcuba.net\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/hackcuba.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=339"}],"version-history":[{"count":1,"href":"https:\/\/hackcuba.net\/index.php?rest_route=\/wp\/v2\/posts\/339\/revisions"}],"predecessor-version":[{"id":343,"href":"https:\/\/hackcuba.net\/index.php?rest_route=\/wp\/v2\/posts\/339\/revisions\/343"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/hackcuba.net\/index.php?rest_route=\/wp\/v2\/media\/119"}],"wp:attachment":[{"href":"https:\/\/hackcuba.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=339"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hackcuba.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=339"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hackcuba.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=339"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}