Compilar se compila usando un compilador Xd. Por ejemplo, puedes usar Visual Studio si estás en Windows (y te gusta el entorno), GCC o G++. Hay otros compiladores.
El compilador acepta una entrada, lee el path, los parámetros de ajustes de la compilación; linkea todos los archivos requeridos en uno sólo, analiza la sintaxis, las variables, el scope y demás del fichero; preprocesa las directivas de preprocesador si las hubiera volcándolas (y sobreescribiendo) al archivo y a continuación va traduciendo línea por línea a su equivalente en ensamblador. El equivalente dependerá de la plataforma en que lo compiles o más bien, la plataforma que especifiques. Luego, con el código, crea un objeto ejecutable y lo embebe, embebiendo también las variables en él mismo.
El equivalente en ensamblador es una forma para que lo entiendas, en realidad son instrucciones en hexadecimal, que en realidad son 0 y 1 que la CPU lee como máscaras de bits.
Te pondré una línea de ejemplo para que lo entiendas (no me apetece tampoco trabajar mucho
)
Código C++:
Ver originalint d = 3; // int suponiendo 4 bytes
d++;
Código Ensamblador:
Ver originalmov eax, 3
dword ptr [d],eax
add eax, 1
Buscamos en la
siguiente referencia el equivalente en hexadecimal de esas 3 instrucciones en ensamblador de Intel que equivalen a las instrucciones en C++.
- En primer lugar, en la primera instrucción vemos que el dato introducido se moverá a un registro de 4 bytes (32 bits). Eso significa que la solución más fácil es interpretar ese valor como un valor de 4 bytes (0x00000003). La instrucción sería MOV r16/32/64 imm16/32/64, y el equivalente B8+r donde r es el código de registro, en este caso, eax, que corresponde al 000. imm representa un valor inmediato. En lugar de coger el valor de una dirección de memoria el valor se lee directamente junto a la instrucción, en el mismo flujo, vamos que va tras la instrucción.
La máscara de bits de B8 es
donde sólo los últimos bits representan el registro, como es 000, no se altera nada, queda igual. Ergo, la instrucción es B8, y el siguiente byte representa el valor mismo, por 4 bytes.
- Lo segundo mueve el valor de eax (ya introducido a una dirección de memoria). Todos los punteros se sustituyen por la dirección a la que representan. Supongamos que [d] es 0x4562b103.
La instrucción sería MOV r/m16/32/64 r16/32/64 donde r es el registro y r/m la memoria o el registro. El código de operación es 89.
Dado que no hay máscara de bits, se aplican las reglas de modo de escritura y redirección de memoria extendida del procesador.
Como será de registro EAX a una dirección directamente en memoria (dispuesta), se usa el 05. A continuación del 05 se indica la dirección de memoria dispuesta. 89 05 03 b1 62 45.
- Lo último es incrementar eax.
Se usará add. En concreto, ADD rAX imm16/32. rAX representa cualquier registro pero implícitamente EAX e imm el valor inmediato (como en el punto 1), de nuevo mirando las reglas de modo de escritura. El código de operación es 05. El código de redirección es ninguno ya que como usaremos EAX y es implícito, y a continuación el valor inmediato, de 32 bits, que es 1. 05 01 00 00 00
Ahora pasamos todo eso a binario.
Código Binario:
Ver original10111000 00000011 00000000 00000000 00000000 10001001 00000101 00000011 10110001 01100010 01000101 00000101 00000001 00000000 00000000 00000000
Y listo. Ya somos compiladores humanos. Ahora falta embeberlo en un objeto. Pero eso ya ni idea de cómo es, tendré que ponerme a aprender.