一个文本翻译工具的实现

一、需求

一个文本翻译工具,功能类似于汇编器,能够把一些字符串(程序的助记符)翻译为其他的字符串或者数字,并打印到文本文件中。完成的功能如下:

1.        助记符翻译

2.        程序地址分配

3.        Label替换程序地址

4.        数据地址替换

5.        宏定义的展开


输入文件格式

1.        纯文本文件,允许行首有多个空格或者制表符。同一行内,语句之间用一个或者多个空格或者制表符隔开。

2.        不区分大小写。

3.        注释以“;”开始,占单独一行。处理的时候丢弃注释行。

4.        Label以“%”开始,以“:”结束,占单独一行。主要用于表示跳转的目的地址。

5.        立即数以“#”开始,以16进制表示。

6.        立即程序地址和立即数据地址都以“&”开始,以16进制表示。

输出文件格式

文件1

   16’h程序地址begin instr = {...}; end

文件2

   所有立即数据地址,每行一个。

助记符翻译

   阴影文字不做翻译,直接输出。xxmy label的低8位。


Jmp &my_label

{`brch, `drt, `cnd_non, `jmp_next, 8’hxx}

Jz & my_label

{`brch, `drt, `cnd_z, `jmp_next, 8’hxx}

Jnz & my_label

{`brch, `drt, `cnd_nz, `jmp_next, 8’hxx}

Jc & my_label

{`brch, `drt, `cnd_c, `jmp_next, 8’hxx}

Jnc & my_label

{`brch, `drt, `cnd_nz, `jmp_next, 8’hxx}

Jw & my_label

{`brch, `drt, `cnd_non, `jmp_wait, 8’hxx}

 

 

Jmp @ r1r0

{`brch, `ptr, `cnd_non, `jmp_next, 8’h00}

Jz @ r1r0

{`brch, `ptr, `cnd_z, `jmp_next, 8’h00}

Jnz @ r1r0

{`brch, `ptr, `cnd_nz, `jmp_next, 8’h00}

Jc @ r1r0

{`brch, `ptr, `cnd_c, `jmp_next, 8’h00}

Jnc @ r1r0

{`brch, `ptr, `cnd_nc, `jmp_next, 8’h00}

Jw @ r1r0

{`brch, `ptr, `cnd_non, `jmp_wait, 8’h00}


Add rega regb

{`arth, `add, `rega, `regb}

Sub rega regb

{`arth, `sub, `rega, `regb}

Mul rega regb

{`arth, `mul, `rega, `regb}

Mac rega regb

{`arth, `mac, `rega, `regb}

Div rega regb

{`arth, `div, `rega, `regb}

Sqt rega regb

{`arth, `sqt, `rega, `regb}


Nop

{16’b0}

Shl 0nmb regs

{`shft, `left, `with_0, `act, `nmb, `regs}

Shl 1nmb regs

{`shft, `left, `with_1, `act, `nmb, `regs}

Shl snmb regs

{`shft, `left, `with_s, `act, `nmb, `regs}

Rttlregs

{`shft, `left, `with_r, `act, 1’b1, `regs}

 

 

Shr 0nmb regs

{`shft, `right, `with_0, `act, `nmb, `regs}

Shr 1nmb regs

{`shft, `right, `with_1, `act, `nmb, `regs}

Shr snmb regs

{`shft, `right, `with_s, `act, `nmb, `regs}

Rttrregs

{`shft, `right, `with_r, `act, 1’b1, `regs}


Ldregs #立即数

{`ldst, `ld_drt_data, `regs, 8’h立即数}

Ldregs &立即地址

{`ldst, `ld_drt_addr, `regs, `立即数据地址}

Stregs &立即地址

{`ldst, `st_drt_addr, `regs, `立即数据地址}

Ldrega regb

{`ldst, `reg_or_ptr, `rega, `ld_reg, `regb}

Strega regb

{`ldst, `reg_or_ptr, `rega, `st_reg, `regb}

Ldregs @ r1r0

{`ldst, `reg_or_ptr, `regs, `ld_ptr, 4’b0}

Stregs @ r1r0

{`ldst, `reg_or_ptr, `regs, `st_ptr, 4’b0}

程序地址分配,Label程序地址替换

每一行有效语句分配一个1616进制的程序地址。对于注释行不分配;对于label行,其表示的是下一行有效语句的地址。

源程序内跳转指令中的跳转目标地址会使用label表示,汇编器把label替换为label表示的实际地址的低8位。把跳转指令之前的“#label_page”替换为label表示的实际地址的高8位。

数据地址替换

保留源程序中的数据地址到输出文件1。同时将其输出到文件2

宏定义的展开

使用macro_def: name(base_para)标记一段对程序的宏定义。在程序中通过macro_gen: name(base_arg)引用,汇编器将这一段宏定义展开,展开时用base_arg添加到宏定义代码段中的立即地址之前。

输入范例

; an input file example

              mul        r32_0   r32_1

%my_label  ld        r64_0   &alu_result

              ld          r3          #my_label_page

jz           my_label

              st         r64_0     &data_save

           ld          r1          #5a

输出文件1范例

16’h0000: begin instr = {`arth, `mul, `r32_0, `r32_1}                     ; end

16’h0001: begin instr = {`ldst, `ld_drt_addr, `r64_0, `alu_result }    ; end

16’h0002: begin instr = {`ldst, `ld_drt_data, `r3, 8’h00 }                ;end

16’h0003: begin instr = {`brch, `drt, `cnd_z, `jmp_next, 8’h01}            ; end

16’h0004: begin instr = {`ldst, `st_drt_addr, `r64_0, `data_save}             ; end

