Código ensamblador en VB6. Complemento ThunderVB.
Código ensamblador en VB6 usando complemento
En otro tutorial vimos cómo ejecutar código asm en VB6 mediante el uso de la función CallWindowProc, un código sencillo que vimos que incluso nos puede servir como protección anticracking. Sin embargo, en VB6 podemos utilizar otra técnica que es el uso de un curioso complemento... Hoy voy a hacer un programa que va a ejecutar un mismo código en Visual Basic 6 y después en ensamblador. Verás la velocidad de uno y otro código.
Complemento ThunderVB
Yo he conocido dos complementos pero uno no conseguí hacerlo funcionar, así que voy a explicar el denominado: ThunderVB en su versión 1.0.0. Realmente es impresionante el gran trabajo que realiza.
Su página web es la siguiente: http://www.freewebs.com/hardcorevb/tvb.html
El proyecto (última actualización el 21 de junio de 2010) se puede encontrar aquí también: http://sourceforge.net/projects/thundervb/
ThunderVB es un excelente complemento para Visual Basic 6. Permite embeber código ensamblador (asm) e instrucciones en C ¡directamente! en el código fuente de tus programas. Además permite extender el IDE de VB a un editor de código asm/C básico, es decir, que puede hacer el resaltado de sintaxis de palabras clave de asm/C y la opción de autocompletar.
ThunderVB dejó de desarrollarse por falta de tiempo de sus desarrolladores, aunque la última versión es bastante estable.
Instalar ThunderVB
Quiero comentar que solo he probado ThunderVB bajo Windows XP, no lo he testeado ni en Windows Vista, ni en 7, ni en 8. Además -importante- requiere que tengas Visual Basic 6 con SP6 que puedes descargar de aquí:
http://www.microsoft.com/download/en/details.aspx?id=5721
Si vas a la descarga de antes de sourceforge y seleccionas "Files" podrás descargar los archivos que necesites. Yo voy a descargar únicamente ThunderVB 1.0.0, exactamente el archivo ThunderVB_1.0.0.rar. Una vez que descomprimes ese archivo verás un ejecutable llamado ThunderVB 1.0.0.exe que es el que debes instalar:
Una vez instalado correctamente te mostrará una ventana: "Add-In called ThunderVB_pl_v1_0 han been installed". Ejecuta VB6, en mi caso observo que se instala el componente y aparece en la barra de herramientas un icono para configurar ThunderVB:
Si al usarlo en un proyecto observas que no aparece, ve al menú de VB6: Complementos -> Administrador de complementos, seleccionas Thunder VB 1.0.0 (observando que no está cargado) y en "comportamiento de carga" selecciona "cargado/descargado" y si quieres "cargar al iniciar".
Proyecto y ejemplo de uso.
Tienes muchos ejemplos que puedes ver en la zona de descarga de antes y hacer las pruebas necesarias. Yo voy a hacer un ejemplo que haga la misma operación en VB que en asm para comprobar la diferencia de velocidad entre uno y otro. ThunderVB puede ensamblar con MASM, TASM y... Yo voy a usar MASM32, así que antes de continuar lo instalo en el directorio C:\.
Crea un nuevo proyecto en VB6, un exe estándar. Voy a crear dos botones: uno para ejecutar código asm(bt_asm) y otro para ejecutar código VB (bt_vb). También crearé dos textbox para mostrar el resultado final de la operación: resultado_asm y resultado_vb. Voy a agregar un módulo al proyecto. En el código del formulario pego el siguiente código:
Option Explicit Private Sub bt_asm_Click() resultado_asm.Text = "" Frame2.Caption = "Procesando...espere un momento" DoEvents resultado_asm.Text = Format$(calcula_en_asm) Frame2.Caption = "Realizar proceso en ASM" End Sub Private Sub bt_vb_Click() Dim i, j As Integer, k As Long resultado_vb.Text = "" Frame1.Caption = "Procesando...espere un momento" DoEvents For j = 0 To 5000 For i = 0 To 32766 k = k + 1 Next i Next j resultado_vb.Text = k Frame1.Caption = "Realizar proceso en Visual Basic 6" End Sub
Y en el código del módulo, pego el siguiente código (donde va el código ensamblador):
Option Explicit Public Function calcula_en_asm() As Long '#asm' LOCAL j :DWORD '#asm' LOCAL i :DWORD '#asm' mov j, 0 '#asm' mov i, 0 '#asm' xor eax, eax '#asm' .repeat '#asm' .repeat '#asm' inc eax '#asm' inc j '#asm' .until j > 1388h '#asm' inc i '#asm' mov j, 0 '#asm' .until i > 7FFEh '#asm' ret End Function
Como puedes ver, los dos códigos hacen las mismas operaciones. En asm cada instrucción debe comenzar por '#asm' pero para más info tienes muchos ejemplos en descarga. Para que ThunderVB pueda ensamblar el código anterior, es necesario configurar la ruta al enlazador (ml.exe). Yo voy a usar MASM32, así que pulso el botón de ThunderVB, selecciono el plugin thunderasm y a la derecha pulso en paths (rutas). En la primera opción (Inline Asm -> Path to Masm (ml.exe)) nos pide la ruta al archivo ml.exe. En mi caso es esta:
C:\masm32\bin\ml.exe
Que pongo en la configuración y pulso Ok.
Con todo configurado ya solo queda generar el exe. Durante este proceso, sale una ventana de título "ThunderAsm" diciendo: "Project Must be saved for asm changes to have effect, You want to save it now?" (Para que los cambios asm tengan efecto debe guardar el proyecto, ¿quiere guardarlo ahora?" Esto es porque habré hecho alguna modificación de código. Pulso en Sí y dice que el proyecto ha sido guardado: "Project ASM_inline was saved". Pulso aceptar y el programa se compila perfectamente.
¿Cómo se genera realmente el código?
Al igual que en otros casos hicimos uso de CallWindowProc para insertar y ejecutar código asm, en este caso quise saber qué hace realmente el plugin ThunderVB con el código anterior. Desensamblé el código del exe y comprobé que ThunderVB hace un trabajo impecable: veo que se ha generado una nueva sección y ahí pega el código ensamblador y el enlace a la misma es una call directa. El código asm final es el siguiente:
1100A000 55 push ebp 1100A001 8BEC mov ebp,esp 1100A003 83C4 F8 add esp,-8 1100A006 C745 FC 00000000 mov dword ptr ss:[ebp-4],0 1100A00D C745 F8 00000000 mov dword ptr ss:[ebp-8],0 1100A014 33C0 xor eax,eax 1100A016 40 inc eax 1100A017 FF45 FC inc dword ptr ss:[ebp-4] 1100A01A 817D FC 88130000 cmp dword ptr ss:[ebp-4],1388 1100A021 ^ 76 F3 jbe short 1100A016 1100A023 FF45 F8 inc dword ptr ss:[ebp-8] 1100A026 C745 FC 00000000 mov dword ptr ss:[ebp-4],0 1100A02D 817D F8 FE7F0000 cmp dword ptr ss:[ebp-8],7FFE 1100A034 ^ 76 E0 jbe short 1100A016 1100A036 C9 leave 1100A037 C3 retn 1100A038 33C0 xor eax,eax 1100A03A C9 leave 1100A03B C3 retn
El trabajo que realiza este plugin es en una palabra: impresionante. Para los todavía usuarios de Visual Basic 6 tal vez les resulte útil.
Descarga de proyecto y exe
Para que todo usuario programador pueda examinar este proyecto dejo el mismo en descarga. También he generado el exe para que cualquiera, tenga o no VB6, pueda ejecutar el exe y comprobar la velocidad final de uno u otro código:
Imagen previa del exe en ejecución en Windows 7:
de antemano gracias y felicitaciones nuevamente por el post
Para pasar un parámetro puedes usar una función como se hace en este tutorial.
El plugin únicamente actúa en la compilación cuando generas el exe.
No sé si lo he comentado en el post, pero en las opciones de Thunder tienes que indicar que vas a usar MASM32. Para hacer esto te vas a la configuración del plugin, como hemos visto en el tutorial.
Y en el menú ThundASM tienes que indicar creo que el compilador de MASM32: ml.exe, no lo recuerdo exactamente porque no lo tengo ahora delante.
Ojalá lo consigas solucionar, tal vez influya la máquina virtual, pero no te lo puedo asegurar.