www.pudn.com > ASM86_64.rar > a64-2.c



/*
 *	a64.h for mik's assembler attribute
 */

#include "a64-2.h"
#include "opcode.h"

/*
 *	x86-64 full registers
 */

reg_t regs[] = {
	/* 1-byte regs */
	{ "al", 0x10 }, { "cl", 0x11 }, { "dl", 0x12 }, { "bl", 0x13 },
	{ "ah", 0x14 }, { "spl", 0x14 }, { "ch", 0x15 }, { "bpl", 0x15 },
	{ "dh", 0x16 }, { "sil", 0x16 }, { "bh", 0x17 }, { "dil", 0x17 },
	{ "r8b", 0x18 }, { "r9b",0x19 }, { "r10b", 0x1a }, { "r11b", 0x1b },
	{ "r12b", 0x1c }, { "r13b", 0x1d }, { "r14b", 0x1e }, { "r15b", 0x1f },

	/* 2-bytes regs */
	{ "ax", 0x20 }, { "cx", 0x21 }, { "dx", 0x22 }, { "bx", 0x23 },
	{ "sp", 0x24 }, { "bp", 0x25 }, { "si", 0x26 }, { "di", 0x27 },
	{ "r8w", 0x28 }, { "r9w", 0x29 }, { "r10w", 0x2a }, { "r11w", 0x2b },
	{ "r12w", 0x2c }, { "r13w", 0x2d }, { "r14w", 0x2e }, { "r15w", 0x2f },

	/* 4-bytes regs */
	{ "eax", 0x40 }, { "ecx", 0x41 }, { "edx", 0x42 }, { "ebx", 0x43 },
	{ "esp", 0x44 }, { "ebp", 0x45 }, { "esi", 0x46 }, { "edi", 0x47 },
	{ "r8d", 0x48 }, { "r9d", 0x49 }, { "r10d", 0x4a }, { "r11d", 0x4b },
	{ "r12d", 0x4c }, { "r13d", 0x4d }, { "r14d", 0x4e}, { "r15d", 0x4f },
	
	/* 8-bytes regs */
	{ "rax", 0x80 }, { "rcx", 0x81 }, { "rdx", 0x82 }, { "rbx", 0x83 },
	{ "rsp", 0x84 }, { "rbp", 0x85 }, { "rsi", 0x86 }, { "rdi", 0x87 },
	{ "r8", 0x88 }, { "r9", 0x89 }, { "r10", 0x8a }, { "r11", 0x8b },
	{ "r12", 0x8c }, { "r13", 0x8d }, { "r14", 0x8e }, { "r15", 0x8f },

	/* 64-bit mmx regs */
	{ "mmx0", 0xe0 }, { "mmx1", 0xe1 }, { "mmx2", 0xe2 }, { "mmx3", 0xe3 },
	{ "mmx4", 0xe4 }, { "mmx5", 0xe5 }, { "mmx6", 0xe6 }, { "mmx7", 0xe7 },

	/* 128-bit xmm regs */
	{ "xmm0", 0xf0 }, { "xmm1", 0xf1 }, { "xmm2", 0xf2 }, { "xmm3", 0xf3 },
	{ "xmm4", 0xf4 }, { "xmm5", 0xf5 }, { "xmm6", 0xf6 }, { "xmm7", 0xf7 },
	{ "xmm8", 0xf8 }, { "xmm9", 0xf9 }, { "xmm10", 0xfa }, {"xmm11", 0xfb},
	{ "xmm12", 0xfc }, { "xmm13", 0xfd }, {"xmm14", 0xfe}, {"xmm15", 0xff},	

	/* segment regs */
	{"es", 0xa0}, {"cs", 0xa1}, {"ss", 0xa2}, 
	{"ds", 0xa3}, {"fs", 0xa4}, {"gs", 0xa5},

	/* control regs */
	{ "cr0", 0xc0 }, { "cr1", 0xc1 }, { "cr2", 0xc2 }, { "cr3", 0xc3 },
	{ "cr4", 0xc4 }, { "cr5", 0xc5 }, { "cr6", 0xc6 }, { "cr7", 0xc7 },
	{ "cr8", 0xc8 }, { "cr9", 0xc9 }, { "cr10", 0xca }, { "cr11", 0xcb },
	{ "cr12", 0xcc }, { "cr13", 0xcd }, { "cr14", 0xce }, { "cr15", 0xcf },

	/* debug regs */
	{ "dr0", 0xd0 }, { "dr1", 0xd1 }, { "dr2", 0xd2 }, { "dr3", 0xd3 },
	{ "dr4", 0xd4 }, { "dr5", 0xd5 }, { "dr6", 0xd6 }, { "dr7", 0xd7 },
	{ "dr8", 0xd8 }, { "dr9", 0xd9 }, { "dr10", 0xda }, { "dr11", 0xdb }, 
	{ "dr12", 0xdc }, { "dr13", 0xdd }, { "dr14", 0xde }, { "dr15", 0xdf },

	/* end flag */
	{ 0, 0 }
};

