Pregunta

¿Cómo genera una máquina virtual código de máquina nativo sobre la marcha y lo ejecuta?

Suponiendo que pueda averiguar cuáles son los códigos de operación nativos de la máquina que desea emitir, ¿cómo puede ejecutarlos?

¿Es algo tan complicado como asignar las instrucciones mnemotécnicas a códigos binarios, introducirlas en un puntero char* y convertirlas en una función y ejecutarlas?

¿O generaría una biblioteca compartida temporal (.dll o .so o lo que sea) y la cargaría en la memoria usando funciones estándar como LoadLibrary ?

¿Fue útil?

Solución

Puedes simplemente hacer el contador de programa señale el código que desea ejecutar.Recuerde que los datos pueden ser datos o código.En x86, el contador del programa es el registro EIP.La parte IP de EIP significa puntero de instrucción.Se llama a la instrucción JMP para saltar a una dirección.Después del salto, EIP contendrá esta dirección.

¿Es algo tan complicado como asignar las instrucciones mnemotécnicas a códigos binarios, introducirlas en un puntero char* y convertirlas en una función y ejecutarlas?

Sí.Ésta es una forma de hacerlo.El código resultante se convertiría en un puntero a la función Cª.

Otros consejos

¿Es algo tan complicado como asignar las instrucciones mnemotécnicas a códigos binarios, introducirlas en un puntero char* y convertirlas en una función y ejecutarlas?

Sí, si lo estuvieras haciendo en C o C++ (o algo similar), eso es exactamente lo que harías.

Parece complicado, pero en realidad es un artefacto del diseño del lenguaje.Recuerde, el algoritmo real que desea utilizar es muy simple:determine qué instrucciones desea utilizar, cárguelas en un búfer en la memoria y salte al principio de ese búfer.

Sin embargo, si realmente intenta hacer esto, asegúrese de que la convención de llamada sea correcta cuando regrese a su programa C.Creo que si quisiera generar código buscaría una biblioteca que se encargara de ese aspecto por mí.Nanojit ha aparecido en las noticias recientemente;podrías mirar eso.

Sí.Simplemente crea un char* y ejecútalo.Sin embargo, es necesario tener en cuenta un par de detalles.El char* debe estar en una sección ejecutable de la memoria y debe tener la alineación adecuada.

Además de nanojit, también puedes consultar LLVM, que es otra biblioteca capaz de compilar varias representaciones de programas en un puntero de función.Su interfaz es limpia y el código generado tiende a ser eficiente.

Hasta donde yo sé, compila todo en la memoria porque tiene que ejecutar algunas heurísticas para optimizar el código (es decir:en línea con el tiempo) pero puedes echar un vistazo a Infraestructura de lenguaje común de fuente compartida 2.0 liberación del rotor.Todo el código base es idéntico a .NET excepto Jitter y GC.

Además del Rotor 2.0, también puede echar un vistazo al Máquina virtual de punto de acceso en OpenJDK.

Acerca de generar una DLL:las E/S adicionales requeridas para eso, más la vinculación, más la complejidad de generar el formato DLL, lo harían mucho más complicado y, sobre todo, acabarían con el rendimiento;Además, al final todavía llamas a un puntero de función al código cargado, así que...Además, la compilación JIT puede realizarse de un método a la vez y, si desea hacerlo, generará muchas DLL pequeñas.

Acerca del requisito de la "sección ejecutable", llamar a mprotect() en sistemas POSIX puede corregir los permisos (hay una API similar en Win32).Debe hacerlo para un segmento de memoria grande en lugar de una vez por método, ya que de lo contrario sería demasiado lento.

En x86 simple no notarías el problema, en x86 con PAE o máquinas AMD64/Intel de 64 bits de 64 bits obtendrías un error de segmentación.

¿Es algo tan hacky como mapear las instrucciones mnemónicas a los códigos binarios, meterlo en un puntero de char* y lanzarlo en función y ejecutar?

Sí, eso funciona.

Para hacer esto en Windows debes configurar PAGE_EXECUTE_READWRITE en el bloque asignado:

void (*MyFunc)() = (void (*)()) VirtualAlloc(NULL, sizeofblock,  MEM_COMMIT, PAGE_EXECUTE_READWRITE);

//Now fill up the block with executable code and issue-

MyFunc();
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top