You also need to make sure that the corresponding memory is executable, and make sure that it is properly cleaned from dcache after it is written and loaded into icache before executing it. How to do this depends on the operation of the OS on your computer with mips.
On Linux, you must use the mprotect system call to make the memory executable, and the cacheflush system call to clear the cache.
change
Example:
#include <unistd.h> #include <sys/mman.h> #include <asm/cachecontrol.h> #define PALIGN(P) ((char *)((uintptr_t)(P) & (pagesize-1))) uintptr_t pagesize; void inc(){ int i = 41; uint32_t *addone = malloc(sizeof(*addone) * 2); //we malloc space for our asm function *(addone) = 0x20820001; // this is addi $v0 $a0 1, which adds one to our arg (gcc calling con) *(addone + 1) = 0x23e00000; //this is jr $ra pagesize = sysconf(_SC_PAGESIZE); // only needs to be done once mprotect(PALIGN(addone), PALIGN(addone+1)-PALIGN(addone)+pagesize, PROT_READ | PROT_WRITE | PROT_EXEC); cacheflush(addone, 2*sizeof(*addone), ICACHE|DCACHE); int (*f)(int x) = addone; //our function pointer i = (*f)(i); printf("%d",i); }
Please note that we make the entire page (s) containing the code, both written and executable. This is because memory protection works on the page, and we want malloc to continue to use the rest of the page for other things. Instead, you could use valloc or memalign to highlight entire pages, in which case you could safely execute code to read.
source share