/******************************************************/
oseg_t osegs[] = {
	{ "cs", 0x2e }, { "ds", 0x3e }, { "es", 0x26 },
	{ "fs", 0x64 }, { "gs", 0x65 }, { "ss", 0x36 },
	/* end flag */
	{ 0, 0 }
};

scale_t scales[] = {
	{ "1", 0x10 }, { "2", 0x21 }, { "4", 0x42 }, { "8", 0x83 },
	{ 0, 0 } /* end flag */
};


cast_t casts[] = {
	{ "byte", 8 }, { "word", 16 }, { "dword", 32 }, { "qword", 64 },
	{ "near", NEAR_ID }, { "far", FAR_ID },
	{ 0, 0 } /* end flag */
};

i_prefix_t i_prefixs[] = {
	{ "lock", 0xf0 }, { "rep", 0xf3 }, { "repe", 0xf3 },
	{ "repz", 0xf3 }, { "repne", 0xf2 }, { "repnz", 0xf2 },
	{ 0, 0 }
};

/******************************************************************/

keyword_t keyword[] = {
	{ "mode", KW_MODE }, { "bits", KW_BITS },
	{ "org", KW_ORG },
	{ "byte", KW_BYTE }, { "word", KW_WORD },
	{ "dword", KW_DWORD }, { "qword", KW_QWORD },
	{ "dqword", KW_DQWORD }, { "ptr", KW_PTR },
	{ "const", KW_CONST }, { "function", KW_FUNCTION },
	{ "var", KW_VAR }, { "macro", KW_MACRO },
	{ "text", KW_TEXT }, { "code", KW_CODE },
	{ 0, 0 }
};

bitmode_t modes[] = {
	{ "long.64", 64 }, { "long.compatibility", 32 },
	{ "protected", 32 }, { "v86", 16 }, { "real", 16 },
	{ 0, 0 }
};

bits_t bits[] = {
	{ "16", 16 }, { "32", 32 }, { "64", 64 },
	{ 0, 0 }
};


/************************************************************/


/***** 	a64 gloabl variable *****/          
unsigned int current_mode = LONG_64;
unsigned int current_bits = 64;
unsigned long long current_pc = 0;
unsigned long long org = 0;
unsigned long line = 0;


e_key_t *e_key_link = 0;

/*
 *	a64.h's function 
 */

/* the memcpy of a64 */
#define do_mem_copy(dest, src, size)			\
	asm("movl %0, %%edi; movl %1, %%esi;		\
		movl %2, %%ecx; movl %%ecx, %%eax;	\
		shr $2, %%ecx; rep movsl;		\
		movl %%eax, %%ecx; andl $3, %%ecx;	\
		rep movsb"				\
		:					\
		: "r" (dest), "r" (src), "r" (size)	\
	);

#define do_mem_zero(ptr, size)			\
	asm("movl %0, %%edi; movl %1, %%ecx;	\
		xorl %%eax, %%eax; rep stosb"	\
		:				\
		: "r" (ptr), "r" (size)		\
	);	



__inline__ void mem_copy(void *dest, void *src, unsigned int size)
{
	do_mem_copy(dest, src, size);
}


__inline__ void mem_zero(void *ptr, unsigned int size)
{
	do_mem_zero(ptr, size);
}



void *a64_malloc(unsigned int size)
{
	void *ptr = (void *)malloc(size);

	if (!ptr) {
		printf("error! no enought memory\n");	
		release_resource();		
		exit(1);
	}

	mem_zero(ptr, size);

	return ptr;
}

void a64_free(void *ptr)
{
	free(ptr);
}