16’h0005: begin instr = {`ldst, `ld_drt_data, `r2, 8’h5a}                ; end

输出文件2范例

`define alu_result  8’h00

`define data_save   8’h01


二、实现

用VS2013控制台实现

1、需要转换的文件格式如下:

macrostart

macro_def : test1 ( base_para )
{
		st	r64_0	& data_save
		ld	r1	# 5a
		arth_mus	r32_0 	r32_1
}

macro_def : test2 ( base_para )
{
		arth_mus	r32_0 	r32_1
% my_label  :
		ld 	r64_0 	& alu_result
		jnz	& my_label
}

datastart
		
; an input file example

		arth_mus	r32_0 	r32_1
		st 	r64_0	& szy_data_save
		ld	r1	# 5a
		arth_mus	r32_0 	r32_1

		ld	r1	# 5a
		arth_mus	r32_0 	r32_1

		arth_mus	r32_0 	r32_1
		st 	r64_0	& szy_data_save
		ld	r1	# 5a
		arth_mus	r32_0 	r32_1

macro_gen :	test2 ( lpf )

% my_label  :
		ld	r64_0 	& alu_result
        	ld	r3	# my_label_page
		jz	& my_label
		arth_mus	r32_0 	r32_1

macro_gen :	test1 ( cic )

% szy_my_label  :
		ld	r64_0 	& szy_alu_result
        	st	r64_0	& data_save
		ld	r1	# 5a

由于需要区别宏和数据,我用了macrostart和datastart分开这两部分。

2、需要的参数如下:
(至少两个参数)程序 输入文件
如果多余两个参数,则对参数进行分类:一类是以"-"开头的,一类则是文件(输入文件和输出文件)
对于以"-"开头的,目前只识别 -d、-r、-md、-m
这四个参数分别表示处理完翻译之后会打印 最终数据、寄存器信息、宏展开后的数据、宏信息
最多有5个文件,若有5个文件,则分别表示 (若不足5个,那就只处理相应的前几个文件)
输入文件、最终数据文件、寄存器信息文件、宏展开后的数据文件、宏信息文件

	//命令行参数处理
	set<int> paraset;//带‘-’参数集合,存储的是到全局数组的偏移量
	vector<string> filelist;//文件列表
	for (int i = 1; i < argc; i++)
	{
		string currpara(argv[i]);
		if (currpara.empty())continue;

		if (currpara[0] == '-')//带‘-’参数
		{
			//判断能否识别这个参数
			auto it = find(g_para, g_para + g_paran, currpara);
			if (it == g_para + g_paran)//没有找到
			{
				cout << "\nerror: not indentifies the \"" << currpara << "\".\n";
				cout << "----------------------------------\n";
				return 0;
			}
			paraset.insert(it - g_para);
		}
		else filelist.push_back(currpara);//文件
	}

	if (filelist.empty())
	{
		cout << "\nerror: not find infile.\n";
		cout << "----------------------------------\n";
		return 0;
	}
	else if (filelist.size() > 5)
	{
		cout << "\nerror: file num too more(greater than 5).\n";
		cout << "----------------------------------\n";
		return 0;
	}

默认第二个参数是输入的文件。

g_para和g_paran是两个全局变量:

//四个带-的参数: -d,-rd,-md,-m
const int		g_paran = 4;
const string		g_para[g_paran] = { "-d", "-r", "-md", "-m" };//依次会打印asmalgorithm中的私有成员
enum				g_parai{ D = 0, R, MD, M };

3、读取需要转换的文件

	//获取输入文件数据
	string filedata;//文件数据
	string errmsg;
	if (!ReadFile(filelist[0], filedata, errmsg))//获取数据
	{
		cout << "\n" << errmsg << "\nexit!\n";
		cout << "----------------------------------\n";
		return 0;
	}

ReadFile实现为:

bool ReadFile(const string &file, string & filedata, std::string &errmsg)
{
	filedata.clear();
	errmsg.clear();

	ifstream fin;
	fin.open(file.c_str());
	if (!fin.is_open())
	{
		errmsg = "not open file: \"" + file + "\"";
		return false;
	}

	ostringstream ss;
	ss << fin.rdbuf();
	
	filedata = ss.str();

	fin.close();

	return true;
}


4、转换文件

//处理输入的文件数据
	AsmAlgorithm myasm;
	if (!myasm.Handle(filedata,errmsg))//处理数据
	{
		cout << "\n" << errmsg << "\nexit!\n";
		cout << "----------------------------------\n";
		return 0;
	}

定义了一个类AsmAlgorithm,用它的Handle成员来统一处理。


5、AsmAlgorithm类

AsmAlgorithm类如下:

class AsmAlgorithm
{
public:
	AsmAlgorithm();
	~AsmAlgorithm();

public://行为

	//核心算法处理	
	/*
	总处理函数
	对于原始文件的一行,判断是哪种处理,并调用相应处理, 然后包裹格式来获取新行
	*/
	bool Handle(const std::string &idata, std::string & errmsg);

	//获取数据成员信息
	const std::vector<std::string>& GetData();
	const std::vector<std::string>& GetReg();
	const std::vector<std::vector<std::string>>& GetMacroData();
	const std::set<MacroInfo>& GetMacro();

private:
	//注释处理 无

	//标签处理
	static bool LabelHandle(const int cmdindex, const std::vector<std::string> &isource,
		std::vector<std::string> &odst, std::string &errmsg);

	//跳转处理  拿到输入的数据,按照某种格式输出
	static bool JumpHandle(const int cmdindex, const std::vector<std::string> &isource,
		std::vector<std::string> &odst, std::string &errmsg);

	//操作处理
	static bool OperatorHandle(const int cmdindex, const std::vector<std::string> &isource,
		std::vector<std::string>&odst, std::string &errmsg);

	//shell处理
	static bool ShellHandle(const int cmdindex, const std::vector<std::string> &isource,
		std::vector<std::string>&odst, std::string &errmsg);

	//传送处理
	static bool TransmitHandle(const int cmdindex, const std::vector<std::string> &isource,
		std::vector<std::string>&odst, std::string &errmsg);

	//
	//辅助方法
	//大写转小写
	static std::string MyToLower(const std::string & str);

	//包裹函数 把一个容器包装成一个字符串 对应于文件1中的字符串格式
	static std::string Wrapper(const std::vector<std::string> isource);

	//包裹文件2的字符串格式
	static std::string Wrapper(const std::pair<std::string, int> & regitem);

	//添加一个立即地址到寄存器列表中
	static void AddRegAddr(const std::string &reg);

	//拼接错误函数
	static std::string SplitError(const std::string &cause, const std::string &line);

	//获取宏域内的信息
	static bool GetMacroInfo(const std::string &data, std::set<MacroInfo> &odata, std::string & errmsg);

	//获取数据域内的信息
	static bool GetDataAreaInfo(const std::string &idata, const std::set<MacroInfo> &vmi,
		std::vector<std::vector<std::string>> &odata, std::string &errmsg);

private:
	std::vector<std::string >		m_data;//最终的数据信息,若有文件1,将会写入到文件1
	std::vector<std::string >		m_reg;//寄存器信息,若有文件2,将会写入到文件2
	std::vector<std::vector<std::string>>	m_macrodata;//宏展开后的数据信息,若有文件3,将会写入到文件3
	std::set<MacroInfo>			m_macro;//宏信息,若有文件4,将会写入到文件4
};


其中MacroInfo这个宏定义成了:

struct MacroInfo
{
	std::string name;//这个宏的名字
	std::string parameter;//这个宏的参数
	std::vector<std::vector<std::string>> cmdlist;//这个宏里面的命令列表
	friend bool operator<(const MacroInfo &item1, const MacroInfo &item2)
	{
		return item1.name < item2.name;
	}
};


6、一些全局变量以及宏等

//宏定义和展开的入口
#define MACRODEF "macro_def"
#define MACROGEN "macro_gen"

//当前行地址
static int g_currlineaddr = -1;//<=0xffffffff

//寄存器地址
static int g_regaddr = -1;//<=0xff
vector<pair<string, int>> g_reglist;//寄存器列表

//标签地址
static map<string, int> g_labeladdrmap;//<标签,地址>

//注释处理的助记符
static const string	g_NC = ";";//note cmd

//标签处理的助记符
static const string	g_LS = "%";//label start
static const string	g_LE = ":";//label end

//跳转处理的的助记符
static const int	g_JCN = 6;//Jump cmd num
static const string	g_JC[g_JCN] = { "jmp", "jz", "jnz", "jc", "jnc", "jw" };//Jump cmd
enum			g_JCI{ JMP = 0, JZ, JNZ, JC, JNC, JW };//Jump cmd index
static const int	g_JFN = 2;//Jump  flag num
static const string	g_JF[g_JFN] = { "&", "@" };//Jump flag
enum			g_JFI{ JAND = 0, JAT };//Jump cmd flag

//操作处理的的助记符
static const string	g_OP = "arth_";//operator prefix
static const string	g_OC = "arth";//operator cmd

//shell处理的助记符
static const int	g_SCN = 5;//shell cmd num
static string		g_SC[g_SCN] = { "nop", "shl", "rttl", "shr", "rttr" };//shell cmd
enum			g_SCI{ NOP = 0, SHL, RTTL, SHR, RTTR };//shell cmd index
static const int	g_SFN = 3;//shell flag num
static string		g_SF[g_SFN] = { "0", "1", "s" };//shell flag
enum			g_SFI{ SFI0 = 0, SFI1, SFIS };//shell flag index

//传送处理的助记符
static const int	g_TCN = 2;//transmit cmd num
static string		g_TC[g_TCN] = { "ld", "st" };//transmit cmd
enum			g_TCI{ LD = 0, ST };//transmit cmd index
static const int	g_TFN = 3;//transmit flag num
static string		g_TF[g_TFN] = { "#", "&", "@" };//transmit flag num
enum			g_TFI{TWELL=0,TAND,TAT};//transmit flag index

7、AsmAlgorithm处理

Handle成员:
数据准备工作:

bool AsmAlgorithm::Handle(const string &idata,string & errmsg)
{
	errmsg.clear();

	//私有数据的初始化
	m_macro.clear();
	m_macrodata.clear();
	m_data.clear();
	m_reg.clear();

	g_labeladdrmap.clear();//清空标签地址
	g_reglist.clear();//清空寄存器地址信息

接着查找宏域和数据域

	/*
	获取的文件数据
	它有两部分,宏和数据(宏不是必须存在的(若存在,则必须在数据域前面),数据是必须存在的)
	用macrostart开始的是宏,直到遇到datastart
	用datastart开始的是数据,直到文件结束
	*/
	/*
	宏的格式:文件数据中遇到这个宏名时会把里面的标签(格式为 % label :)
	和 &地址(跳转中的&地址和传送中的地址)添加相应的label和地址的前缀(实参_)
	macro_def : 宏名 ( 参数 )
	{
			文件数据中的数据格式
	}
	例如:
	macro_def : test1 ( base_para )
	{
			st 		r64_0	& data_save
			ld		r1		# 5a
			mul		r32_0 	r32_1
	}
	*/
	
	//
	//查找宏区域
	auto macrostart = idata.find(MACROSTART);//查找macrostart
	string tmpstr(idata.substr(0,macrostart));
	int LF = tmpstr.rfind("\n");//从后往前找换行符,行首
	if (LF + 1 != macrostart)//行首的下一个不是macrostart
	{
		errmsg = SplitError("\"macrostart\" is not at top of line", 
			idata.substr(LF+1, macrostart - LF) + MACROSTART + "...");
		return false;
	}
	
	//查找数据区域
	auto datastart = idata.find(DATASTART);//查找datastart
	tmpstr = idata.substr(0, datastart);
	LF = tmpstr.rfind("\n");//从后往前找换行符,行首
	if (LF + 1 != datastart)//行首的下一个不是datastart
	{
		errmsg = SplitError("\"datastart\" is not at top of line",
			idata.substr(LF+1, datastart - LF) + DATASTART + "...");
		return false;
	}

	//判断宏域和数据域的位置关系
	if (datastart == string::npos)//没有找到数据域开始的部分
	{
		errmsg = "not find data area from the infile.\n";
		return false;
	}
	if (macrostart != string::npos && macrostart > datastart)//宏域在数据域之后,错误
	{
		errmsg = "the macrostart is not at behand of datastart.\n";
		return false;
	}

处理宏域并宏展开:

	//
	if (macrostart != string::npos)//有宏域
	{
		//处理宏域
		if (!GetMacroInfo(idata.substr(macrostart, datastart - macrostart), m_macro, errmsg))
			return false;
	}

	//宏展开和填写标签地址信息
	if (!GetDataAreaInfo(idata.substr(datastart), m_macro, m_macrodata, errmsg))
		return false;

处理完宏域之后,接着处理数据域(把它们放入一个vector的m_macrodata里面),处理数据域时,遇到宏定义需要宏展开(宏的信息在m_macro中),并且还需要填写标签地址信息(标签地址信息是一个全局变量g_labeladdrmap)。

数据处理:

//
	//数据处理。。。
	using fun_manager =
		bool(*)(const int, const vector<string> &, vector<string> &, string &);//函数对象 
	vector<string> cmdlist;//命令列表,含所有命令
	map<int, fun_manager,greater<int>> cmdfunmap;//函数对象的映射关系
	cmdfunmap.insert({ cmdlist.end() - cmdlist.begin(), LabelHandle });
	cmdlist.push_back(g_LS);//标签 0
	cmdfunmap.insert({ cmdlist.end() - cmdlist.begin(), JumpHandle });
	cmdlist.insert(cmdlist.end(), g_JC, g_JC + g_JCN);//跳转
	cmdfunmap.insert({ cmdlist.end() - cmdlist.begin(), OperatorHandle });
	cmdlist.insert(cmdlist.end(), g_OC);//操作
	cmdfunmap.insert({ cmdlist.end() - cmdlist.begin(), ShellHandle });
	cmdlist.insert(cmdlist.end(), g_SC, g_SC + g_SCN);//shell
	cmdfunmap.insert({ cmdlist.end() - cmdlist.begin(), TransmitHandle });
	cmdlist.insert(cmdlist.end(), g_TC, g_TC + g_TCN);//传送

	for (vector<vector<string>>::size_type i = 0; i < m_macrodata.size(); i++)
	{//执行原始文件的每一行
		vector<string> oldformat = m_macrodata[i];//获取输入的数据格式
		string cmd(MyToLower(oldformat[0]));//获取命令

		auto cmdit = find(cmdlist.begin(), cmdlist.end(), cmd);//查找这个命令是否存在
		if (cmdit == cmdlist.end())//没有找到
		{
			errmsg = SplitError("command is not find", Vector2String(oldformat));
			return false;
		}
		const int cmdoffset = cmdit - cmdlist.begin();//cmd的偏移
		const auto realit = find_if(cmdfunmap.cbegin(), cmdfunmap.cend(), //获取需要执行的cmd属于哪一类
			[cmdoffset](const pair<int, fun_manager>&item){return cmdoffset >=item.first; });

		vector<string> newformat;//输出的数据格式
		
		//需要执行function的命令
		if (!realit->second(cmdoffset - realit->first, oldformat, newformat, errmsg))
		{
			return false;
		}

		if (realit->first == 0)//标签的处理,不用添加到输出容器中
		{
			continue;
		}

		string newline = Wrapper(newformat);//包裹起来
		
		//追加到新容器中,之后会把这个容器的内容写到目标文件中
		m_data.push_back(newline);
	}

我把需要转换的命令分成了五类:标签(%开头的)、跳转(J开头的)、操作(add、sub、mul等)、shell(nop、shl、rttl等)、传送(ld,st),它们不区分大小写,我统一用MyToLower转换成小写了。

fun_manager在必要的时候分别指向这五类函数。
主要算法是遍历每一行,通过命令来判断这一行应该属于哪一类处理,然后调用相应的函数来处理这一行数据。

再介绍辅助函数
MyToLower:

string AsmAlgorithm::MyToLower(const string & str)
{
	string ret;

	for (string::size_type i = 0; i < str.size();i++)
	{
		ret += tolower(str[i]);
	}

	return ret;
}


Wrapper:

string AsmAlgorithm::Wrapper(const vector<string> isource)
{//格式:16’h0000: begin instr = {`arth, `mul, `r32_0, `r32_1}; end
	g_currlineaddr++;
	if (g_currlineaddr > 0xffffffff)
	{
		g_currlineaddr = 0;
	}

	char sztmp[50] = { 0 };//前缀部分
	MySprintf(sztmp, sizeof(sztmp), "16'h%04x : begin instr = ", (short)(g_currlineaddr));

	string vsstr = "{" + Vector2String(isource, ",") + "}";//数据部分

	ostringstream sout;
	sout << sztmp << setw(45) << left << vsstr << ";end";
	return sout.str();
}

std::string AsmAlgorithm::Wrapper(const std::pair<std::string, int> & regitem)
{//格式: `define alu_result	8’h00

	char regstr[10] = { 0 };
	MySprintf(regstr, sizeof(regstr), " 8'h%02x", (char)(regitem.second));

	ostringstream sout;
	sout << "`define " << setw(15) << left << regitem.first.c_str() << regstr;

	return sout.str();
}

