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

📄 assembler.java.svn-base

📁 北航编译原理课程设计成果——一个扩充的C0文法编译器
💻 SVN-BASE
字号:
package cn.edu.buaa.scse.liyi.compile.tools;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.util.LinkedList;
import java.util.Vector;

import cn.edu.buaa.scse.liyi.compile.types.*;

/**
 * 
 * @author liyi
 */
public class Assembler
{
	private Vector<Constant> global_const=null;
	private Vector<String> global_var=null;
	private LinkedList<Function> funcList=null;
	private Vector<String> output=null;				//汇编输出
	private Function func=null;						//当前函数
	private int pcount=0;							//参数计数
	private String condition=null;
	private Vector<String> strlist=null;			//printf用字符串表
	private int stc=0;								//字符串计数
	private String outputpath;
	private String warn=null;
	
	/**
	 * 汇编代码生成器构造方法
	 * @param global_const
	 * @param global_var
	 * @param funcList
	 * @param outputpath
	 */
	public Assembler(Vector<Constant> global_const,Vector<String> global_var,LinkedList<Function> funcList,String outputpath)
	{
		this.funcList=funcList;
		this.global_const=global_const;
		this.global_var=global_var;
		this.output=new Vector<String>();
		this.strlist=new Vector<String>();
		this.outputpath=outputpath;
		strlist.add("@_IO_DATA dword ?");
		strlist.add("@_IO_STR byte \"%d\", 0");
		strlist.add("@_NEWLINE byte 0dh,0ah,0");
	}
	
	public void setGlobal_const(Vector<Constant> global_const)
	{
		this.global_const=global_const;
	}
	public Vector<Constant> getGlobal_const()
	{
		return global_const;
	}

	public void setGlobal_var(Vector<String> global_var)
	{
		this.global_var=global_var;
	}
	public Vector<String> getGlobal_var()
	{
		return global_var;
	}
	
	public void setOutput(Vector<String> output)
	{
		this.output=output;
	}
	public Vector<String> getOutput()
	{
		return output;
	}
	
	public void setStrlist(Vector<String> strlist)
	{
		this.strlist=strlist;
	}
	public Vector<String> getStrlist()
	{
		return strlist;
	}
	
	public void setWarn(String warn)
	{
		this.warn=warn;
	}
	public String getWarn()
	{
		return warn;
	}

/********************************************************************************************/
	
	//给出该参数或变量的地址表示,若为全局变量则返回原字符串
	private String findAddress(String ss)
	{
		Integer i;
		i=func.getPmap().get(ss);			//在参数表里找
		if(i!=null)
		{
			return "[ebp + "+i+" ]";
		}
		i=func.getVmap().get(ss);
		if(i!=null)
		{									//再在变量表里找
			return "[ebp - "+i+" ]";
		}
		if(ss.equals("@teax"))
		{									//若取函数调用的返回值则译为eax
			return "eax";
		}
		
		if((ss.charAt(0)>='0'&&ss.charAt(0)<='9')||ss.charAt(0)=='-')
		{									//当为全局常量时返回原数字
			return ss;					   
		}
		else
		{
			return "$"+ss;					//当为全局变量时直接返回加$的字符串
		}
											  
	}

