博客
关于我
用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/

    你可能感兴趣的文章
    npm,yarn,cnpm 的区别
    查看>>
    NPOI
    查看>>
    NPOI之Excel——合并单元格、设置样式、输入公式
    查看>>
    NPOI初级教程
    查看>>
    NPOI利用多任务模式分批写入多个Excel
    查看>>
    NPOI在Excel中插入图片
    查看>>
    NPOI将某个程序段耗时插入Excel
    查看>>
    NPOI格式设置
    查看>>
    NPOI设置单元格格式
    查看>>
    Npp删除选中行的Macro录制方式
    查看>>
    NR,NF,FNR
    查看>>
    nrf24l01+arduino
    查看>>
    nrf开发笔记一开发软件
    查看>>
    nrm —— 快速切换 NPM 源 (附带测速功能)
    查看>>
    nrm报错 [ERR_INVALID_ARG_TYPE]
    查看>>
    NS3 IP首部校验和
    查看>>
    NSDateFormatter的替代方法
    查看>>
    NSError 的使用方法
    查看>>
    nsis 安装脚本示例(转)
    查看>>
    NSJSON的用法(oc系统自带的解析方法)
    查看>>