SplitError:

string AsmAlgorithm::SplitError(const string &cause, const string &line)
{
	char szerr[300] = { 0 };
	MySprintf(szerr, sizeof(szerr), "error[%s]: \"%s\"\n", cause.c_str(), line.c_str());

	return string(szerr);
}

因为我的程序也会在gcc下编译,所以MySprintf是:

#if defined(_WIN32)|| defined(WIN32) || defined(_WIN64) || defined(WIN64) || defined(_WIN32_WINNT)
#define  MySprintf	sprintf_s//Win下
#else
#define  MySprintf	snprintf//linux下
#endif

AddRegAddr:

void AsmAlgorithm::AddRegAddr(const std::string &reg)
{
	g_regaddr++;
	if (g_regaddr > 0xff)
	{
		g_regaddr = 0;
	}

	g_reglist.push_back(pair<string, int>(reg, g_regaddr));
}

处理宏域的GetMacroInfo:

bool AsmAlgorithm::GetMacroInfo(const string &data, set<MacroInfo> &odata, string &errmsg)
{
	/*
	格式
	macro_def : test1 ( base_para )
	{
	st 		r64_0	& data_save
	ld		r1		# 5a
	mul		r32_0 	r32_1
	}
	*/

	stringstream sin(data);

	string line;
	getline(sin, line);//第一行的格式应该是 macrostart
	vector<string> FML = String2Vector(line);//first macro list
	if (FML.size() != 1 || FML[0] != MACROSTART)//不是“macrostart”格式
	{
		errmsg = SplitError("format is not \"macrostart\"", line);
		return false;
	}
	
	//先获取所有数据到容器里面,
	//空行舍弃、只含有空格的行也舍弃,以;开头的行(注释行)也舍弃
	vector<vector<string>> linelist;
	while (getline(sin, line))
	{
		if (line.empty()) continue;//空行
		vector<string> s2v = String2Vector(line);
		if (s2v.empty()) continue;//只含有空格的行
		if (s2v[0] == g_NC) continue;//注释行
		linelist.push_back(s2v);
	}

	//对每一行,开始找macro_def
	const int linesize = linelist.size();
	int titleline = 0;
	for (int i = 0; i < linesize; i++)
	{
		vector<string> itemlist = linelist[i];

		if (itemlist.size() != 6
			|| itemlist[0] != MACRODEF
			|| itemlist[1] != ":"
			|| itemlist[3] != "("
			|| itemlist[5] != ")")//这个macro_def不符合格式,错误
		{
			errmsg = SplitError("format is not \"macro_def : name ( base_para )\"", Vector2String(linelist[i]));
			return false;
		}
		//找到这个宏的题头了
		MacroInfo info;
		info.name = itemlist[2];
		info.parameter = itemlist[4];
		titleline = i;//记录下题头行

		//开始找这个宏包含的命令信息
		//先找{符号
		i++;
		if (i == linesize)
		{
			errmsg = SplitError("not find the \"{\" after the macrotitile", Vector2String(linelist[titleline]));
			return false;
		}
		itemlist = linelist[i];
		if (!(itemlist.size() == 1 && itemlist[0] == "{"))//这行不是只含有{,则认为是错的
		{
			errmsg = SplitError("the line is not \"{\" after macrotitle", Vector2String(linelist[titleline]));
			errmsg += "it is \"" + Vector2String(linelist[i]) + "\"\n";
			return false;
		}

		//开始找命令行信息了
		bool bfindend = false;//用}来判断这个宏的结束
		for (i++; i < linesize;i++)
		{
			itemlist = linelist[i];
			if (itemlist.size() == 1 && itemlist[0] == "}")//找到一个只含有}的行
			{
				bfindend = true;
				break;
			}
			info.cmdlist.push_back(itemlist);
		}
		if (!bfindend)//遍历完宏域,都没有找到},则认为是错的
		{
			errmsg = SplitError("not find the \"}\" of the macro_def", Vector2String(linelist[titleline]));
			return false;
		}

		//找到}了
		//判断以前是否有这个宏定义
		auto it = find_if(odata.begin(), odata.end(),
			[info](const MacroInfo &item){return info.name == item.name; });
		if (it != odata.end())//这个宏定义已经存在了
		{
			errmsg = "the macro define of \"" + info.name + "\"have 2 times or more.\n";
			return false;
		}
		odata.insert(info);
	}

	return true;
}