int str_cmp(char *d, char *s) 
{
	if (!d || !s)
		return 0;
	while (*d && *d == *s) {
		d++; s++;
	}
		
	return ((*d == *s) && (*(d-1) == *(s-1)));
}

int str_len(char *s) 
{
	char *p = s;
	if (!p) return 0;
	while (*p) p++;
	return p - s;
}

int str_cat(char *d, char *s)
{
	char *p = d;
	if (!d || !s) return 0;
	
	while (*d) d++;
	while (*s) *d++ = *s++;
	return d - p;
}


/******************************************************
*******************************************************/
int trim_space(char *d, char *s)
{
	if (!d || !s || !s[0]) 
		return 0;

	int i = 0, j = 0;
	char *p = s;
	char *q = s;

	while (*s) {
		if (*s != ' ') 
			*d++ = *s++;
		else if (s == p) {	/* head */
			while (*s && (*s == ' ')) s++;
		} else {
			q = s - 1;
			while (*s && (*s == ' ')) s++;
			if ((is_c(*q) || is_n(*q)) && (is_c(*s) || is_n(*s)))
				*d++ = ' ';
		}
	}
	*d = 0;

	return 1;
}


int get_c(char *s, char c) 
{
	int ret = 0;
	
	while (*s) {
		ret += (*s == c);
		s++;
	}

	return ret;
}



