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

📄 asmwriter.cpp

📁 当前支持 16-bit, 32-bit and 64-bit 的二进制文件
💻 CPP
字号:
// asmwriter.cpp
// Copyright (C) 2008 Willow Schlanger

#include "asmwriter.h"

#include <cstring>
#include <cstdio>

#ifdef _MSC_VER
#define STD
#else
#define STD std
#endif

namespace x86s
{

// This assumes s->encoding != 0xffffff.
void AsmWriter::disasm(char *dest, decode_state_t *s_t, const char *imm_t, const char *disp_t, U8 rel_t)
{
	//const char *strsreg[8] = {"es", "cs", "ss", "ds", "fs", "gs", "ss", "ds"};

	rel = rel_t;
	out = dest;
	s = s_t;
	imm = imm_t;
	disp = disp_t;

	// if insn is 'osz' sensitive, see if the encoding has any 'osz-sensitive arguments'.
	// if not, print o16/o32/o64 here if different from default mode.
	
	if(s->icode->lockrep == 1)
		write("lock ");
	
	if(insns[s->icode->insn].suffix.size == size_none_dsz && s->dsz != s->icode->osz)
	{
#if 0
		int i;
		for(i = 0; i < MAX_ARGS; ++i)
			if(arg_is_osz_sensitive(get_full_argsize(i)))
				break;
		if(i == MAX_ARGS)
#endif
		{
			if(s->icode->osz == argsize_16)
				write("o16 ");
			else
			if(s->icode->osz == argsize_32)
				write("o32 ");
			else
			if(s->icode->osz == argsize_64)
				write("o64 ");
		}
	}

	if(!special_insn())
	{
		if((const char *)(insn_strings[s->icode->insn]) == 0)
		{
			write("<unknown opcode>");
		}
		else
		{
			write((const char *)(insn_strings[s->icode->insn]));
			if(get_argtype_lo(encodings[s->encoding].argtype[0]) != argtype_void)
			{
				space();
				write_args();
			}
		}
	}
}

// *** I don't understand this imm_value thing. Figure it out for 64-bit support.
void AsmWriter::write_operand(int type, int size, int value, bool suppress_size, U8 imm_value)
{
	const char *strsize[4] = {"word", "dword", "qword", "xword"};
	const char *strsreg[8] = {"es", "cs", "ss", "ds", "fs", "gs", "ss", "ds"};
	// To do: add 64-bit register support.
	const char *regs8[8] = {"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"};
	const char *regs16[8] = {"ax", "cx", "dx", "bx", "sp", "bp", "si", "di"};
	const char *regs32[8] = {"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"};;

	if(get_argtype_lo(type) == argtype_reg)
	{
		switch(get_argtype_hi(type))
		{
			case argtypehi_reg_r:
			case argtypehi_reg_basecode:
				// *** add 64-bit support here.
				if(value < 0 || value > 8)
					write("<unknown>");
				else
				if(get_argsize_lo(size) == argsize_8)
					write(regs8[value]);
				else
				if(get_argsize_lo(size) == argsize_16)
					write(regs16[value]);
				else
				if(get_argsize_lo(size) == argsize_32)
					write(regs32[value]);
				else
					write("<unknown>");
				break;
			case argtypehi_reg_sr:
				if(value < 0 || value > 6)
					write("<unknown>");
				else
					write(strsreg[value]);
				break;
			case argtypehi_reg_cr:
				write("cr");
				out += STD::sprintf(out, "%d", value);
				break;
			case argtypehi_reg_dr:
				write("dr");
				out += STD::sprintf(out, "%d", value);
				break;
			default:
				write("<unknown>");
				break;
		}
		return;
	}
	else
	if(get_argtype_lo(type) == argtype_mem)
	{
		if(!suppress_size)
		{
			// fixme--how to describe structure sizes? fword, tword, whatever-word (!)
		
			if(get_argsize_lo(size) < 3)
			{
				write(strsize[get_argsize_lo(size)]);
				if(is_ctrlxfer() && get_argsize_hi(size) == argsize__end)
					write(" near");
			}
			else
			if(get_argsize_lo(size) == argsize_8)
				write("byte");
			else
				write("<unsupported size>");
			
			if(is_ctrlxfer())
			{
				if(get_argsize_hi(size) != argsize__end)
					write(" far");
			}
			else
			if(get_argsize_hi(size) != argsize__end)
			{
				write(":");
				if(get_argsize_hi(size) < 3)
					write(strsize[get_argsize_hi(size)]);
				else
				if(get_argsize_hi(size) == argsize_8)
					write("byte");
				else
					write("<unsupported size>");
			}
			
			write(" ");
		}
		type = get_argtype_hi(type);
		size = get_argsize_lo(size);
		
		if(type == argtypehi_mem_mem || type == argtypehi_mem_disp)
		{
		// --- begin memory code ---
				write("[");

				// write any segment register override.
				if(get_sreg() <= 5)
				{
					write(strsreg[get_sreg()]);
					write(":");
				}
				
				// write any size override, e.g. mov eax,[word 0x5555] in 32-bit mode.
				if(get_asz() != get_bits())
				{
					// bug fix from release 0.04: don't write size if it's an rm and there's a register.
					// the size of the register indicates the size.
					if(type == argtypehi_mem_disp || (get_ea_base() == -1 && get_ea_index() == -1))
					{
						write(strsize[get_asz()]);
						write(" ");
					}
					// end bug fix.
				}
				
				if(get_disp() != NULL)
				{
					write(get_disp());
				}
				else
				{
					bool need_plus = false;
					if(type == argtypehi_mem_mem)
					{
						// write ea.
						
						const char *base = NULL;
						const char *index = NULL;
						
						// fixme--add 64bit support here.

						if(get_asz() == argsize_16)
						{
							if(get_ea_base() != -1)
								base = regs16[get_ea_base()];
						}
						else
						{
							if(get_ea_base() != -1)
								base = regs32[get_ea_base()];
						}						

						if(get_asz() == argsize_16)
						{
							if(get_ea_index() != -1)
								index = regs16[get_ea_index()];
						}
						else
						{
							if(get_ea_index() != -1)
								index = regs32[get_ea_index()];
						}						
						
						if(base != NULL)
						{
							write(base);
							need_plus = true;
						}
						if(index != NULL)
						{
							need_plus = true;
							if(base != NULL)
								write("+");
							write(index);
							if(get_ea_scale() != 0)
								out += sprintf(out, "*%x", 1 << get_ea_scale());
						}		
					}
					
					// write disp here.
					// if need a minus, show it.
					// else, show + if need_plus is true.
					
					if(type == argtypehi_mem_mem && has_disp8())
					{
						if((get_disp64() & 0xff) < 0x80)
						{
							if(need_plus)
								write("+");
							out += sprintf(out, "0x%02x", get_disp64() & 0xff);
						}
						else
							out += sprintf(out, "-0x%02x", 0x100 - (get_disp64() & 0xff));
					}
					else
					// fixme--add 64-bit displacement support here.
					if((U4)(get_disp64()) != 0 || (get_ea_index() == -1 && get_ea_base() == -1) || (type == argtypehi_mem_disp))
					{
						if(need_plus)
							write("+");
						if(get_asz() == argsize_16)
							out += sprintf(out, "0x%04x", (U4)get_disp64());
						else
						if(get_asz() == argsize_32)
							out += sprintf(out, "0x%08x", (U4)get_disp64());
						else
							write("<unsupported displacement size>");
					}
				}
				
				write("]");
		// --- end memory code ---
		}
		else
			write("<unknown>");
	}
	else
	if(get_argtype_lo(type) == argtype_imm)
	{
		if(is_sx())
		{
			if(is_ctrlxfer())
			{
				if(is_jmp())
					write("short ");
			}
			else
				write("byte ");
		}
		else
		if(!suppress_size)
		{
			if(get_argsize_lo(size) < 3)
			{
				write(strsize[get_argsize_lo(size)]);
			}
			else
			if(get_argsize_lo(size) == argsize_8)
				write("byte");
			write(" ");
		}
		
		type = get_argtype_hi(type);
		size = get_argsize_lo(size);

		// fixme--add support for other sizes here.
		// note: sometimes size is argsize_32_16 etc. We handle
		// these specially.
		/*else
		{
			out += STD::sprintf(out, "<--bad size %d-->", size);
		}*/

		if(type == argtypehi_imm_implict8)
			imm_value = (value & 0xff);
		
		// now ok to use imm_value.
		// fixme--add 64-bit support.
		
		// fixme --  use 'imm' field here.
		
		if(get_imm() != NULL)
		{
			write(get_imm());
			return;
		}
		
		if(type == argtypehi_imm_rel)
		{
			imm_value += get_rel();
			// bugfix from version 0.03: and by 0xffff.
			if(get_osz() == argsize_16)
				imm_value &= 0xffff;
		}
		
		if(is_sx() && !is_ctrlxfer())
		{
			if((imm_value & 0xff) < 0x80)
				out += sprintf(out, "+0x%02x", imm_value & 0xff);
			else
				out += sprintf(out, "-0x%02x", 0x100 - (imm_value & 0xff));
		}
		else
			do_write_imm(size, imm_value);
		
		return;
	}
	else
	if(get_argtype_lo(type) != argtype_void)
	{
		write("<unknown>");
	}
	
	return;
}

// ---

//#include "../x86c/x86c_insn_enums.h"

void NasmWriter::write_size()
{
	if(get_osz() != get_bits())
	{
		if(get_osz() == argsize_16)
			write("o16 ");
		else
		if(get_osz() == argsize_32)
			write("o32 ");
		else
			write("o64 ");
	}
}

// returns true if it was a special instruction.
bool NasmWriter::special_insn()
{
	if(insn_strings[get_insn()] != 0)
		return false;
	switch(get_insn())
	{
#include "../x86s/out_disassemble.h"
		default:
			write("<unknown>");
			return false;
	}
	return true;
}

}	// namespace x86s

⌨️ 快捷键说明

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