获取数据域内的信息GetDataAreaInfo:

bool AsmAlgorithm::GetDataAreaInfo(const string &idata, const set<MacroInfo> &vmi,
	vector<vector<string>> &odata,string &errmsg)
{//遇到宏定义需要展开,并填写标签地址
	odata.clear();
	errmsg.clear();

	stringstream sin(idata);

	string line;
	getline(sin, line);//第一行的格式应该是 datastart
	vector<string> FDL = String2Vector(line);//first data list
	if (FDL.size() != 1 || FDL[0] != DATASTART)//不是“datastart”格式
	{
		errmsg = SplitError("format is not \"datastart\"", line);
		return false;
	}

	while (getline(sin, line))
	{
		if (line.empty())continue;//空行
		vector<string> linelist = String2Vector(line);//拆分当前行
		if (linelist.empty())continue;//只有空格的行
		if (linelist[0] == g_NC)continue;//注释行舍弃

		string firstitem = MyToLower(linelist[0]);
		const auto findpos = firstitem.find(g_OP);//查找operator处理
		if (findpos == 0)//找到 arth_
		{
			linelist.insert(linelist.begin(), g_OC);
			linelist[1] = firstitem.substr(g_OP.size());
		}

		const string cmd(linelist[0]);//获取命令

		//只有宏展开入口macro_gen
		if (cmd == MACROGEN)//宏展开
		{
			if (linelist.size() != 6
				|| linelist[0] != MACROGEN
				|| linelist[1] != ":"
				|| linelist[3] != "("
				|| linelist[5] != ")")//这个macro_gen不符合格式
			{
				errmsg = SplitError("format is not \"macro_gen : name ( para )\"", line);
				return false;
			}

			//将这一行替换为宏定义
			//查找这个宏
			auto macroit = find_if(vmi.begin(), vmi.end(),
				[linelist](const MacroInfo &item){return linelist[2] == item.name; });
			if (macroit == vmi.end())//没有找到这个宏定义
			{
				errmsg = "not find macro define of the \"" + linelist[2] + "\".\n";
				return false;
			}
			
			for (vector<vector<string>>::size_type i = 0; i < macroit->cmdlist.size(); i++)
			{//把标签和&的都添加前缀
				vector<string> itemlist = macroit->cmdlist[i];//获取一个命令行的容器

				const string mcmd(MyToLower(itemlist[0]));//获取命令

				string firstitem = MyToLower(itemlist[0]);
				const auto findpos = firstitem.find(g_OP);//查找operator处理
				if (findpos == 0)//找到 arth_
				{
					itemlist.insert(itemlist.begin(), g_OC);
					itemlist[1] = firstitem.substr(g_OP.size());
				}
				
				//跳转
				auto jumpit = find_if(g_JC, g_JC + g_JCN, 
				[mcmd](const string & item){return item == mcmd; });
				
				//传送
				auto tramsit = find_if(g_TC, g_TC + g_TCN, 
				[mcmd](const string & item){return item == mcmd; });
				
				if (jumpit != g_JC + g_JCN)//跳转处理
				{
					if (itemlist.size() == 3 && itemlist[1] == g_JF[g_JFI::JAND])//是jxx & xxx
					{
						itemlist[2] = linelist[4] + "_" + itemlist[2];
					}
					odata.push_back(itemlist);
				}
				else if (tramsit != g_TC + g_TCN)//传送处理
				{
					if (itemlist.size() == 4 && itemlist[2] == g_TF[g_TFI::TAND])//是 ld/st xxx & xxx
					{
						itemlist[3] = linelist[4] + "_" + itemlist[3];
					}
					odata.push_back(itemlist);
				}
				else if (mcmd==g_LS)//标签
				{
					if (itemlist.size() == 3 && itemlist[2] == g_LE)//完全匹配标签
					{
						itemlist[1] = linelist[4] + "_" + itemlist[1];
						odata.push_back(itemlist);

						//写到标签地址中
						g_labeladdrmap[itemlist[1]] = odata.size() - g_labeladdrmap.size() - 1;
					}
					else
					{
						errmsg = SplitError("format is not \"% label :\" from macro \"" + macroit->name + "\"", 
						Vector2String(itemlist));
						return false;
					}
				}
				else//宏中的其他命令
				{
					odata.push_back(itemlist);
				}
			}
		} 
		else//除了宏之外的行信息
		{
			if (cmd == g_LS)//标签行
			{
				if (linelist.size() == 3 && linelist[2] == g_LE)//完全匹配标签
				{
					odata.push_back(linelist);

					//写到标签地址中
					g_labeladdrmap[linelist[1]] = odata.size() - g_labeladdrmap.size() - 1;
				}
				else
				{
					errmsg = SplitError("format is not \"% label :\"", line);
					return false;
				}
			}
			else//其他的行
			{
				odata.push_back(linelist);
			}
		}
	}

	return true;
}