int is_c(char c) {
	return (((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')));
}

int is_n(char c) {
	return ((c >= '0') && (c <= '9'));
}

int is_hc(char c) {
	return (((c >= 'a') && (c <= 'f')) || ((c >= 'A') && (c <= 'F')));
}


int is_dec(char *s) {
	if (!s) return 0;
	while (*s) {
		if (!(*s >= '0' && *s <= '9'))
			return 0;
		s++;
	}
	return 1;
}


int is_hex(char *s) {
	if (!s) return 0;

	if ((*s == '0') && (*(s+1) == 'x' || *(s+1) == 'X')) 
	{
		s += 2;

		while (*s) {
			if (!(is_n(*s) || is_hc(*s)))
				return 0;
			s++;
		}	
	} else if ((*s == '0') && is_hc(*(s+1))) {
		s += 2;
		while (*s) {
			if (!(is_n(*s) || is_hc(*s)))
				break;
			s++;
		}
		if (*s == 0) 
			return 0;
		if ((*s == 'h' || *s == 'H') && (*(s+1) == 0))
			return 1;
	} else 
		return 0;

	return 1;
}

int is_binary(char *s) {
	if (!s) return 0;
	while (*s && (*s == '0' || *s == '1')) 
		s++;
	if (*s == 0)
		return 0;
	else if ((*s == 'b' || *s == 'B') && (*(s+1) == 0))
		return 1;
	else 
		return 0;

	return 1;
}




int is_numeric(char *s) {
	int ret = 0;

	if (!s) return 0;
	
	if (is_c(*s))
		return 0;

	if (!(ret = is_hex(s)))
		if (!(ret = is_dec(s)))
			ret = is_binary(s);

	return ret;
}



int get_sizeof(long long n) 
{
	int ret = 0;
	
	if (n < 0)
		n = -n;

	union {
		long long ll;
		long l[2];
		char c[4];
	} u;
	u.ll = n;

/*
	if (n) {
		if (u.l[1])
			ret = 8;
		else if (n <= 0xff)
			ret = 1;
		else if (n <= 0xffff)
			ret = 2;
		else if (n <= 0xffffffff)
			ret = 4;
	} 
*/
	if (n) {
		if (u.l[1])
			ret = 8;

		else if (u.c[3] || u.c[2])
			ret = 4;

		else if (u.c[1])
			ret = 2;

		else if (u.c[0])
			ret = 1;
	} else
		ret = 1;
	

	return ret;
}


/* ----------------------------------------------- */

unsigned char get_regid(char *s) 
{
	reg_t *p = regs;
	
	if (!s || !s[0])
		return 0;

	while (p->reg && !str_cmp(s, p->reg))
		p++;

	return p->reg_id;
}


unsigned char get_osegid(char *s) 
{
	oseg_t *p = osegs;
	
	if (!s || !s[0])
		return 0;

	while (p->oseg && !str_cmp(s, p->oseg))
		p++;
	
	return p->oseg_id;
}

unsigned char get_scaleid(char *s) 
{
	scale_t *p = scales;

	if (!s || !s[0])
		return 0;

	while (p->scale && !str_cmp(s, p->scale))
		p++;
	
	return p->scale_id;
}

unsigned char get_castid(char *s) 
{
	cast_t *p = casts;

	if (!s || !s[0]) 
		return 0;
	
	while (p->cast && !str_cmp(s, p->cast))
		p++;

	return p->cast_id;
}


unsigned char get_prefixid(char *s)
{
	i_prefix_t *p = i_prefixs;

	if (!s || !s[0])
		return 0;

	while (p->prefix && !str_cmp(s, p->prefix))
		p++;

	return p->prefix_id;
}


unsigned char get_modeid(char *s) 
{
	bitmode_t *p = modes;

	if (!s || !s[0])
		return 0;

	while (p->mode && !str_cmp(s, p->mode))
		p++;

	return p->mode_id;
}

unsigned char get_bitsid(char *s)
{
	bits_t *p = bits;

	if (!s || !s[0])
		return 0;

	while (p->bits && !str_cmp(s, p->bits))
		p++;

	return p->bits_id;
}

/*************************************************************/
int check_cast(unsigned char cast)
{
	if (cast == NEAR_ID || cast == FAR_ID) {
		/* it's transfer cast */
	} else if (cast && (current_bits == 64)) {
	} else if (!cast || cast == 64)
		return 0;
		
	return 1;
}


int check_oseg(unsigned char oseg)
{
	if (oseg && (current_bits != 64)) { 
		/* 32-bit */
	} else if (!oseg || (oseg == 0x2e) || (oseg ==  0x3e) || 
			(oseg == 0x26) || (oseg == 0x36))
		/* in 64-bit mode: the CS,DS,ES and SS is invalid */
		return 0;

	return 1;
}

/*****************************************
 check register is GPR
*****************************************/
/*
int is_GPR(unsigned char regid)
{
	return regid && ((regid & 0xf0) < 0xa0);
}
*/
// #define is_GPR(regid)	((regid) && ((regid & 0xf0) < 0xa0))

/*
int is_eGPR(unsigned char regid)
{
	return regid && ((regid & 0xf0) == 0x80);
}
*/

// #define is_eGPR(regid)	((regid) && ((regid & 0xf0) == 0x80))


int get_reg_size(unsigned char regid)
{
	int reg_size = 0;

	if (is_GPR(regid))
		reg_size = (regid & 0xf0) >> 1;	
	else if ((regid & 0xf0) == 0xa0)	/* segment register */
		reg_size = 16;
	else if ((regid & 0xf0) == 0xc0)	/* control register */
		reg_size = 16;
	else if ((regid & 0xf0) == 0xd0)	/* debug register */
		reg_size = 16;
	else if ((regid & 0xf0) == 0xe0)	/* mmx register */
		reg_size = 64;
	else if ((regid & 0xf0) == 0xf0)	/* xmm register */
		reg_size = 128;
	
	return reg_size;
}


/**************************************************
 the funtion check base or index register
***************************************************/
int check_mreg(unsigned char regid)
{
	if (!regid || ((regid & 0xF0) == 0x10))	/* 1-byte register */
		return 0;
	else if ((regid & 0xF0) >= 0xa0)	/* not GPR */
		return 0;
	else if ((regid & 0xF0) == 0x20) {	/* 2-byte register */
		/* it's 16-bit address mode */
		/* in 64-bit mode: not support 16-bit address */
		if (current_bits == 64)
			return 0;
		/* in 32-bit mode: 16-bit address base register 
		   only support bx, bp, si and di register */
		else if (regid == BX || regid == BP || regid == SI 
			|| regid == DI) {
			/* at 32-bit or 16-bit... OK */
		} else 
			return 0;
	} else if ((regid == ESP) || (regid == RSP)) {
		
		/* 32-bit address or 64-bit address is OK */
		
	}

	return 1;
}

/*********************************************************
 check the string is var ????
**********************************************************/
int check_var(char *s)
{
	return 1;
}


/************************************************************/
kw_id_t get_keyword(char *s) {
	 keyword_t *p = keyword;

	if (!s) return 0;
	
	while (p->keyword && !str_cmp(p->keyword, s)) 
		p++;

	return p->keyword_id;
}


long long strd_to_n(char *s) {
	long long retval = 0;
	while (*s)
		retval = retval * 10 + (*s++ - '0');
	return retval;
}

long long strh_to_n(char *s) {
	long long retval = 0;
	int i = 0;

	s++;
	if (*s == 'x' || *s == 'X') {
		s++;
		while (*s) {
			if (is_n(*s))
				i = *s - '0';
			else if (is_hc(*s))
				i = *s - 'a' + 10;
			else
				return 0;
			retval = retval * 16 + i;
			s++;
		}
	} else {
		while (*s) {
			if (*s == 'h' || *s == 'H')
				break;
			if (is_n(*s))
				i = *s - '0';	
			else if (is_hc(*s))
				i = *s - 'a' + 10;
			else
				return 0;
			retval = retval * 16 + i;
			s++;
		}
	}

	return retval;
}

long long strb_to_n(char *s) {
	long long retval = 0;

	while (*s) {
		if (*s == 'b' || *s == 'B')
			break;
		retval = retval * 2 + (*s - '0');
		s++;
	}
	return retval;
}


long long str_to_n(char *s) 
{
	long long retval = 0;

	if (!s || !s[0]) return 0;

	if (is_hex(s)) 
		retval = strh_to_n(s);
	else if (is_dec(s))
		retval = strd_to_n(s);
	else if (is_binary(s))
		retval = strb_to_n(s);
	else
		return 0;

	return retval;
}





/***********************************************************
 *  i_key_t *get_i_key(char *s)
 *  return value: i_key if found
 *                  0   if no found
************************************************************/
i_key_t *get_ins(char *s)
{
	if (!s || !s[0])
		return 0;

	i_set_t *p = i_set;
	
	while (p->mnemonic && !str_cmp(s, p->mnemonic)) 
		p++;

	return p->i_key;

}

i_key_t *get_transfer_ins(char *s)
{
	if (!s || !s[0])
		return 0;

	i_set_t *p = i_transfer;

	while (p->mnemonic && !str_cmp(s, p->mnemonic))
		p++;

	return p->i_key;
}


int is_string_ins(i_key_t *ins_key)
{
	if (ins_key == CMPSB) {
	} else if (ins_key == CMPSW) {
	} else if (ins_key == CMPSD) {
	} else if (ins_key == CMPSQ) {
	} else if (ins_key == SCASB) {
	} else if (ins_key == SCASW) {
	} else if (ins_key == SCASD) {
	} else if (ins_key == SCASQ) {
	} else if (ins_key == MOVSB) {
	} else if (ins_key == MOVSW) {
	} else if (ins_key == MOVSD) {
	} else if (ins_key == MOVSQ) {
	} else if (ins_key == LODSB) { 
	} else if (ins_key == LODSW) { 
	} else if (ins_key == LODSD) {
	} else if (ins_key == LODSQ) {
	} else if (ins_key == STOSB) {
	} else if (ins_key == STOSW) {
	} else if (ins_key == STOSD) {
	} else if (ins_key == STOSQ) {
	} else
		return 0;

	return 1;
}


int is_transfer_ins(i_key_t *ins_key)
{
	if (ins_key == JMP) {
	} else if (ins_key == CALL) {
	} else if (ins_key == JO) { 
	} else if (ins_key == JNO) {
	} else if (ins_key == JB) {
	} else if (ins_key == JNB) {
	} else if (ins_key == JZ) {
	} else if (ins_key == JNZ) {
	} else if (ins_key == JBE) { 
	} else if (ins_key == JNBE) {
	} else if (ins_key == JS) {
	} else if (ins_key == JNS) {
	} else if (ins_key == JP) { 
	} else if (ins_key == JNP) {
	} else if (ins_key == JL) {
	} else if (ins_key == JNL) {
	} else if (ins_key == JLE) {
	} else if (ins_key == JNLE) {
	} else if (ins_key == LOOP) {
	} else if (ins_key == LOOPZ) {
	} else 
		return 0;

	return 1;
}

int is_imul_ins(i_key_t *i_key) 
{
	int ret = 0;
	if ((i_key >= IMUL) && (i_key < (IMUL + sizeof(IMUL))))
		ret = 1;
	return ret;
}


/****************************************************************/
i_key_t *get_i_key(i_key_t *i_key, ops_attr_t *ops_attr)
{
	if (!i_key || !ops_attr)
			return 0;

	unsigned int i_attr = 0;
	unsigned int i_so_attr = 0;
	unsigned int i_do_attr = 0;
	unsigned int i_to_attr = 0;
	
	unsigned int so_attr = ops_attr->so_attr;
	unsigned int do_attr = ops_attr->do_attr;
	unsigned int to_attr = ops_attr->to_attr;

	
	while (i_key->opcode || i_key->i_attr) {

		i_attr = i_key->i_attr;
		i_so_attr = i_key->so_attr;
		i_do_attr = i_key->do_attr;
		i_to_attr = i_key->to_attr;


		if (((i_so_attr == 0) && (so_attr != 0))
			|| ((i_so_attr != 0) && (so_attr == 0))
			|| ((i_do_attr == 0) && (do_attr != 0))
			|| ((i_do_attr != 0) && (do_attr == 0))
			|| ((i_to_attr == 0) && (to_attr != 0))	
			|| ((i_to_attr != 0) && (to_attr == 0))) 
		{
			i_key++;
			continue;
		}

/*

		if (((OPTYPE(i_so_attr) == 0) && (OPTYPE(so_attr) != 0)) 
			|| ((SIZE(i_so_attr) == 0) && (SIZE(so_attr) != 0)) 
			|| ((OPTYPE(i_so_attr) != 0) && (OPTYPE(so_attr) == 0))
			|| ((SIZE(i_so_attr) != 0) && (SIZE(so_attr) == 0))

			|| ((OPTYPE(i_do_attr) == 0) && (OPTYPE(do_attr) != 0))
			|| ((SIZE(i_do_attr) == 0) && (SIZE(do_attr) != 0))
			|| ((OPTYPE(i_do_attr) != 0) && (OPTYPE(do_attr) == 0))
			|| ((SIZE(i_do_attr) != 0) && (SIZE(do_attr) == 0))

			|| ((OPTYPE(i_to_attr) == 0) && (OPTYPE(to_attr) != 0))
			|| ((SIZE(i_to_attr) == 0) && (SIZE(to_attr) != 0))
			|| ((OPTYPE(i_to_attr) != 0) && (OPTYPE(to_attr) == 0))
			|| ((SIZE(i_to_attr) != 0) && (SIZE(to_attr) == 0)))
		{
			i_key++;
			continue;
		}

*/

		if (((so_attr & i_so_attr) == so_attr) 
	   	   && ((do_attr & i_do_attr) == do_attr)
		   && ((to_attr & i_to_attr) == to_attr))
		{
			if (current_bits == 64) {
				if (is_INVLD_IN_64(i_attr)) {
					i_key++;
					continue;
				}
			}

			if (is_FS_64(i_attr) && (current_bits != 64)) {
				i_key++;
				continue;
			}
			

			return i_key;
		}

		i_key++;
	}
		
	return 0;
}



/*********************************************************/
static void release_o_key(o_key_t *o_key)
{
	if (o_key->mem)
		a64_free(o_key->mem);
	
	if (o_key->imme)
		a64_free(o_key->imme);

	a64_free(o_key);
}


static void release_ops_key(ops_key_t *ops_key)
{
	if (ops_key->so_key)
		release_o_key(ops_key->so_key);
	
	if (ops_key->do_key)
		release_o_key(ops_key->do_key);	

	if (ops_key->to_key)
		release_o_key(ops_key->to_key);

	a64_free(ops_key);
}


static void release_e_key(e_key_t *e_key)
{
	if (e_key) {
		if (e_key->ops_key)
			release_ops_key(e_key->ops_key);
/*
	e_key->i_key it's not need malloc()!!!
*/
		if (e_key->i_prefix)
			a64_free(e_key->i_prefix);
	}

	a64_free(e_key);
}



static void release_e_key_link()
{
	e_key_t *e_key_next;

	while (e_key_link) {
		e_key_next = e_key_link->next;
		release_e_key(e_key_link);
		e_key_link = e_key_next;
	}
}

void release_resource()
{
	release_e_key_link();
	release_label_table();
	release_hole_link();
	release_err_link();
}

void reset_environment()
{
	current_mode = LONG_64;
	current_bits = 64;
	current_pc = 0;
	line = 0;
	org = 0;
}