/* Dumbest possible run-time code generation for ARM Thumb? */ #include #include #include #include typedef int (*func_type)(); void assemble_halfword(char **buf, unsigned short h) { *(*buf)++ = h & 0xff; *(*buf)++ = h >> 8; } void assemble_pushn(char **buf, int regs) { assemble_halfword(buf, 0xb400 + regs); } void assemble_popn(char **buf, int regs) { assemble_halfword(buf, 0xbc00 + regs); } void assemble_movs8(char **buf, int reg, int imm8) { assemble_halfword(buf, 0x2000 + (reg << 8) + imm8); } int main() { char *codebuf = mmap(0, /* no requested address */ 4096, /* requested size */ PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, -1, /* MAP_ANONYMOUS portability requires fd -1 */ 0 /* offset is meaningless with no fd */ ); printf("codebuf = %lx\n", (long)codebuf); if (!codebuf) return 1; char *p = codebuf; assemble_pushn(&p, 1 << 8 | 1 << 3); /* only push lr and r3 */ assemble_movs8(&p, 0, 53); /* set r0 to #53 */ assemble_movs8(&p, 1, 53); /* set r1 to #53 */ assemble_popn(&p, 1 << 8 | 1 << 3); /* only pop pc and r3 */ int n = p - codebuf; for (int i = 0; i < n; i++) { printf("%02x ", codebuf[i]); } printf("\n"); /* Write it to a file so I can run a disassembler on it. As in: arm-linux-gnueabi-objdump -b binary -D -Mforce-thumb -mcortex-m4 nullcomplr.out.bin */ char *outfile = "nullcomplr.out.bin"; int fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (fd < 0) { perror(outfile); return 2; } if (n != write(fd, codebuf, n)) { perror("write"); return 3; } if (0 != close(fd)) { perror("close"); return 4; } /* +1 for Thumb! */ printf("result = %d\n", ((func_type)(codebuf+1))()); return 0; }