最后介绍五类转换函数:

标签的LabelHandle:

bool AsmAlgorithm::LabelHandle(const int cmdindex, const vector<string> &isource,
	vector<string> &odst, string &errmsg)
{//格式 % label : //为了和另外几个xxxHandle函数统一,也用了输出容器,其实不需要输出容器
	odst.clear();
	errmsg.clear();

	if (isource.size() != 3 || isource[2] != g_LE)
	{
		errmsg = AsmAlgorithm::SplitError("format is not \"% label :\"", Vector2String(isource));
		return false;
	}

	//添加到地址 其实在宏展开的时候就已经写好了
	g_labeladdrmap[isource[1]] = g_currlineaddr + 1;

	return true;
}

这里为了和另外几个转换函数风格一致,我用了isource容器,但用不上,需要注意这个isource不能添加到输出容器中。

跳转的JumpHandle:

bool AsmAlgorithm::JumpHandle(const int cmdindex, const vector<string> &isource,
	vector<string> &odst, string &errmsg)
{//格式 jxx &/@ label/r1r0
	/*
	Jmp & my_label	{`brch, `drt, `cnd_non, `jmp_next, 8’hxx}
	Jz & my_label		{`brch, `drt, `cnd_z, `jmp_next, 8’hxx}
	Jnz & my_label	{`brch, `drt, `cnd_nz, `jmp_next, 8’hxx}
	Jc & my_label		{`brch, `drt, `cnd_c, `jmp_next, 8’hxx}
	Jnc & my_label	{`brch, `drt, `cnd_nc, `jmp_next, 8’hxx}
	Jw & my_label		{`brch, `drt, `cnd_non, `jmp_wait, 8’hxx}

	Jmp @ r1r0		{`brch, `ptr, `cnd_non, `jmp_next, 8’h00}
	Jz @ r1r0		{`brch, `ptr, `cnd_z, `jmp_next, 8’h00}
	Jnz @ r1r0		{`brch, `ptr, `cnd_nz, `jmp_next, 8’h00}
	Jc @ r1r0		{`brch, `ptr, `cnd_c, `jmp_next, 8’h00}
	Jnc @ r1r0		{`brch, `ptr, `cnd_nc, `jmp_next, 8’h00}
	Jw @ r1r0		{`brch, `ptr, `cnd_non, `jmp_wait, 8’h00}
	*/

	odst.clear();
	errmsg.clear();

	if (isource.size() != 3)
	{
		errmsg = SplitError("format is not \"jxx &/@ label/r1r0\"", Vector2String(isource));
		return false;
	}

	string flag(MyToLower(isource[1]));//获取符号

	auto flagit = find(g_JF, g_JF + g_JFN, flag);//查找符号
	if (flagit == g_JF + g_JFN)//没找到符号
	{
		errmsg = SplitError("not find flag \"@/&\"", Vector2String(isource));
		return false;
	}

	if (*flagit == g_JF[g_JFI::JAND])//&
	{
		if (g_labeladdrmap.find(isource[2]) == g_labeladdrmap.end())//查找标签
		{//没找到
			errmsg = SplitError("not find the label address", Vector2String(isource));
			return false;
		}

		string tmparray[5] = { "`brch", "`drt", "`cnd_non", "`jmp_next", "8'h" };
		odst.assign(tmparray, tmparray + 5);
		char sztmp[20] = { 0 };
		MySprintf(sztmp, sizeof(sztmp), "%02x", (char)(g_labeladdrmap[isource[2]]));
		odst[4] += sztmp;

		switch (cmdindex)
		{
		case g_JCI::JMP:
			break;
		case g_JCI::JZ:
			odst[2] = "`cnd_z";
			break;
		case g_JCI::JNZ:
			odst[2] = "`cnd_nz";
			break;
		case g_JCI::JC:
			odst[2] = "`cnd_c";
			break;
		case g_JCI::JNC:
			odst[2] = "`cnd_nc";
			break;
		case g_JCI::JW:
			odst[3] = "`jmp_wait";
			break;
		default:
			errmsg = SplitError("format is not \"jxx &/@ label/r1r0\"", Vector2String(isource));
			return false;
		}

		return true;
	}
	else //@
	{
		if (MyToLower(isource[2]) != MyToLower("r1r0"))
		{
			errmsg = SplitError("not defined", Vector2String(isource));
			return false;
		}

		string tmparray[5] = { "`brch", "`ptr", "`cnd_non", "`jmp_next", "8'h00" };
		odst.assign(tmparray, tmparray + 5);

		switch (cmdindex)
		{
		case g_JCI::JMP:
			break;
		case g_JCI::JZ:
			odst[2] = "`cnd_z";
			break;
		case g_JCI::JNZ:
			odst[2] = "`cnd_nz";
			break;
		case g_JCI::JC:
			odst[2] = "`cnd_c";
			break;
		case g_JCI::JNC:
			odst[2] = "`cnd_nc";
			break;
		case g_JCI::JW:
			odst[3] = "`jmp_wait";
			break;
		default:
			errmsg = SplitError("format is not \"jxx &/@ label/r1r0\"", Vector2String(isource));
			return false;
		}

		return true;
	} 
}

