Esta es una pregunta muy abierta, no estoy seguro de dónde quiere ir con ella. Wikipedia cubre el tema genérico con una respuesta genérica. El código nativo emulado o virtualizado se reemplaza por código nativo. Cuanto más se ejecuta el código, más se reemplaza.
Creo que necesita hacer algunas cosas, primero decida si está hablando de una emulación o una máquina virtual como vmware o virtualbox. Una emulación: el procesador y el hardware se emulan utilizando software, por lo que el emulador lee la siguiente instrucción, el código de operación se separa por código y usted determina qué hacer con él. He estado realizando una emulación 6502 y una traducción binaria estática, que es una recompilación dinámica pero preprocesada en lugar de en tiempo real. Entonces tu emulador puede tomar un LDA # 10, cargar un con inmediato, el emulador ve la carga Una instrucción inmediata, sabe que tiene que leer el siguiente byte que es el inmediato que el emulador tiene una variable en el código para el registro A y pone el valor inmediato en esa variable. Antes de completar las instrucciones, el emulador necesita actualizar las banderas, en este caso, la bandera de Cero es clara, la bandera de N es clara, C y V no se tocan.Pero, ¿y si la siguiente instrucción fuera una carga X inmediata? No es gran cosa, ¿verdad? Bueno, la carga x también modificará los indicadores z y n, por lo que la próxima vez que ejecutes la carga de una instrucción podrás darte cuenta de que no tienes que calcular las banderas porque serán destruidas, es un código muerto en la emulación. Usted puede continuar con este tipo de pensamiento, digamos que ve el código que copia la x de registro a la de un registro y luego empuja el un registro en la pila se copia a la y registro a la de un registro y lo empuja en la pila, podría reemplazar ese pedazo simplemente presionando los registros xey en la pila. O puede ver un par de agregar con acarreos encadenados para realizar un agregado de 16 bits y almacenar el resultado en ubicaciones de memoria adyacentes. Básicamente busca operaciones que el procesador que se está emulando no pudo hacer, pero es fácil de hacer en la emulación. La traducción binaria estática que sugiero que investigue antes de la recompilación dinámica, realiza este análisis y traducción de forma estática, como antes de ejecutar el código. En lugar de emular, puede traducir los códigos de operación a C, por ejemplo, y eliminar tanto código muerto como pueda (una buena característica es que el compilador de C puede eliminar más código muerto para usted).
Una vez que el concepto de la emulación y la traducción se entiende entonces se puede tratar de hacerlo de forma dinámica, desde luego, no es trivial. Sugiero tratar de hacer nuevamente una traducción estática de un código binario al procesador de la máquina del procesador de destino, lo cual es un buen ejercicio. No intentaría optimizaciones dinámicas de tiempo de ejecución hasta que hubiera tenido éxito en realizarlas estáticamente contra a/the binary.
virtualización es una historia diferente, usted está hablando acerca de cómo ejecutar el mismo procesador en el mismo procesador. Entonces x86 en un x86 por ejemplo. la belleza aquí es que al usar procesadores x86 no antiguos, puede tomar el programa que se está virtualizando y ejecutar los códigos de operación reales en el procesador real, sin emulación. Te atrapa de configuración integradas en el procesador para coger cosas, por lo que los valores de carga en AX y la adición de BX, etc., todo ocurre en tiempo real sobre el procesador, cuando AX quiere leer o escribir en la memoria depende de su mecanismo de interceptación si las direcciones se encuentran dentro las máquinas virtuales ram espacio, no hay trampas, pero digamos que el programa escribe en una dirección que es la UART virtualizado, usted tiene la trampa de procesador que a continuación, a continuación, VMware o lo que sea que decodifica escritura y emula que hablar con un puerto serie real. Sin embargo, esa instrucción no era en tiempo real, llevó bastante tiempo ejecutarla. Lo que podría hacer si elige es reemplazar esa instrucción o conjunto de instrucciones que escriben un valor en el puerto serie virtualizado y tal vez luego escribir en una dirección diferente que podría ser el puerto serie real o alguna otra ubicación que no va a funcionar. causa un error que hace que el administrador de vm tenga que emular la instrucción. O agregue un código en el espacio de memoria virtual que realiza una escritura en el uart sin una trampa, y haga que ese código se bifurque a esta rutina de escritura uart. La próxima vez que aciertes ese trozo de código, ahora se ejecuta en tiempo real.
Otra cosa que puede hacer es, por ejemplo, emular y, a medida que avanza, traducir a un bytcode intermedio virtual, como llvm. A partir de ahí, puede traducir de la máquina intermedia a la máquina nativa, reemplazando eventualmente grandes secciones del programa, si no todo. Todavía tiene que lidiar con los periféricos y E/S.
Eso no es lo que estoy hablando. Estoy hablando de tomar bytes en bruto que no son IE del código fuente. Necesita escribir el compilador y cargarlo en código ingenuamente. Vi un mal ejemplo con ensamblaje en línea que creo que es un lote pero parece que no funciona, fue un mal ejemplo. –