博客
关于我
用C#实现一个简易的Mips汇编器
阅读量:453 次
发布时间:2019-03-05

本文共 8374 字,大约阅读时间需要 27 分钟。

Mips汇编器简易实现:基于C#开发的Mips汇编语言解析器与代码生成器

作为一名计算机专业的大二学生,我进行了一个有趣的项目——实现一个简易的Mips汇编器。这个项目不仅让我对汇编语言有了更深入的理解,还锻炼了我对软件开发的能力。以下将详细介绍我的实现过程与成果。

项目概述

Mips(Multiply-Add-shift-Program)汇编器是一种经典的单指令流控制器,广泛应用于嵌入式系统和硬件开发。由于本项目不支持外部文件引入,仅支持数据段(.data)和代码段(.text),因此我们需要直接处理这些段的内容。

系统架构设计

项目采用了模块化设计,主要包含以下几个部分:

  • Token定义:定义Mips汇编语言的基本标记。
  • 扫描器(Scanner):负责解析输入的汇编代码。
  • 指令翻译器(Instruction Translator):将汇编指令转化为机器码。
  • 代码生成与数据处理:根据用户提供的汇编代码,生成对应的机器码,并处理数据段的初始化值。
  • 核心实现模块

    1. Token定义

    Token.cs文件定义了Mips汇编语言的基本标记,包括寄存器、操作码、数据类型等。以下是部分关键定义:

    public enum BaseType{    WORD,    BYTE}public enum Instruction{    // R-type    add, addu, sub, subu, and, or, xor, nor, slt, sltu, sll, srl, sra,    sllv, srlv, srav, jr,    // I-type    addi, addiu, andi, ori, xori, sltiu, lui, lw, sw, beq, bne, bgtz,    // J-type    j, jal}public enum Register{    zero, at, v0, v1, a0, a1, a2, a3,    t0, t1, t2, t3, t4, t5, t6, t7,    s0, s1, s2, s3, s4, s5, s6, s7,    t8, t9, k0, k1, gp, sp, fp, ra}

    2. 扫描器(Scanner)

    Scanner.cs负责解析输入的汇编代码。它支持忽略空格和注释,以便提取有用的汇编指令。以下是其核心实现逻辑:

    public class Scanner{    public string CurrentString;    public string[] OpNums;    public string OpType;    public int innerLine;    public int Line;    public Scanner(string code, bool isData)    {        StreamReader = File.OpenText(code);        IsData = isData;    }    public void ScanLine()    {        CurrentString = StreamReader.ReadLine();        // 删除空行        CurrentString = CurrentString.Trim();        while (CurrentString.Length == 0)        {            Line++;            CurrentString = StreamReader.ReadLine();            if (CurrentString == null) return;            CurrentString = CurrentString.Trim();        }        // 删除整行注释        while (CurrentString.Trim().StartsWith("#"))        {            CurrentString = StreamReader.ReadLine();        }        // 删除空行        CurrentString = CurrentString.Trim();        while (CurrentString.Length == 0)        {            Line++;            CurrentString = StreamReader.ReadLine();            if (CurrentString == null) return;            CurrentString = CurrentString.Trim();        }        if (!IsData)        {            if (!CurrentString.Contains(":"))                innerLine++;        }        Line++;        // 删除一行里面的注释        List
    currentStringList = CurrentString.ToList(); int firstAnnotation = currentStringList.FindIndex(s => s == '#'); if (firstAnnotation != -1) { CurrentString = CurrentString.Substring(0, firstAnnotation); } try { int firstSpace = currentStringList.FindIndex(s => s == ' '); string opType = CurrentString.Substring(0, firstSpace); string opNum = CurrentString.Substring(firstSpace).Trim(); string[] opNums = opNum.Split(","); for (int i = 0; i < opNums.Length; i++) { opNums[i] = opNums[i].Trim(); } OpNums = opNums; OpType = opType; } catch (Exception ex) { } }}

    3. 指令翻译器(Instruction Translator)

    InstructionTranslator.cs负责将解析出的汇编指令转化为机器码。其核心逻辑包括:

    • 数据段处理:初始化变量的存储位置。
    • 代码段处理:将汇编指令转化为对应的机器码。
    • 标签处理:处理代码中的标签,生成相应的地址信息。

    以下是部分关键实现代码:

    public class InstructionTranslator{    private Dictionary
    SymbolTable; private Dictionary
    LabelTable; private FileStream DataFileStream; private FileStream TextFileStream; private FileStream TextSegCodeStream; public InstructionTranslator(string codePath) { DataFileStream = new FileStream("data.txt", FileMode.Create, FileAccess.Write); TextFileStream = new FileStream("text.txt", FileMode.Create, FileAccess.Write); TextSegCodeStream = new FileStream("textSeg.txt", FileMode.Create, FileAccess.Write); Scanner = new Scanner(codePath, true); } public void Translate() { Scanner.ScanLine(); if (Scanner.CurrentString.Contains(".data")) { BuildSymbolTable(); } BuildLabelTable(); TranslateData(); TranslateText(); } private void TranslateData() { using (StreamWriter sw = new StreamWriter(DataFileStream)) { int currentAddr = 0; foreach (KeyValuePair
    var in SymbolTable) { if (!isByte) { if (var.Value.Type == BaseType.BYTE) { var.Value.Addr = "0x" + Convert.ToString(currentAddr | 0x10010000, 16); currentAddr += 1; if (var.Value.InitVal != null) { Buffer = Buffer.Insert(0, var.Value.InitVal.Substring(var.Value.InitVal.Length - 2, 2)); } isByte = true; } else { var.Value.Addr = "0x" + Convert.ToString(currentAddr | 0x10010000, 16); currentAddr += 4; sw.WriteLine(var.Value.InitVal); } } else { if (var.Value.Type == BaseType.BYTE) { var.Value.Addr = "0x" + Convert.ToString(currentAddr | 0x10010000, 16); currentAddr += 1; if (var.Value.InitVal != null) { Buffer = Buffer.Insert(0, var.Value.InitVal.Substring(var.Value.InitVal.Length - 2, 2)); } } else { isByte = false; if (Buffer != "") { while (Buffer.Length % 8 != 0) { Buffer = Buffer.Insert(0, "0"); } int i = Buffer.Length - 8; while (i >= 0) { data = Buffer.Substring(i, 8); sw.WriteLine(data); i -= 8; } } var.Value.Addr = "0x" + Convert.ToString(currentAddr | 0x10010000, 16); currentAddr += 4; sw.WriteLine(var.Value.InitVal); Buffer = ""; } } } } } private void TranslateText() { using (StreamWriter sw = new StreamWriter(TextFileStream)) { Scanner = new Scanner("textSeg.txt", false); while (true) { string[] instruction = Scanner.CurrentString.Split(","); if (instruction.Length == 0) break; string opType = instruction[0].Trim(); string[] opNums = instruction[1].Split(","); string hexCode = TranslateSentence(opType, opNums); sw.WriteLine(hexCode); } } }}

    项目测试与验证

    为了验证这个Mips汇编器的实现,我们可以使用以下汇编代码测试:

    .text    j main_loop    beq $t1, $t2, mode_mode1    beq $t1, $t3, mode_mode2    beq $t1, $t4, mode_mode3    j main_loopmode_mode1:    lw $s3, count    lw $s4, mode1_init_rstate    lw $s5, mode1_init_lstate    addi $s6, $0, 0x00FFF000    addi $s7, $0, 0x000FFF00    beq $s3, $0, mode1_end    beq $s4, $s6, mode1_start_dark    mode1_start_light:        sll $s4, $s4, 1        srl $s5, $s5, 1        jal model1_processor        jal start_timer        addi $s3, $s3, -1        j mode1_start_light    mode1_start_dark:        beq $s3, $0, mode1_end        addi $t6, $0, 0x00000FFF        beq $s4, $t6, mode1_start_light        mode1_dark:            srl $s4, $s4, 1            sll $s5, $s5, 1            jal model1_processor            jal start_timer            addi $s3, $s3, -1            j mode1_dark    mode1_end:        j main_loopmodel1_processor:    and $t1, $s4, $s6    and $t2, $s5, $s7    srl $t1, $t1, 12    sll $t2, $t2, 4    sw $t1, t1    sw $t2, t2    add $t3, $t1, $t2    sw $t3, temp    andi $t1, $t3, 0x0000FFFF    sw $t1, 0xC60($28)    andi $t1, $t3, 0x00FF0000    srl $t1, $t1, 16    sw $t1, 0xC62($28)    jr $ramain_loop:

    总结

    通过以上实现,我们成功构建了一个简易的Mips汇编器。虽然还有许多可以改进的地方,但这是我在大学生阶段完成的首个大型软件开发项目,给予了我宝贵的学习经验。未来,我希望能够在这个领域深入研究,开发更加功能完善的Mips汇编工具。

    转载地址:http://brizz.baihongyu.com/

    你可能感兴趣的文章
    node编译程序内存溢出
    查看>>
    Node读取并输出txt文件内容
    查看>>
    node防xss攻击插件
    查看>>
    noi 1996 登山
    查看>>
    noi 7827 质数的和与积
    查看>>
    NOI-1.3-11-计算浮点数相除的余数
    查看>>
    NOI2010 海拔(平面图最大流)
    查看>>
    NOIp2005 过河
    查看>>
    NOIP2011T1 数字反转
    查看>>
    NOIP2014 提高组 Day2——寻找道路
    查看>>
    noip借教室 题解
    查看>>
    NOIP模拟测试19
    查看>>
    NOIp模拟赛二十九
    查看>>
    Vue3+element plus+sortablejs实现table列表拖拽
    查看>>
    Nokia5233手机和我装的几个symbian V5手机软件
    查看>>
    non linear processor
    查看>>
    Non-final field ‘code‘ in enum StateEnum‘
    查看>>
    none 和 host 网络的适用场景 - 每天5分钟玩转 Docker 容器技术(31)
    查看>>
    None还可以是函数定义可选参数的一个默认值,设置成默认值时实参在调用该函数时可以不输入与None绑定的元素...
    查看>>
    NoNodeAvailableException None of the configured nodes are available异常
    查看>>