操作的OperatorHandle:

bool AsmAlgorithm::OperatorHandle(const int cmdindex, const vector<string> &isource,
	vector<string>&odst, string &errmsg)
{//格式 operator rega regb	
	/*
	Add rega regb	{`arth, `add, `rega, `regb}
	Sub rega regb	{`arth, `sub, `rega, `regb}
	Mul rega regb	{`arth, `mul, `rega, `regb}
	Mac rega regb	{`arth, `mac, `rega, `regb}
	Div rega regb	{`arth, `div, `rega, `regb}
	Sqt rega regb	{`arth, `sqt, `rega, `regb}
	*/

	odst.clear();
	errmsg.clear();

	if (isource.size() != 4)
	{
		errmsg = SplitError("format is not \"operator rega regb\"", Vector2String(isource));
		return false;
	}

	//{`arth, `add, `rega, `regb}
	odst.push_back("`" + isource[0]);
	odst.push_back("`" + isource[1]);
	odst.push_back("`" + isource[2]);
	odst.push_back("`" + isource[3]);

	return true;
}

shell的ShellHandle:

bool AsmAlgorithm::ShellHandle(const int cmdindex, const vector<string> &isource,
	vector<string>&odst, string &errmsg)
{//格式 Shl 0 nmb regs
	/*
	Nop				{16’b0}
	Shl 0 nmb regs	{`shft, `left, `with_0, `act, `nmb, `regs}
	Shl 1 nmb regs	{`shft, `left, `with_1, `act, `nmb, `regs}
	Shl s nmb regs	{`shft, `left, `with_s, `act, `nmb, `regs}
	Rttl 	regs		{`shft, `left, `with_r, `act, 1’b1, `regs}

	Shr 0 nmb regs	{`shft, `right, `with_0, `act, `nmb, `regs}
	Shr 1 nmb regs	{`shft, `right, `with_1, `act, `nmb, `regs}
	Shr s nmb regs	{`shft, `right, `with_s, `act, `nmb, `regs}
	Rttr 	regs		{`shft, `right, `with_r, `act, 1’b1, `regs}
	*/

	odst.clear();
	errmsg.clear();

	string tmparray[6] = { "`shft", "`left", "`with_", "`act", "`", "`" };
	odst.assign(tmparray, tmparray + 6);

	switch (cmdindex)
	{
	case g_SCI::NOP:
	{
					   if (isource.size() != 1)
					   {
						   errmsg = SplitError("format is not \"nop\"", Vector2String(isource));
						   return false;
					   }
					   odst.clear();
					   odst.push_back("16'b0");
					   break;
	}
	case g_SCI::RTTL:
	case g_SCI::RTTR:
	{
					   if (isource.size() != 2)
					   {
						   errmsg = SplitError("format is not \"rttl/rttr regs\"", Vector2String(isource));
						   return false;
					   }
					   odst[2] = "`with_r";
					   odst[4] = "1'b1";
					   odst[5] += isource[1];
					   if (cmdindex == g_SCI::RTTR)
					   {
						   odst[1] = "`right";
					   }
					   break;
	}
	case g_SCI::SHL:
	case g_SCI::SHR:
	{
						if (isource.size() != 4)
						{
							errmsg = SplitError("format is not \"shl/shr 0/1/s nmb regs\"", Vector2String(isource));
							return false;
						}

						string flag(MyToLower(isource[1]));//获取符号
						auto flagit = find(g_SF, g_SF + g_SFN, flag);
						if (flagit == g_SF + g_SFN)//没找到
						{
							errmsg = SplitError("not find flag \"0/1/s\"", Vector2String(isource));
							return false;
						}

						odst[2] += g_SF[flagit - g_SF];
						odst[4] += isource[2];
						odst[5] += isource[3];
						if (cmdindex == g_SCI::SHR)
						{
							odst[1] = "`right";
						}
						break;
	}
	default:
	{
			   errmsg = SplitError("format is not \"nop/shl/shr/rttl/rttr ...\"", Vector2String(isource));
			   return false;
	}
	}

	return true;
}

