Ver Mensaje Individual
  #1 (permalink)  
Antiguo 22/12/2012, 17:18
Avatar de dontexplain
dontexplain
 
Fecha de Ingreso: junio-2012
Mensajes: 536
Antigüedad: 11 años, 9 meses
Puntos: 127
Transcripción de C++ a Ensamblador - 1

Bueno, estuve haciendo unas pruebas, más pasatiempo que otra cosa, para ver el código ensamblador (desensamblado) resultante de el código objeto generado al compilar C++. Lo que en cierto modo se puede denominar transcripción de la lógica de alto nivel de C++ a ensamblador.

Como sé que a muchos les puede hacer falta, lo posteo acá y que cada cual saque sus conclusiones. Pongo la primera parte. Perdonen los errores en la descripción que pudieran haber.

---------------------------------------------------------------------

AND estándar

Un AND o que dos condiciones o subconjuntos de condiciones se den a la vez implica que si una de ellas no es positiva se salta directamente. Por lo que son dos condiciones con salto seguidas.

Código C++:
Ver original
  1. if (c > b && b > a)

mov eax,dword ptr [c]
cmp eax,dword ptr [b]
jle main+56h (01124F76h)
mov eax,dword ptr [b]
cmp eax,dword ptr [a]
jle main+56h (01124F76h)

Se compara b con c, y si es negativo se salta a main+56h. Si es positivo se continua comparando a con b y si es negativo se salta a main+56. Si ninguno de los dos anteriores son positivos no se salta, y se continua con la ejecución. Dos comprobaciones negativas.

OR inclusivo (estándar)

Un or inclusivo implica que la condición es verdadera si uno de ellos es verdadero. De modo que con que la primera condición evaluada sea verdadera se salta. Si no es verdadera se comprueba la segunda, y si no es verdadera entonces es cuando se salta, y si no, se continua. Son entonces dos comprobaciones, comprobación positiva y una negativa.

Código C++:
Ver original
  1. if (c > b || b > a)

mov eax,dword ptr [c]
cmp eax,dword ptr [b]
jg main+43h (013C4F63h)
mov eax,dword ptr [b]
cmp eax,dword ptr [a]
jle main+56h (013C4F76h)

Or exclusivo

El operador exclusivo XOR no existe en C++ por lo que es una lógica simulada.

c > b XOR b > a
!(c > b) || !(b > a)

La conversión se produce correctamente porque el operando ! convierte en false cuando hay una salida true, entonces, si los dos operandos son ciertos los dos son negativos. Un operando ! sobre todo el conjunto daría la salida contraria continuamente así que debe ser aplicado a cada subconjunto. Entonces, finalmente, cada una de las salidas sería una positiva y otra negativa salvo cuando los dos fueran positivas.

mov eax,dword ptr [c]
cmp eax,dword ptr [b]
jle main+43h (0964F63h)
mov eax,dword ptr [b]
cmp eax,dword ptr [a]
jg main+56h (0964F76h)

Las instrucciones de comparación son contrarias. La primera salta si es menor, por lo que no permite una segunda comprobación. Si es negativa continua para verificar si la segunda es correcta; si no es correcta salta a otro punto, y si no, continua ejecutando. Una negativa y otra positiva.

Do-while sin operaciones en do

Código C++:
Ver original
  1. do{
  2.  
  3. } while(b > a);

mov eax,dword ptr [b]
cmp eax,dword ptr [a]
jg main+33h (0FA4D03h)

Tras comprobar la superioridad de b sobre a, se establece la condición del salto. El salto es hacia la dirección de memoria 0FA4D03h, que corresponde con la primera instrucción (mov eax, dword ptr [b]), para volver a comprobar.

La variable b (el valor de b) se vuelve a introducir en eax, ya que podría haber cambiado.

Do-while con instrucción en do

Código C++:
Ver original
  1. do{
  2.   d++;
  3. } while(b > a);


mov eax,dword ptr [d]
add eax,1 mov
dword ptr [d],eax
mov eax,dword ptr [b]
cmp eax,dword ptr [a]
jg main+3Ah (01294D0Ah)

Al ser una instrucción do-while, do se realiza aunque no se haya comprobado la condición de while, de modo que las primeras 3 instrucciones se encargan de preincrementar la variable d. Y en la cuarta se procede a realizar la comprobación (si b es superior a a), si es superior se salta a la primera instrucción (01294D0Ah) nuevamente para realizar el mismo procedimiento.

Bucle for

Código C++:
Ver original
  1. for (int i = 0; i < 1000; i++)
  2.  {
  3. d++
  4.  }

mov dword ptr [ebp-38h],0
jmp main+4Ch (011D4D1Ch)
mov eax,dword ptr [ebp-38h]
add eax,1
mov dword ptr [ebp-38h],eax
cmp dword ptr [ebp-38h],3E8h
jge main+60h (011D4D30h)

mov eax,dword ptr [d]
add eax,1
mov dword ptr [d],eax

jmp main+43h (01A4D13h)

1. Lo primero que se hace es introducir el 0 en el registro que apunta (ebp-38h = 0x0040f8b4). La operación jmp probablemente venga precedida por alguna comprobación anterior, por lo que se ignora. Se introduce el 0 en eax y se le suma 1 para volverlo a introducir en el mismo registro. Se compara el registro con 3E8h (1000) y si es mayor o igual se salta a main+60h (coincide con while), si no, se continua con el segundo conjunto.

2. El segundo conjunto mueve d a eax y le incrementa 1 para volverlo a introducir en d. (d++)

3. El tercer conjunto salta inincondicionalmente a la tercera operación del primer conjunto, justo donde se mueve el puntero a eax para sumarle uno. ( } )

Se aprecian dos cualidades:
- La variable i del bucle no se almacena como ningún puntero ([i]) sino que se almacena como ebp-38h y se referencia directamente a esa dirección.
- En un inicio se incrementa i de 0 a 1 antes de realizar la comprobación de si es mayor o menor, de modo que continuamente se incrementa antes de realizar la comprobación.
__________________
21añero.
HTML/CSS, PHP, JS/jQuery, Mysql; NodeJS/Socket.io (& V8); C++ ; Python (wxpy); Ensamblador.
Músico (clarinetista/pianista) y compositor

Última edición por dontexplain; 22/12/2012 a las 17:24