⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gen.c

📁 Intel x86处理器的汇编器
💻 C
📖 第 1 页 / 共 3 页
字号:
		switch (get_sizeof(u.ll)) {		case 1:			e_buf[offset++] = u.byte; break;		case 2:			e_buf[offset++] = u.word[0];			e_buf[offset++] = u.word[1];			e_buf[offset++] = 0;			e_buf[offset++] = 0;			break;		case 4:			e_buf[offset++] = u.dword[0];			e_buf[offset++] = u.dword[1];			e_buf[offset++] = u.dword[2];			e_buf[offset++] = u.dword[3];			break;		case 8:			e_buf[offset++] = u.qdword[0];			e_buf[offset++] = u.qdword[1];			e_buf[offset++] = u.qdword[2];				e_buf[offset++] = u.qdword[3];			e_buf[offset++] = u.qdword[4];			e_buf[offset++] = u.qdword[5];			e_buf[offset++] = u.qdword[6];			e_buf[offset++] = u.qdword[7];		}		}}/********************************************************* function: errno_t do_generate(char *e_buf, e_key_t *e_key) parameter:            e_buf: this is encode memory buffer.           e_key: this is instruction encode key word link.***********************************************************/errno_t do_generate(char *e_buf, e_key_t *e_key){	errno_t errno = 0;	if (!e_buf || !e_key)		return ERR_ERROR;	unsigned long long priv_pc = current_pc;		offset = 0;	unsigned char rex = 0x40;	int is_sib = 0;	int set_disp = 0;		/* must set disp */	int set_imme = 0;	unsigned int to_attr = 0;	unsigned int do_attr = 0;	unsigned int so_attr = 0;	unsigned int i_attr = 0;	o_key_t *to_key = 0;	o_key_t *so_key = 0;	o_key_t *do_key = 0;	ops_key_t *ops_key = e_key->ops_key;	union {		unsigned short opcode;	/* two bytes opcode */		unsigned char code[2];	} u;		if (e_key->i_key) {		to_attr = e_key->i_key->to_attr;		do_attr = e_key->i_key->do_attr;		so_attr = e_key->i_key->so_attr;		i_attr = e_key->i_key->i_attr;		u.opcode = e_key->i_key->opcode;	}	if (ops_key) {		to_key = ops_key->to_key;		do_key = ops_key->do_key;		so_key = ops_key->so_key;	}	mem_t *mem = so_key && so_key->mem ? so_key->mem :		do_key && do_key->mem ? do_key->mem : 0;		to_key && to_key->mem ? to_key->mem : 0;		imme_t *imme = so_key && so_key->imme ? so_key->imme :		do_key && do_key->imme ? do_key->imme :			to_key && to_key->imme ? to_key->imme : 0;	int oattr_size = 0;	if (so_key) {		oattr_size = SIZE(so_attr);	} else if (do_key) {		oattr_size = SIZE(do_attr);		} else if (to_key) {		oattr_size = SIZE(to_attr);	}	unsigned int ops_size = get_ops_size(ops_key);	unsigned int addr_size = get_ops_addr(ops_key);	if (is_FS(i_attr))		ops_size = get_FS_SIZE(i_attr);/************************************************************************/	prefix_t *i_prefix = e_key->i_prefix; 	if (i_prefix) {			/* lock or rep prefix */		if (i_prefix->lock)			e_buf[offset++] = i_prefix->lock;		if (i_prefix->rep)			e_buf[offset++] = i_prefix->rep;	}	/************************************* 	 * size override prefix  	 * address override prefix	 * segment override prefix          *************************************/	/* segment override */	if (mem && mem->oseg)		e_buf[offset++] = mem->oseg;	/*******************************************************         * TODO: reserved for check instruction's attribute         *       -> to check instruction fixed-operand size         *       -> to check instruction default operand size	 *******************************************************/	/* size override */	if (is_NO_CAST(i_attr)) {		/* example: push es, push cs .... */		/* do nothing */	} else if (!so_key && !do_key && !to_key && !is_FS(i_attr)) { 		/*** no operands and no fix operand's size ***/		/* example: "nop", "ret", so that....*/			/* do nothing */	} else if (current_bits == 16) {  /* CPU's current mode is 16-bit */		if ((addr_size == 32) && !is_NO_CAST_ADDR(i_attr))			e_buf[offset++] = 0x67;		if ((ops_size == 32) && !is_NO_CAST_SIZE(i_attr))			e_buf[offset++] = 0x66;	} else if (current_bits == 32) { /* CPU's current mode is 32-bit */		if ((addr_size == 16) && !is_NO_CAST_ADDR(i_attr))			e_buf[offset++] = 0x67;		if ((ops_size == 16) && !is_NO_CAST_SIZE(i_attr))			e_buf[offset++] = 0x66;	} else if (current_bits == 64) { /* CPU's current mode is 64-bit */		if ((addr_size == 32) && !is_NO_CAST_ADDR(i_attr))			e_buf[offset++] = 0x67;				/*     more instruct in 64-bit mode to default 		   operand size is 32-bit				       so ops_size is 32-bit have not 0x66 byte */		if ((ops_size == 16) && !is_NO_CAST_SIZE(i_attr))			e_buf[offset++] = 0x66;		/* 64-bit mode not support to 16-bit address size 		   so addr_size is 16-bit have not 0x67 byte */		/******* set rex byte to get extern GPRs ***********/		if (ops_size == 64 || addr_size == 64 ||			((so_key && (so_key->reg & 0x08)) ||			(do_key && (do_key->reg & 0x08)) ||			(to_key && (to_key->reg & 0x08)))) 		{			/* set REX.W to extern 64-bit */			if (!is_DS_64(i_attr) && !is_FS_64(i_attr)					&& !is_FS_8(i_attr))				rex |= REX_W;				switch (get_ops_type(ops_key)) {			case S_R: 	/* register */		#if 0				if (is_GROUP(i_attr)) {					/* example "inc rcx" 					   it's GROUP,so set REX.B 					*/					if (so_key->reg & 0x08) 						rex |= REX_B;					} else { /* have not other insturction */ }		#endif				if (is_eGPR(so_key->reg))					rex |= REX_B;				break;			case S_M:	/* it's a memory */				/* it's not to extern 64-bit address */				if (addr_size != 64)					break;				if (mem->base && !mem->index) {			#if 0					if (is_GROUP(i_attr)) {						/* example: call [rcx] */						/* it's a GROUP,so set REX.B */ 						if (so_key->mem->base & 0x08)							rex |= REX_B;					} else { /* have not other */ }				#endif					if (is_eGPR(so_key->mem->base))						rex |= REX_B;				} else if (mem->index && !mem->base) {			#if 0					if (is_GROUP(i_attr)) {						if (mem->index & 0x08)							rex |= REX_X;					} else { /* have not oterh */}			#endif					if (is_eGPR(mem->index))							rex |= REX_X;				} else if (mem->base && mem->index) {			#if 0					if (is_GROUP(i_attr)) {						if (mem->base & 0x08)							rex |= REX_B;						if (mem->index & 0x08)							rex |= REX_X;						} else { }			#endif					if (is_eGPR(mem->base))						rex |= REX_B;					if (is_eGPR(mem->index))						rex |= REX_X;					} else if (mem->disp) {					/* example:call [0x1122334455667788] */					/* it's GROUP,so set REX.B */					if (is_GROUP(i_attr)) {						rex |= REX_B;					} else { /* have not other */ }								}				break;			case S_I: break; 	/* have not REX.B */			case D_R|S_R:	/* source is reg and dest is reg */ 				/* example: mov rax, rcx */				/* modrm: 					mod field = 11					reg field = REX_R + XXX					r/m field = REX_B + XXX				*/				if (is_eGPR(so_key->reg))					rex |= REX_R;				if (is_eGPR(do_key->reg))				 	rex |= REX_B;				break;			case D_R|S_M:			case D_M|S_R:				if (is_eGPR(so_key->reg) 						|| is_eGPR(do_key->reg))					rex |= REX_R;				if (addr_size != 64) {					/* example: mov rax, [ecx] */					/* the ops_size is 64-bit, but					   the addr_size is 32-bit.					   so not set to REX_B */					break;				}				/* example: mov rax, [rcx*8+rbx+0xc] */				/* REX_B: set for base reg */				/* REX_X: set for index reg */				if (is_eGPR(mem->base))					rex |= REX_B;				if (is_eGPR(mem->index))					rex |= REX_X;				break;				case D_R|S_I: 	/* dest is reg and source is imme */				/* example: mov rax, 0x0c */				/* register id in reg field of opcode byte 				   so, REX_R & REX_X are not used */				/* is GROUP set REX_B too !!! 				   example: mov ecx,0x00000001 				   if the opcode code is 0xC7/0...				   it's a GROUP, so set REX_B 				*/				if (is_eGPR(do_key->reg))					rex |= REX_B;				break;			case D_M|S_I:				/* ops_size is 64-bit,but addr_size 				   isn't 64-bit, so skip set REX */				if (addr_size != 64) 					break;								/* example: mov [rax+rcx], 0x0c 				   it's GROUP */				/* set REX_B for base reg */				/* set REX_X for index reg */					if (is_eGPR(mem->base))					rex |= REX_B;				if (is_eGPR(mem->index))					rex |= REX_X;								break;			default: break;					/***********************************   				 * TODO: reserved for three operands 				 ***********************************/			}						e_buf[offset++] = rex;		}	}	/*** prefix bytes ****/	/* opcode bytes */	if (u.code[1])		/* it's two bytes opcode */		e_buf[offset++] = u.code[1];	e_buf[offset++] = u.code[0];	/****************** modrm byte *******************/	/* example: inc eax         * it has not modrm byte          */	if (!is_NO_NEED_MODRM(i_attr)) {		e_buf[offset++] = get_modrm(e_key, &is_sib, &set_disp);	} else if (mem && !mem->base && !mem->index && mem->disp) {		/* example: mov eax, [0x1122] */		set_disp = (current_bits >> 3) - get_sizeof(mem->disp);	}	/* sib byte */	if (is_sib) {		e_buf[offset++] = get_sib(e_key, &set_disp);	}	/******** disp bytes *************/	union {		long long ll;		char byte[8];	} d;	d.ll = mem ? mem->disp : 0;	if (d.ll == 0) {		/* do nothing */	} else switch (get_sizeof(d.ll)) {	case 1:		e_buf[offset++] = d.byte[0];		break;	case 2:		e_buf[offset++] = d.byte[0];		e_buf[offset++] = d.byte[1];		break;	case 4:		e_buf[offset++] = d.byte[0];		e_buf[offset++] = d.byte[1];		e_buf[offset++] = d.byte[2];		e_buf[offset++] = d.byte[3];		break;	case 8:		e_buf[offset++] = d.byte[0];		e_buf[offset++] = d.byte[1];		e_buf[offset++] = d.byte[2];		e_buf[offset++] = d.byte[3];		if (!is_SUPPORT_VALUE64(i_attr)) {			fputs("warning: "				"the instruction not support 64-bit value,",				 stderr);			break;			}		e_buf[offset++] = d.byte[4];		e_buf[offset++] = d.byte[5];		e_buf[offset++] = d.byte[6];		e_buf[offset++] = d.byte[7];	}	for (; set_disp; set_disp--)		e_buf[offset++] = 0;	/************* imme bytes ********************/	d.ll = imme ? imme->imme_value : 0;	int imme_size = imme && imme->cast ? imme->cast >> 3 : 			d.ll ? get_sizeof(d.ll) : 0;		if (OPTYPE(so_attr) == IMME_1) { 	/* example: shl eax,1 */		/* do nothing */	} else if (imme) {		switch (imme_size) {		case 0:	/* imme operand is 0 */			if (imme->cast == 8) {				e_buf[offset++] = d.byte[0];				imme_size = 1;			} else if (imme->cast == 16) {				e_buf[offset++] = d.byte[0];				e_buf[offset++] = d.byte[1];				imme_size = 2;			} else if (imme->cast == 32) {				e_buf[offset++] = d.byte[0];					e_buf[offset++] = d.byte[1];				e_buf[offset++] = d.byte[2];				e_buf[offset++] = d.byte[3];				imme_size = 4;			} else if (imme->cast == 64) {				e_buf[offset++] = d.byte[0];				e_buf[offset++] = d.byte[1];				e_buf[offset++] = d.byte[2];				e_buf[offset++] = d.byte[3];				if (!is_SUPPORT_VALUE64(i_attr))					break;				e_buf[offset++] = d.byte[4];				e_buf[offset++] = d.byte[5];				e_buf[offset++] = d.byte[6];				e_buf[offset++] = d.byte[7];				imme_size = 8;			}			break;		case 1:			e_buf[offset++] = d.byte[0];

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -