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

📄 asmwriter.h

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

#ifndef l_crudasm__asmwriter_h__included
#define l_crudasm__asmwriter_h__included

#include "../x86s/types.h"
#include "../x86s/x86s_common.h"
#include "../x86s/x86s_decode.h"

#include <cstdio>

namespace x86s
{

class AsmWriter
{
	char *out;
	decode_state_t *s;
	const char *imm;
	const char *disp;
	U8 rel;

	public:
	void disasm(char *dest, decode_state_t *s, const char *imm, const char *disp, U8 rel_t);
	protected:
	virtual bool special_insn() = 0;
	U4 get_insn() { return s->icode->insn; }
	U2 basecode() { return s->basecode; }
	void write(const char *s)
	{
		while(*s != '\0')
		{
			*out = *s;
			++s;
			++out;
		}
		*out = '\0';
	}
	void space()
	{
		// bug fix from release 0.04: change \t to two spaces.
		write("  ");
	}
	void comma()
	{
		write(",");
	}
	const char *get_imm() { return imm; }
	const char *get_disp() { return disp; }
	U4 get_rel() { return rel; }
	bool is_sx() { return encodings[s->encoding].suffix.sx != sx_def;  }
	bool is_ctrlxfer() { return insns[s->icode->insn].suffix.ctrlxfer == ctrlxfer_yes; }
	bool is_jmp() { return s->icode->insn == insn_jmp; }
	int get_osz()
	{
		return s->icode->osz;
	}
	int get_asz()
	{
		return s->icode->asz;
	}
	int get_dsz()
	{
		return s->dsz;
	}
	void write_arg(int arg)
	{
		// Do not write operand size if endcoding's operand has size 'osz'
		// and a register argument also exists with size 'osz'. For immediates
		// with size osz, do not write operand size if a memory argument
		// exists also with size osz. This handles these general cases:
		// OP reg,mem/imm -> OP reg,<no size> mem/imm
		// OP mem/imm,reg -> OP <no size> mem/imm.reg
		// OP mem,imm     -> OP mem,<no size> imm
		// Thus  jmp target -> jmp dword target (for example).
		// Note: this will not suppress e.g. 'add byte [eax],al'.
		bool suppress = false;
		
		if(insns[s->icode->insn].suffix.size == size_none ||
			insns[s->icode->insn].suffix.size == size_none_dsz
		)
			suppress = true;
		
		U8 imm_value = (U8)s->icode->imm | ((U8)s->icode->disp << (U8)32);
		bool has_reg = false;
		for(int i = 0; i < MAX_ARGS; ++i)
		{
			if(get_argtype_lo(encodings[s->encoding].argtype[i]) == argtype_reg)
			{
				has_reg = true;
				break;
			}
		}
		for(int i = 0; i < arg; ++i)
		{
			if(get_argtype_lo(encodings[s->encoding].argtype[i]) == argtype_imm)
			{
				// this argument is the second immediate argument - use displacement.
				i = arg;
				imm_value = s->icode->disp;		// fixme--check this!
			}
		}
		
		if(get_argtype_lo(encodings[s->encoding].argtype[arg]) == argtype_imm)
		{
			if(insns[s->icode->insn].suffix.size == size_same)
				suppress = true;
			// if this is a ctrl xfer, suppress default size.
			//if(is_ctrlxfer() && get_osz() == get_dsz())
			//	suppress = true;
		}
		
		if(!suppress)
		{
			if(insns[s->icode->insn].suffix.size == size_same)
				if(has_reg)
					suppress = true;
		}
		
		//write_operand((UINT)(U1)encodings[s->encoding].argtype[arg], encodings[s->encoding].argsize[arg], argvalue(arg), suppress, imm_value);
		write_operand(s->icode->argtype[arg], s->icode->argsize[arg], argvalue(arg), suppress, imm_value);
	}
	void write_args()
	{
		for(int i = 0; i < 3; ++i)
		{
			if(get_argtype_lo(encodings[s->encoding].argtype[i]) == argtype_void)
				break;
			if(i != 0)
				comma();
			write_arg(i);
		}
	}
	void write_suffix(int size)
	{
		if(size == argsize_8)
			write("b");
		else
		if(size == argsize_16)
			write("w");
		else
		if(size == argsize_32)
			write("d");
		else
			write("q");
	}
	void write_cc(int value)
	{
		//const char *cc[] = {"o","no","b","nb","z","nz","be","nbe","s","ns","p","np","l","nl","le","nle"};
		// These cc's are the ones that make the most sense sense to me.
		//const char *cc[16] = {"o","no","b","ae","e","ne","be","a","s","ns","p","np","l","ge","le","g"};
		const char *cc[16] = {"o","no","c","nc","z","nz","be","a","s","ns","p","np","l","ge","le","g"};
		write(cc[value]);
	}
	int get_sreg()
	{
		return s->icode->ea.sreg;
	}
	int get_ea_base()
	{
		if(s->icode->ea.base == 31)
			return -1;
		return s->icode->ea.base & 15;
	}
	int get_ea_index()
	{
		if(s->icode->ea.index == 31)
			return -1;
		return s->icode->ea.index & 15;
	}
	int get_ea_scale()
	{
		return s->icode->ea.index_scale & 3;
	}
	bool has_disp8()
	{
		return s->icode->ea.disp8;
	}
	// Ignore the upper 32 bits of this unless asz is size_64.
	U8 get_disp64()
	{
		return (U8)(s->icode->disp) | ((U8)(s->icode->imm) << (U8)(32));
	}
	// Ignore the upper 32 bits of this unless osz is size_64 (and you really
	// know what you're doing!)
	U8 get_imm64()
	{
		return (U8)(s->icode->imm) | ((U8)(s->icode->disp) << (U8)(32));
	}
	int get_bits()
	{
		return s->dsz & 3;
	}
	int argsize_lo(int arg) { return (int)(unsigned)get_argsize_lo(s->icode->argsize[arg]); }
	//int get_full_argsize(int arg) { return (int)(unsigned)s->icode->argsize[arg]; }
	U1 argvalue(int arg) { return s->icode->argvalue[arg]; }
	void write_operand(int type, int size, int value, bool suppress_size = false, U8 imm_value = 0);
	
	// --- begin new things ---
	void write_seg_reg()
	{
		const char *mysreg[6] = {"es", "cs", "ss", "ds", "fs", "gs"};
		if(s->icode->ea.sreg < 6)
		{
			write(mysreg[s->icode->ea.sreg]);
			write(" ");
		}
	}
	void write_rep()
	{
		if(s->icode->lockrep == 2 || s->icode->lockrep == 3)
			write("rep ");
	}
	void write_repcc()
	{
		if(s->icode->lockrep == 2)
			write("repnz ");
		else
		if(s->icode->lockrep == 3)
			write("repz ");
	}
	void write_byte_size(int s)
	{
		if(s == argsize_16)
			write("word");
		else
		if(s == argsize_32)
			write("dword");
		else
		if(s == argsize_64)
			write("qword");
		else
		if(s == argsize_128)
			write("xword");
		else
		if(s == argsize_8)
			write("byte");
		else
			write("<unsupported size>");
	}
	void write_far(bool is_imm = false)
	{
		if(is_imm)
		{
			write_byte_size(s->icode->osz);
			write(" ");
		}
		else
		{
			if(s->icode->osz != s->dsz)
			{
				write_byte_size(s->icode->osz);
				write(" ");
			}
			write("far ");
		}
	}
	void do_write_imm(int size, U8 imm_value)
	{
		if(size == argsize_8)
		{
			out += std::sprintf(out, "0x%02x", (U4)(U1)imm_value);
		}
		else
		if(size == argsize_16)
		{				
			out += std::sprintf(out, "0x%04x", (U4)(U2)imm_value);
		}
		else
		if(size == argsize_32)
		{				
			out += std::sprintf(out, "0x%08x", (U4)imm_value);
		}
		else
		{
			write("<unimplemented immediate size>");
		}
	}
	void write_far_imm()
	{
		write_far(true);
		do_write_imm(get_argsize_lo(s->icode->argsize[1]), (U4)(U2)s->icode->disp);
		write(":");
		do_write_imm(get_argsize_lo(s->icode->argsize[0]), (U4)s->icode->imm);
	}
	void write_size_suffix(U1 size)
	{
		if(size == argsize_8)
			write("b");
		else
		if(size == argsize_16)
			write("w");
		else
		if(size == argsize_32)
			write("d");
		else
		if(size == argsize_64)
			write("q");
	}
	// --- end new things ---
};

class NasmWriter :
	public AsmWriter
{
	public:
	virtual bool special_insn();
	private:
	void write_size();
};

}	// namespace x86s

#endif	// l_crudasm__asmwriter_h__included

⌨️ 快捷键说明

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