	public void generateCode()
	{
		FileWriter fw=null;


		for(Function func:this.funcList)
		{									//遍历所有函数
			this.func=func;									//ff存当前函数,以为后面方法调用从中获得数据
			int space=(this.func.getVmap().size()+4)*4;		//算出函数调用需要的保留区大小,存为space
			output.add("@f"+func.getName()+":");			//写入汇编函数头
			output.add("push ebp");
			output.add("mov ebp,esp");
			output.add("sub esp,"+space);

			for(Quaternion quater:func.getQuaterList())
			{									//遍历该函数的所有四元式
				switch (quater.getOperator())
				{								//根据四元式的操作符op,转入相应的方法去添加对应的汇编代码
					case Yacc.ADD:
						add(quater);
						break;
					case Yacc.SUB:
						sub(quater);
						break;
					case Yacc.MUL:
						mul(quater);
						break;
					case Yacc.DIV:
						div(quater);
						break;
					case Yacc.MOV:
						mov(quater);
						break;
					case Yacc.CALL:
						call(quater);
						break;
					case Yacc.CMP:
						cmp(quater);
						break;
					case Yacc.CONDITION:
						condition(quater);
						break;
					case Yacc.J:
						j(quater);
						break;
					case Yacc.JFALSE:
						jfalse(quater);
						break;
					case Yacc.PRINTF:
						print(quater);
						break;
					case Yacc.PUSHPARA:
						pushpara(quater);
						break;
					case Yacc.RETURN:
						ret(quater);
						break;
					case Yacc.SCANF:
						scan(quater);
						break;
					case Yacc.STAMP:
						stamp(quater);
						break;
					default:
						break;
					}
			}
			if(func.getQuaterList().getLast().getOperator()!=Yacc.RETURN)
			{							//检查是否有返回语句,若没有自动添加,并向用户发出警告
				warn="Warning:Return Missing!";
				output.add("mov esp,ebp");
				output.add("pop ebp");
				output.add("ret");
			}
		}
		if(!"main".equals(funcList.getLast().getName()))
		{
			warn="Warning: 找不到main函数!";
		}
		else if(funcList.getLast().getRetype()==-1)
		{
			warn="Warning: main函数的返回类型没有定义!";
		}

		File ofile=new File(outputpath);			//汇编输出文件
		try
		{
			ofile.createNewFile();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
		try
		{
			fw=new FileWriter(ofile);
			fw.write(".386\n");
			fw.write(".MODEL FLAT\n");
			fw.write("includelib msvcrt.lib\n");
			fw.write("puts proto C\n");
			fw.write("printf proto C\n");
			fw.write("scanf proto C\n");
			fw.write(".STACK 4096\n");
			fw.write(".DATA\n");
			for(String s:this.global_var)
			{
				fw.write("$"+s+" DWORD 0\n");
			}
			for(String s:strlist)
			{
				fw.write(s+'\n');
			}
			
			fw.write(".CODE\n");
			for(String s:output)
			{
				fw.write(s+'\n');
			}
			fw.write("_main:\n");
			fw.write("jmp near ptr @fmain\n");
			fw.write("end _main\n");
			fw.flush();
			fw.close();
		}
		catch(FileNotFoundException e)
		{
			e.printStackTrace();
		}
		catch(IOException e)
		{
			e.printStackTrace();
		}

	}
	
	/**
	 * 加法操作
	 * @param quater
	 */
	private void add(Quaternion quater)
	{
		output.add("mov eax, "+findAddress(quater.getOperend1()));
		output.add("add eax, "+findAddress(quater.getOperend2()));
		output.add("mov "+findAddress(quater.getResult())+", eax");
	}
	
	/**
	 * 函数调用操作
	 * @param quater
	 */
	private void call(Quaternion quater)
	{
		output.add("call "+"@f"+quater.getOperend1());
		output.add("add esp, "+(pcount*4));
		pcount=0;
	}
	
	/**
	 * 比较操作
	 * @param quater
	 */
	private void cmp(Quaternion quater)
	{
		output.add("mov eax, "+findAddress(quater.getOperend1()));
		output.add("cmp eax, "+findAddress(quater.getOperend2()));
	}
	
	/**
	 * 将应满足的条件存入condition字段,使后面的跳转语句可以确定其条件
	 * @param quater
	 */
	private void condition(Quaternion quater)
	{
		condition=quater.getOperend1();
	}
	
	/**
	 * 除法操作
	 * @param quater
	 */
	private void div(Quaternion quater)
	{
		output.add("mov eax, "+findAddress(quater.getOperend1()));
		output.add("cdq");
		output.add("mov ecx, "+findAddress(quater.getOperend2()));
		output.add("idiv ecx");
		output.add("mov "+findAddress(quater.getResult())+", eax");
	}
	
	/**
	 * 无条件跳转操作
	 * @param quater
	 */
	private void j(Quaternion quater)
	{
		output.add("jmp near ptr @l"+quater.getOperend1());
	}
	
	/**
	 * 不满足条件时的跳转操作
	 * @param quater
	 */
	private void jfalse(Quaternion quater)
	{
		switch(new Integer(condition).intValue())
		{
			case Lex.EE:
				output.add("jne near ptr @l"+quater.getOperend1());
				break;
			case Lex.NE:
				output.add("je near ptr @l"+quater.getOperend1());
				break;
			case Lex.G:
				output.add("jle near ptr @l"+quater.getOperend1());
				break;
			case Lex.L:
				output.add("jge near ptr @l"+quater.getOperend1());
				break;
			case Lex.GE:
				output.add("jl near ptr @l"+quater.getOperend1());
				break;
			case Lex.LE:
				output.add("jg near ptr @l"+quater.getOperend1());
				break;
		}
		condition=null;
	}
	
	/**
	 * 赋值操作
	 * @param quater
	 */
	private void mov(Quaternion quater)
	{
		output.add("mov eax, "+findAddress(quater.getOperend1()));
		output.add("mov "+findAddress(quater.getResult())+", eax");
	}
	
	/**
	 * 乘法操作
	 * @param quater
	 */
	private void mul(Quaternion quater)
	{
		output.add("mov eax, "+findAddress(quater.getOperend1()));
		output.add("mov ecx, "+findAddress(quater.getOperend2()));
		output.add("imul ecx");
		output.add("mov "+findAddress(quater.getResult())+", eax");
	}
	
	/**
	 * 打印操作
	 * @param quater
	 */
	private void print(Quaternion quater)
	{
		String strname="@str"+stc;
		switch (new Integer(quater.getResult()))
		{
			case 0:
				// string
				strlist.add(strname+" byte "+quater.getOperend1()+",0");
				stc++;
				output.add("lea eax, "+strname);
				output.add("push eax");
				output.add("call puts");
				output.add("add esp, 4");
				break;
			case 1:
				// integer
				output.add("mov eax,"+findAddress(quater.getOperend2()));
				output.add("push eax");
				output.add("lea eax, @_IO_STR");
				output.add("push eax");
				output.add("call printf");
				output.add("add esp, 8");
				break;
			case 2:
				// both
				/*
				st.add(strname+" BYTE "+four.first+",0");
				stc++;
				output.add("mov eax,"+findAddress(four.last));
				output.add("push eax");
				output.add("lea eax, "+strname);
				output.add("push eax");
				output.add("call printf");
				output.add("add esp, 8");
				 */
				strlist.add(strname+" BYTE "+quater.getOperend1()+",0");
				stc++;
				output.add("lea eax, "+strname);
				output.add("push eax");
				output.add("call puts");
				output.add("add esp, 4");

				output.add("mov eax, "+findAddress(quater.getOperend2()));
				output.add("push eax");
				output.add("lea eax, @_IO_STR");
				output.add("push eax");
				output.add("call printf");
				output.add("add esp, 8");
				break;
		}
		output.add("lea eax,@_NEWLINE");
		output.add("push eax");
		output.add("call printf");
		output.add("add esp, 4");
	}
	
	/**
	 * 将参数压入运行栈操作
	 * @param quater
	 */
	private void pushpara(Quaternion quater)
	{
		output.add("push "+findAddress(quater.getOperend1()));
		pcount++;
	}
	
	/**
	 * 返回操作
	 * @param quater
	 */
	private void ret(Quaternion quater)
	{
		if (quater.getOperend1() != null)
		{
			output.add("mov eax, "+findAddress(quater.getOperend1()));
		}
		output.add("mov esp,ebp");
		output.add("pop ebp");
		output.add("ret");
	}
	
	/**
	 * 读取操作
	 * @param quater
	 */
	private void scan(Quaternion quater)
	{
		output.add("lea eax, @_IO_DATA");
		output.add("push eax");
		output.add("lea eax, @_IO_STR");
		output.add("push eax");
		output.add("call scanf");
		output.add("add esp, 8");

		output.add("mov eax, @_IO_DATA");
		output.add("mov "+findAddress(quater.getOperend1())+", eax");
	}
	
	/**
	 * 标签
	 * @param quater
	 */
	private void stamp(Quaternion quater)
	{
		output.add("@l"+quater.getOperend1()+" :");
	}
	
	/**
	 * 减法操作
	 * @param quater
	 */
	private void sub(Quaternion quater)
	{
		output.add("mov eax, "+findAddress(quater.getOperend1()));
		output.add("sub eax, "+findAddress(quater.getOperend2()));
		output.add("mov "+findAddress(quater.getResult())+", eax");
	}
}

⌨️ 快捷键说明

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