Simples JIT (just in time) em C
Publicado por ??? (última atualização em 08/07/2013)
[ Hits: 3.774 ]
Este é um simples exemplo de um JIT (just in time) escrito em puro C para Windows e GNU/Linux em 32 bits.
Este exemplo gera uma simples função que chama outra função (hello)...
Espero que seja útil para alguém.
//------------------------------------------------------------------- // // THANKS TO: // The only GOD, creator of heaven and earth, in the name of JESUS CHRIST. // // DESCRIPTION: // A simples JIT (32 bits) x86. // // FILE: // asm.c // // COMPILE: // gcc asm.c -o asm -m32 -O2 -Wall // // BY: gokernel - gokernel@hotmail.com // //------------------------------------------------------------------- #include <stdio.h> #include <stdlib.h> #ifdef __linux__ #include <unistd.h> #include <sys/mman.h> // for: mprotect #endif typedef struct ASM { unsigned char *code; int len; }ASM; ASM *asm_new (int size) { ASM *a = (ASM*) malloc (sizeof(ASM)); a->code = (unsigned char*) malloc (size); a->len = 0; return a; } //------------------------------------------------------------------- // This function use the code of Fabrice Bellard: // // LIB: tcc-0.9.25 // FILE: libtcc.c // FUNC: void set_pages_executable (void *ptr, unsigned long length); // LINE: 400 // // Set executable: a->code // //------------------------------------------------------------------- void asm_set_executable (ASM *a) { #ifdef __linux__ unsigned long start, end, PageSize; PageSize = sysconf (_SC_PAGESIZE); start = (unsigned long)a->code & ~(PageSize - 1); end = (unsigned long)a->code + a->len; end = (end + PageSize - 1) & ~(PageSize - 1); mprotect ((void *)start, end - start, PROT_READ | PROT_WRITE | PROT_EXEC); #endif } // 1 byte void asm_gen (ASM *a, unsigned char c) { *(unsigned char*)(a->code + a->len) = c; a->len++; } // 4 bytes void asm_get_addr (ASM *a, void *ptr) { *(void**)(a->code + a->len) = ptr; a->len += sizeof (void*); } // 7 bytes void asm_op_call (ASM *a, void *func) { // b8 7a 13 40 00 mov $0x40137a,%eax // ff d0 call *%eax // asm_gen (a, 0xb8); asm_get_addr (a, func); asm_gen (a, 0xff); asm_gen(a, 0xd0); } void hello (void) { printf ("\ncall function: Hello World\n\n"); } void execute (void) { ASM *a = asm_new (1000); if (a && a->code) { //----------------------------------------------------------- asm_gen(a, 0x55); // push %ebp asm_gen(a, 0x89); asm_gen(a, 0xe5); // mov %esp,%ebp asm_op_call (a, hello); asm_gen(a, 0xc9); // leave asm_gen(a, 0xc3); // ret //----------------------------------------------------------- asm_set_executable (a); // execute here // ( (void(*)())a->code ) (); free (a->code); free (a); } } int main (void) { execute (); printf ("Exiting with sucess !!!\n"); return 0; }
Crivo de Eratóstenes Simples para Linux x86 em Assembly Puro (GNU Assembler)
GAS Inteiro para String (formato binário)
Escrita de um número em decimal na tela em Assembly Puro para Linux 64 bits (GNU Assembly)
Calcula ano de nascimento - C + Assembly
"Clear Screen" para Linux x86 com Inline Assembly (embutido no código) em C
Desktop Linux ganha fôlego enquanto distros refinam experiência e segurança
Wayland em alta, IA em debate e novos ventos para distros e devices
Qt 6.10 e Python 3.14 puxam o ritmo do software livre nesta quarta
Atualizações de Apps, Desktop e Kernel agitam o ecossistema Linux nesta terça-feira
Como mudar o nome de dispositivos Bluetooth via linha de comando
Adicionando o repositório backports no Debian 13 Trixie