147 lines
3.1 KiB
C
147 lines
3.1 KiB
C
/* RAR-VM assembler/disassembler by pancake for radare with love */
|
|
/* this implementation is licensed under LGPLv3 - 2012 */
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
// XXX little endian only?
|
|
|
|
/* helpers */
|
|
#define eprintf(x,...) fprintf(stderr,x,##__VA_ARGS__)
|
|
#define SKIPSPACES(x) if (x) while (*x==' '||*x=='\t') x++
|
|
static const char *skipspaces(const char *x) { SKIPSPACES(x); return x; }
|
|
//static const char *regs = "r0\x00r1\x00r2\x00r3\x00r4\x00r5\x00r6\x00r7";
|
|
//static const char *getregi(int n) { return (n>=0&&n<=7)? regs+(3*n): "r?"; }
|
|
static int getreg(const char *s) {
|
|
if (s[0]=='r' && s[2]=='\0') {
|
|
int n = s[1]-'0';
|
|
if (n<8) return n;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
// ugly global vars
|
|
typedef struct {
|
|
int bits;
|
|
unsigned char *out;
|
|
} Bitbuf;
|
|
|
|
//static void clrbit(Bitbuf *bb) { memset (bb->out, 0, 1+(bb->bits/8)); }
|
|
|
|
static int bitget(Bitbuf *bb, int bit) {
|
|
if (bit>=bb->bits) return -1;
|
|
return (bb->out[bit/8] & (1<<((bit%8))))? 1: 0;
|
|
}
|
|
|
|
static void bitadd(Bitbuf *bb, unsigned int v, int n) {
|
|
int i, b, bit;
|
|
for (i=0; i<n; i++, bb->bits++) {
|
|
b = (bb->bits+i)/8;
|
|
bit = (bb->bits+i)%8;
|
|
//printf ("[%d].%d = %d\n", b, bit, v& (1<<(n-i-1)));
|
|
if (!bit) bb->out[b] = 0;
|
|
//printf ("BIT (%d)\n", n-i-1);
|
|
//if (v&(1<<(n-i-1))) bb->out[b] |= 1<<bit;
|
|
if (v&(1<<(n-i-1))) bb->out[b] |= 1<<bit;
|
|
// printf ("%d", oz);
|
|
}
|
|
//printf ("\n");
|
|
}
|
|
|
|
#define T_BYTE (1<<2)
|
|
#define T_JUMP (1<<3)
|
|
#define T_PROC (1<<4)
|
|
|
|
#define NOPS 53
|
|
static struct {
|
|
const char *name;
|
|
int flags;
|
|
} opcodes [NOPS] = {
|
|
{ "mov", 3|T_BYTE },
|
|
{ "cmp", 3|T_BYTE },
|
|
{ "add", 3|T_BYTE },
|
|
{ "sub", 1|T_BYTE },
|
|
{ "jz", 1|T_JUMP },
|
|
{ "jnz", 1|T_JUMP },
|
|
{ "inc", 1|T_BYTE },
|
|
{ "dec", 1|T_BYTE },
|
|
{ "jmp", 1|T_JUMP },
|
|
{ "xor", 3|T_BYTE },
|
|
{ "and", 3|T_BYTE },
|
|
{ "or", 3|T_BYTE },
|
|
{ "test", 3|T_BYTE },
|
|
{ "js", 1|T_JUMP },
|
|
{ "jb", 1|T_JUMP },
|
|
{ "jbe", 1|T_JUMP },
|
|
{ "ja", 1|T_JUMP },
|
|
{ "jae", 1|T_JUMP },
|
|
{ "push", 1 },
|
|
{ "pop", 1 },
|
|
{ "call", 1|T_PROC },
|
|
{ "ret", T_PROC },
|
|
{ "not", 1|T_BYTE },
|
|
{ "shl", 3|T_BYTE },
|
|
{ "shr", 3|T_BYTE },
|
|
{ "sar", 3|T_BYTE },
|
|
{ "neg", 1|T_BYTE },
|
|
{ "pusha",0 },
|
|
{ "popa", 0 },
|
|
{ "pushf",0 },
|
|
{ "popf", 0 },
|
|
{ "movzx",3 },
|
|
{ "movsx",3 },
|
|
{ "xchg", 3|T_BYTE },
|
|
{ "mul", 3|T_BYTE },
|
|
{ "div", 3|T_BYTE },
|
|
{ "adc", 3|T_BYTE },
|
|
{ "sbb", 3|T_BYTE },
|
|
{ "print",0 },
|
|
{ "movb", 0 },
|
|
{ "movd", 0 },
|
|
{ "cmpb", 0 },
|
|
{ "cmpd", 0 },
|
|
{ "addb", 0 },
|
|
{ "addd", 0 },
|
|
{ "subb", 0 },
|
|
{ "subd", 0 },
|
|
{ "incb", 0 },
|
|
{ "incd", 0 },
|
|
{ "decb", 0 },
|
|
{ "decd", 0 },
|
|
{ "negb", 0 },
|
|
{ "negd", 0 },
|
|
};
|
|
|
|
#if 0
|
|
static int bitnum (Bitbuf *bb, int n, int c) {
|
|
int i, ret = 0;
|
|
if (n<bb->bits)
|
|
for (i=0; i<c; i++)
|
|
if (bitget (bb, n+i)>0)
|
|
ret |= (1<<i);
|
|
return ret;
|
|
}
|
|
#else
|
|
static int bitnum (Bitbuf *bb, int n, int c) {
|
|
int i, ret = 0;
|
|
if (n<bb->bits)
|
|
for (i=0; i<c; i++)
|
|
if (bitget (bb, n+i)>0)
|
|
ret |= (1<<(c-i-1));
|
|
return ret;
|
|
}
|
|
|
|
#endif
|
|
static inline const char *opcode_str (int n) {
|
|
if (n>=0 && n<NOPS)
|
|
return opcodes[n].name;
|
|
return NULL;
|
|
}
|
|
static inline int opcode_num (const char *s) {
|
|
int i;
|
|
for (i=0; opcodes[i].name; i++)
|
|
if (!strcmp (s, opcodes[i].name))
|
|
return i;
|
|
return -1;
|
|
}
|