传送的TransmitHandle:

bool AsmAlgorithm::TransmitHandle(const int cmdindex, const vector<string> &isource,
	vector<string>&odst, string &errmsg)
{//格式 ld/st regx #/&/@/_ xxx
	/*
	Ld regs # 立即数		{`ldst, `ld_drt_data, `regs, 8’h立即数}
	Ld regs & 立即地址	{`ldst, `ld_drt_addr, `regs, `立即数据地址}
	St regs & 立即地址	{`ldst, `st_drt_addr, `regs, `立即数据地址}
	Ld rega regb			{`ldst, `reg_or_ptr, `rega, `ld_reg, `regb}
	St rega regb			{`ldst, `reg_or_ptr, `rega, `st_reg, `regb}
	Ld regs @ r1r0		{`ldst, `reg_or_ptr, `regs, `ld_ptr, 4’b0}
	St regs @ r1r0		{`ldst, `reg_or_ptr, `regs, `st_ptr, 4’b0}
	*/

	odst.clear();
	errmsg.clear();

	const int isourcesize = isource.size();
	if (isourcesize != 3 && isourcesize != 4)
	{
		errmsg = SplitError("format is not \"ld/st regx #/&/@/_ xxx\"", Vector2String(isource));
		return false;
	}

	if (isourcesize == 3)
	{
		string temparray[5] = { "`ldst", "`reg_or_ptr", "`", "`ld_reg", "`" };
		odst.assign(temparray, temparray + 5);
		odst[2] += isource[1];
		odst[4] += isource[2];
		if (cmdindex==g_TCI::ST)
		{
			odst[3] = "`st_reg";
		}
		return true;
	} 
	else//4个元素
	{
		auto flagit = find(g_TF, g_TF + g_TFN, isource[2]);//查找标志
		if (flagit == g_TF + g_TFN)//没找到
		{
			errmsg = SplitError("not find flag \"#/&/@\"", Vector2String(isource));
			return false;
		}

		const int flagoffset = flagit - g_TF;//获取标志所在的偏移量
		switch (flagoffset)
		{
		case g_TFI::TWELL://#
		{
							  string temparray[4] = { "`ldst", "`ld_drt_data", "`", "8'h"};
							  odst.assign(temparray, temparray + 4);
							  odst[2] += isource[1];
							  
							  //判断是label_page还是立即数
							  const auto findpos = isource[3].rfind("_page");
							  if (findpos == string::npos)//没找到 _page
							  {
								  odst[3] += isource[3];
							  } 
							  else
							  {
								  string label = isource[3].substr(0, findpos);
								  if (g_labeladdrmap.find(label) == g_labeladdrmap.end())//查找标签
								  {//没找到
									  errmsg = SplitError("not find the label address", Vector2String(isource));
									  return false;
								  }

								  char hight8addr[20] = { 0 };
								  MySprintf(hight8addr, sizeof(hight8addr), "%02x", (char)(g_labeladdrmap[label] >> 8));
								  odst[3] += hight8addr;
							  }

							  return true;
		}
		case g_TFI::TAND://&
		{
							 string temparray[4] = { "`ldst", "`ld_drt_addr", "`", "`" };
							 odst.assign(temparray, temparray + 4);
							 odst[2] += isource[1];
							 odst[3] += isource[3];
							 
							 if (cmdindex==g_TCI::ST)
							 {
								 odst[1] = "`st_drt_addr";
							 }

							 //判断是否已存在,如果存在就不用写到寄存器地址列表中
							 string reg = isource[3];
							 auto regit = find_if(g_reglist.begin(), g_reglist.end(),
								 [reg](const pair<string, int> & item){return item.first == reg; });
							 if (regit == g_reglist.end())
							 {
								 AddRegAddr(isource[3]);//添加到寄存器地址列表中去
							 }

							 return true;
		}
		case g_TFI::TAT://@
		{
							if (MyToLower(isource[3]) != MyToLower("r1r0"))
							{
								errmsg = SplitError("not defined", Vector2String(isource));
								return false;
							}

							string temparray[5] = { "`ldst", "`reg_or_ptr", "`", "`ld_ptr", "4'b0" };
							odst.assign(temparray, temparray + 5);
							odst[2] += isource[1];
							if (cmdindex == g_TCI::ST)
							{
								odst[3] = "`st_ptr";
							}
							return true;
		}
		default:
		{
				   errmsg = SplitError("format is not \"ld/st regx #/&/@/_ xxx\"", Vector2String(isource));
				   return false;
		}
		}
	}

	return true;
}

