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

📄 gen.c

📁 Intel x86处理器的汇编器
💻 C
📖 第 1 页 / 共 3 页
字号:
#include <stdio.h>#include "generate.h"#include "operand.h"#include "label.h"extern hole_pos_t *hole_link;static unsigned long offset = 0;static char err_msg[80];/****************************************************************** function unsigned char get_16modrm(mem_t *mem)last change: 02-19-2006 21:45 by mik*******************************************************************/unsigned char get_16modrm(mem_t *mem, int *is_sib, int *set_disp){	unsigned char modrm = 0;	unsigned int size = mem->disp ? get_sizeof(mem->disp) : 0;			/* 16-bit memory operand only set MOD field and R/M field */	if (mem) {		if (!mem->base && !mem->index && mem->disp) {			modrm |= 0x06;		} else switch (size) {		case 1: modrm |= 0x40; break;		case 2: modrm |= 0x80; break;		}			if (((mem->base == BX) && (mem->index == SI)) ||			(mem->base == SI && mem->index == BX))			modrm |= 0x0;		else if (((mem->base == BX) && (mem->index == DI)) ||			(mem->base == DI && mem->index == BX))			modrm |= 0x01;		else if (((mem->base == BP) && (mem->index == SI)) ||			(mem->base == SI && mem->index == BP))			modrm |= 0x02;		else if (((mem->base == BP) && (mem->index == DI)) ||			(mem->base == DI && mem->index == BP))			modrm |= 0x03;		else if ((mem->base == SI) && (!mem->index))			modrm |= 0x04;		else if ((mem->base == DI) && (!mem->index))			modrm |= 0x05;		else if (!mem->base && !mem->index && mem->disp) {			modrm |= 0x06;			if (size == 1)				*set_disp = 1; 	/* 1-byte 0 need */		} else if ((mem->base == BP) && !mem->index) {			if (size == 0) {				modrm |= 0x46;				*set_disp = 1;	/* 1-byte 0 need */			} else if (size == 1)				modrm |= 0x46;			else if (size == 2)				modrm |= 0x86;		} else if ((mem->base == BX) && (!mem->index))			modrm |= 0x07;	}	return modrm;}/******************************************************************* function: unsigned char get_modrm(e_key_t *e_key) parameter:           e_key: instruction key word. return: 	            modrm byte.last change: 02-19-2006 20:45 by miklast change: 02-19-2006 22:09 by mik********************************************************************/unsigned char get_modrm(e_key_t *e_key, int *is_sib, int *set_disp){	unsigned char modrm = 0;	mem_t *mem = 0;	unsigned char reg = 0;	ops_key_t *ops_key = e_key->ops_key;	unsigned int i_attr = e_key->i_key->i_attr;	ops_type_t ops_type = get_ops_type(ops_key);	unsigned int addr_size = get_ops_addr(ops_key);	switch (ops_type) {	case D_R|S_I:		/* 		  example: mov eax, 0xc 		  if the opcode is 0xC7, it's a group.	 	     so need to set group id at reg field of modrm !!!		     so skip break jmp next to do ...		  if the opcode is 0xB8, it's not need modrm byte		     so this not to do never !!!		  ****** It has not a SIB byte !!! ******		*/			case S_R:		/* only one register operand */		/* 		  example: inc eax		  if the opcode is 0xFF/0, it's a group.		     so need to set group id at reg field of modrm !!!		     so do this ....		  if the opcode is 0x40, it's not need modrm byte		     so this not to do never !!!		  ****** It has not a SIB byte !!! ******		*/		/* set MOD field of modrm byte */		reg = ops_key->so_key->reg ? ops_key->so_key->reg :			ops_key->do_key->reg ? ops_key->do_key->reg : 0;		modrm |= 0xc0;			/* set R/M field of modrm byte */		modrm |= reg & 0x07;		/* set REG field of modrm byte */		if (is_GROUP(i_attr)) {			/* example: call rax, inc rax, so that.... */			/* there have a group id 			  ******* the REG field is GROUP ID ****** 			*/			modrm |= (unsigned char)get_GROUPID(i_attr);		} else { 			/* example: setz al, setb al, so that ... 			  there are two opcodes, have not group id */			/* so not group set 			  ****** the REG field is 0 *****			*/		}		break;	case S_I:  break;			/* source operand is imme		   ****** so it has no modrm byte ******		 */	case T_R|D_M|S_I:			/*			the case for  IMUL Gv, Ev, Ev			example: imul edi, [si], 0x0c			in this case, the modrm's byte is same as D_M|S_R		*/	case D_M|S_R:		/* source operand is register, dest operand is memory 		   the reg field of modrm is register ID ...		   ****** it has not group id ... ******		*/	case D_R|S_M:		/* source operand is memory, dest operand is register		   the reg field of modrm is register ID ...		   ****** it has not group id ******		*/		reg = ops_key->so_key->reg ? ops_key->so_key->reg : 			ops_key->do_key->reg ? ops_key->do_key->reg : 			ops_key->to_key && ops_key->to_key->reg ?			ops_key->to_key->reg : 0;				/* 		   it's no group,so skip break jmp next step to do !!!		*/				/* set REG field of modrm */		modrm |= (reg & 0x07) << 3;	case D_M|S_I:	/* skip break jmp next step to do !!! */		/* example: mov [eax], 0xc => is group !!! */		/* skip reg field set for register ... it has a group */	case S_M:		/* modrm's REG field */		if (is_GROUP(i_attr))			/* example: call [eax] */			/* example: mov [eax], 0xc */			/* the REG field is GROUP ID */			modrm |= (unsigned char)get_GROUPID(i_attr);		else { /* example: setz (byte)[ecx] is no group */ }/*		mem = ops_key->so_key->mem ? ops_key->so_key->mem :			ops_key->do_key && ops_key->do_key->mem ?			ops_key->do_key->mem : 0;*/				unsigned int o_attr = 0;		if (ops_key->so_key->mem) {			mem = ops_key->so_key->mem;			o_attr = e_key->i_key->so_attr;		} else if (ops_key->do_key && ops_key->do_key->mem) {			mem = ops_key->do_key->mem;			o_attr = e_key->i_key->do_attr;		} else if (ops_key->to_key && ops_key->to_key->mem) {			/* this case never do */			mem = ops_key->to_key->mem;			o_attr = e_key->i_key->to_attr;		}		unsigned int size = mem->disp ? get_sizeof(mem->disp) : 0;		if (((mem->index == ESP) || (mem->index == RSP)) 			&& mem->base) 		{			/********************* NOTE: **********************			   if have a "esp" or "rsp" register of memory operand			   must set "esp" or "rsp" to base register !!!			   becase the X86-64 not support "esp" or "rsp" 				index register !!!			*****************************************************/			/* exchange base and index register */				/* example: mov [eax+esp],eax ==> mov [esp+eax],eax */			unsigned char c = mem->base;			mem->base = mem->index;			mem->index = c;		} else if (((mem->base == EBP) || (mem->base == RBP)) 				&& mem->index)		{			/********************* NOTE: **********************			 if base is "ebp" or "rbp" register of memory operand		         It's good choice that set "ebp" or "rbp" 				to index register !!!			 becase it's good idea !!!			***************************************************/			/* exchange base and index reister */			/* example: mov [ebp+eax],eax ==> mov [eax+ebp],eax */			unsigned char r = mem->index;			mem->index = mem->base;			mem->base = r;		} else if (((mem->base == EBP) || (mem->base == RBP)) 			&& !mem->index)		{			/* only base register is "ebp" or "rbp" */			/* must set disp for "ebp" base register */			if (size == 0) {				*set_disp = 1;	/* 1-byte 0 need */				modrm |= 0x40;	/* MOD field */			} else if (size == 2)				*set_disp = 2;		} else if (!mem->base && !mem->index && mem->disp) {			/* only memory offset value of memory operand */			/* [disp32] is 0x05 => r/m field of memory operand */			/* if base is 0, index is 0, and has a disp value 			      return 0x05 modrm byte ...			 *//*			if (SIZE(o_attr) == SIZE_V || is_FS_IN_BITS(i_attr))				*set_disp =  (current_bits >> 3) - 					get_sizeof(mem->disp);*/			*set_disp = (current_bits >> 3) - get_sizeof(mem->disp);			/******* It has not a SIB byte *******/			if (addr_size != 16) {				modrm |= 0x05;				return modrm;			}		}		if (addr_size == 16) {			modrm |= get_16modrm(mem, is_sib, set_disp);			*is_sib = 0;			break;		}		/* example: mov [ecx*4+0xc], 0xc */		if (mem->index && !mem->base) {			modrm |= 0x04;			if (size == 1)				*set_disp = 3;			else if (size == 2)				*set_disp = 2;		} else { 			/* modrm's MOD field */			if (size == 0) {				/* no disp */			} else if (size == 1) { 				/* disp8 */				modrm |= 0x40;			} else if (size == 2) {				/* disp32 */				modrm |= 0x80;				*set_disp = 2;	/* 2-byte 0 need */			} else {				/* disp32 */				modrm |= 0x80;			}			/* modrm's R/M field */			modrm |= mem->index ? 0x04 : mem->base & 0x07;		}		/*   			*** is SIB byte need ???  ***			 if base is "esp" or "rsp" register, then must set SIB byte !!!		    becase x86-64 not support esp register in MODRM byte !!!					 And if has a index register, then must set SIB byte !!!		*/		if ((mem->base == ESP) || (mem->base == RSP) || (mem->index))			*is_sib = 1;		break;	case D_R|S_R:		/* no group */		if (e_key->i_key->opcode == 0x0fb6) {			modrm |= 0xc0 | ops_key->so_key->reg & 0x07;			modrm |= (ops_key->do_key->reg & 0x07) << 3;		} else {			modrm |= 0xc0 | ops_key->do_key->reg & 0x07;			modrm |= (ops_key->so_key->reg & 0x07) << 3;		}		/*** has not a SIB byte ***/		break;	case T_R|D_R|S_I:		/* imul Gv,Ev,Iv */	case T_R|D_R|S_R:		/* shld Ev, Gv, CL */		modrm |= 0xc0 | ops_key->to_key->reg & 0x07;		modrm |= (ops_key->do_key->reg & 0x07) << 3;				break;	default: break;	} /**** end of switch ****/				return modrm;}/***************************************************************** function: unsigned char get_sib(e_key_t *e_key) parameter: last change: 02-19-2006 00:01 by mik*****************************************************************/unsigned char get_sib(e_key_t *e_key, int *set_disp){	unsigned char sib = 0;	ops_key_t *ops_key = e_key->ops_key;	mem_t *mem = ops_key->so_key && ops_key->so_key->mem ?		ops_key->so_key->mem : ops_key->do_key &&		ops_key->do_key->mem ? ops_key->do_key->mem :		ops_key->to_key && ops_key->do_key->mem ?		ops_key->to_key->mem : 0; 		if (mem && ((mem->base & 0xf0) != 0x20)) {		if (((mem->base == ESP) || (mem->base == RSP)) && mem->index)		{			/* example: mov (byte)[esp+eax], 0xc */			sib |= mem->base & 0x07;			sib |= (mem->index & 0x07) << 3;		} else if (((mem->index == ESP) || (mem->index == RSP))			&& mem->base) {			/* example: mov (byte)[eax+esp], 0xc */			sib |= mem->index & 0x07;			sib |= (mem->base & 0x07) << 3;		} else if (((mem->base == ESP) || (mem->base == RSP)) 			&& !mem->index) {			/* example: mov (byte)[esp], 0xc */			sib |= (mem->base & 0x07) | 0x20;		} else {			sib |= (mem->index & 0x07) << 3;			if (mem->base)				sib |= mem->base & 0x07;			else {				/* example: mov [ecx*4], ecx */				sib |= 0x05;				if (!mem->disp)					*set_disp = 4;			}		}		sib |= (mem->scale & 0x0f) << 6;	}	return sib;}/************************************************************** function: int get_disp(char *e_buf, e_key_t *e_key)**************************************************************/void get_disp(char *e_buf, e_key_t *e_key){	union {		long long ll;		char byte;		char word[2];		char dword[4];		char qdword[8];	} u;	mem_t *mem = 0;		if (e_key && e_key->ops_key)		if (e_key->ops_key->so_key && e_key->ops_key->so_key->mem)			mem = e_key->ops_key->so_key->mem;		else if (e_key->ops_key->do_key && e_key->ops_key->do_key->mem)			mem = e_key->ops_key->do_key->mem;		else if (e_key->ops_key->to_key && e_key->ops_key->to_key->mem)			mem = e_key->ops_key->to_key->mem;		if (mem) {		u.ll = mem->disp;

⌨️ 快捷键说明

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