获取私有成员变量的get函数不再列出。

8、打印结果

在主程序中,调用Handle处理完之后就可以打印信息:

//写入文件中
	switch (filelist.size())
	{
	case 5:
		cout << "macro info into " << filelist[4] << endl;
		WriteFile(filelist[4], myasm.GetMacro());
	case 4:
		cout << "macro and data info into " << filelist[3] << endl;
		WriteFile(filelist[3], myasm.GetMacroData());
	case 3:
		cout << "register info into " << filelist[2] << endl;
		WriteFile(filelist[2], myasm.GetReg());
	case 2:
		cout << "data info into " << filelist[1] << endl;
		WriteFile(filelist[1], myasm.GetData());
	default:
		break;
	}

	//打印到界面上
	cout << endl;
	for (auto it = paraset.begin(); it != paraset.end(); ++it)
	{
		switch (*it)
		{
		case g_parai::D:
			cout << "print data info :" << endl;
			cout << myasm.GetData()<<endl;
			break;
		case g_parai::R:
			cout << "print register info :" << endl;
			cout << myasm.GetReg() << endl;
			break;
		case g_parai::MD:
			cout << "print macro and data info :" << endl;
			cout << myasm.GetMacroData() << endl;
			break;
		case g_parai::M:
			cout << "print macro info :" << endl;
			cout << myasm.GetMacro() << endl;
			break;
		default:
			break;
		}
	}


9、在Win控制台和gcc下的makefile
win32:

#Win下编译
#需要vcvars32.bat环境支持
#nmake 本文件
asmtranslator.exe : main.obj asmalgorithm.obj file.obj 
	link.exe main.obj asmalgorithm.obj file.obj /out:asmtranslator.exe
	@del *.obj 
	
main.obj:main.cpp
	cl.exe /c /EHsc main.cpp
	
asmalgorithm.obj:asmalgorithm.cpp
	cl.exe /c /EHsc asmalgorithm.cpp
	
file.obj:file.cpp
	cl.exe /c /EHsc file.cpp 

这个需要vcvars32.bat的环境支持。我开始编的时候能编译过去,后来不知调整了什么就编译不过了,只能分开编译。

gcc:

#g++ build
#make -f thisfile

AsmTranslator.out: main.o asmalgorithm.o file.o
	g++ -o AsmTranslator.out main.o asmalgorithm.o file.o 
	
#clear .o file
	@rm -rf *.o

main.o: main.cpp
	g++ -std=c++11 -c main.cpp
	
asmalgorithm.o: asmalgorithm.cpp asmalgorithm.h os.h
	g++ -std=c++11 -c asmalgorithm.cpp

file.o: file.cpp file.h
	g++ -std=c++11 -c file.cpp    

10、测试:

我用1中的那个文件在gcc中使用 ./AsmTranslator.out infile.txt -d -r 测试结果如下:

----------welcome-----------------
welcom to ./AsmTranslator.out!

print data info :
16'h0000 : begin instr = {`arth,`mus,`r32_0,`r32_1}                   ;end
16'h0001 : begin instr = {`ldst,`st_drt_addr,`r64_0,`szy_data_save}   ;end
16'h0002 : begin instr = {`ldst,`ld_drt_data,`r1,8'h5a}               ;end
16'h0003 : begin instr = {`arth,`mus,`r32_0,`r32_1}                   ;end
16'h0004 : begin instr = {`ldst,`ld_drt_data,`r1,8'h5a}               ;end
16'h0005 : begin instr = {`arth,`mus,`r32_0,`r32_1}                   ;end
16'h0006 : begin instr = {`arth,`mus,`r32_0,`r32_1}                   ;end
16'h0007 : begin instr = {`ldst,`st_drt_addr,`r64_0,`szy_data_save}   ;end
16'h0008 : begin instr = {`ldst,`ld_drt_data,`r1,8'h5a}               ;end
16'h0009 : begin instr = {`arth,`mus,`r32_0,`r32_1}                   ;end
16'h000a : begin instr = {`arth,`mus,`r32_0,`r32_1}                   ;end
16'h000b : begin instr = {`ldst,`ld_drt_addr,`r64_0,`lpf_alu_result}  ;end
16'h000c : begin instr = {`brch,`drt,`cnd_nz,`jmp_next,8'h0b}         ;end
16'h000d : begin instr = {`ldst,`ld_drt_addr,`r64_0,`alu_result}      ;end
16'h000e : begin instr = {`ldst,`ld_drt_data,`r3,8'h00}               ;end
16'h000f : begin instr = {`brch,`drt,`cnd_z,`jmp_next,8'h0d}          ;end
16'h0010 : begin instr = {`arth,`mus,`r32_0,`r32_1}                   ;end
16'h0011 : begin instr = {`ldst,`st_drt_addr,`r64_0,`cic_data_save}   ;end
16'h0012 : begin instr = {`ldst,`ld_drt_data,`r1,8'h5a}               ;end
16'h0013 : begin instr = {`arth,`mus,`r32_0,`r32_1}                   ;end
16'h0014 : begin instr = {`ldst,`ld_drt_addr,`r64_0,`szy_alu_result}  ;end
16'h0015 : begin instr = {`ldst,`st_drt_addr,`r64_0,`data_save}       ;end
16'h0016 : begin instr = {`ldst,`ld_drt_data,`r1,8'h5a}               ;end

print register info :
`define szy_data_save   8'h00
`define lpf_alu_result  8'h01
`define alu_result      8'h02
`define cic_data_save   8'h03
`define szy_alu_result  8'h04
`define data_save       8'h05

----------------------------------
11、我已压缩这个工程传到 http://download.csdn.net/detail/u011311985/9405378这儿了,有需要的朋友可以下载。














评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值