Ubuntu中搭建MIPS编译环境

此博客为个人博客,不涉及商业用途,仅提供学习参考,内容均来自个人原创以及互联网转载和摘录。
此博客上带有原创标识的文章、图片、文件等,未经本人允许,不得用于商业用途以及传统媒体。
本文首发于优快云,其他网站均为转载。网络媒体或个人转载请注明出处和链接,否则属于侵权行为。

原博客链接:https://blog.youkuaiyun.com/qq_38305370
原博主昵称:城外南风起
————————————————

安装GNU工具链

输入以下代码检测是否安装成功。

mips-linux-gnu-gcc -v

没有的话会有相应的安装命令提示,根据提示安装即可。

编译

新建文件夹tinymips,作为工作文件夹。在该文件夹中打开terminal。
使用以下命令新建文件inst_rom.s。

touch inst_rom.s

在inst_rom.s输入以下测试程序。

.org 0x0
.global _start
.set noat
_start:
ori $1, $0, 0x1100	# $1 = $0 | 0x1100 = 0x1100
ori $2, $0, 0x0020	# $2 = $0 | 0x0020 = 0x0020
ori $3, $0, 0xff00 	# $3 = $0 | 0xff00 = 0xff00
ori $4, $0, 0xffff	# $4 = $0 | 0xffff = 0xffff

使用以下命令进行编译。其中添加了” -mips32"选项,表示按照MIPS32指令集架构进行编译。

mips-linux-gnu-as -mips32 inst_rom.s -o inst_rom.o

上述命令会得到文件inst_rom.o,是一个ELF文件。

链接

通过编译得到了一个ELF文件,但这个文件还不能执行,衙要通过链接转化为可执行文件, 然后才能执行。
使用touch命令新建一个Document作为链接描述脚本, 文件名为ram.Id,内容如下。

MEMORY
	{
	ram : ORIGIN = 0x00000000, LENGTH = 0x00001000
	}
	
SECTIONS
{
	.text :
	{
	*(.text)
	} > ram
	
	.data :
	{
	*(.data)
	} > ram
	
	.bss :
	{
	* (.bss)
	} > ram
}

ENTRY (_start)

现在就可以使用链接器了,在终端输入以下代码进行链接,得到链接后的文件inst_rom.om。

mips-linux-gnu-ld -T ram.ld inst_rom.o -o inst_rom.om

得到ROM初始化文件

inst_rom.om是一个ELF格式的可执行文件,与我们希望的指令存储器ROM初始化文件inst_rom.data 的格式有很大区别,需要进行格式转化。
利用以下命令可以将inst_rom.om转化为二进制(Binary)形式。

mips-linux-gnu-objcopy -O binary inst_rom.om inst_ron.bin

得到inst_rom.bin文件。将Bin2Mem.exe拷贝至工作文件夹,利用Bin2Mem.exe程序将其转为inst_rom.data文件,命令如下:

./Bin2Mem.exe -f inst_rom.bin -o inst_rom.data

下面给出Bin2Mem.c代码,来自@CherryYang~:Linux点点滴滴(二):在Linux上安装GNU工具链并进行编译

#include <stdlib.h>
#include <stdio.h>

char *option_invalid  = NULL;
char *option_file_in  = NULL;
char *option_file_out = NULL;

FILE *file_in_descriptor  = NULL;
FILE *file_out_descriptor = NULL;

void exception_handler(int code) {
    switch (code) {
        case 0:
            break;
        case 10001:
            printf("Error (10001): No option recognized.\n");
            printf("Please specify at least one valid option.\n");
            break;
        case 10002:
            printf("Error (10002): Invalid option: %s\n", option_invalid);
            break;
        case 10003:
            printf("Error (10003): No input Binary file specified.\n");
            break;
        case 10004:
            printf("Error (10004): Cannot open file: %s\n", option_file_in);
            break;
        case 10005:
            printf("Error (10005): Cannot create file: %s\n", option_file_out);
            break;
        default:
            break;
    }

    if (file_in_descriptor  != NULL) {
        fclose(file_in_descriptor);
    }
    if (file_out_descriptor != NULL) {
        fclose(file_out_descriptor);
    }
    exit(0);
}

int main(int argc, char **argv) {
 
    int i=0,j=0;
    unsigned char temp1,temp2,temp3,temp4;
    unsigned int option_flag = 0;

    while (argc > 0) {
        if (**argv == '-') {
            (*argv) ++;
            switch (**argv) {
                case 'f':
                    option_flag |= 0x4;
                    argv ++;
                    option_file_in = *argv;
                    argc --;
                    break;
                case 'o':
                    option_flag |= 0x8;
                    argv ++;
                    option_file_out = *argv;
                    argc --;
                    break;
                default:
                    option_flag |= 0x1;
                    (*argv) --;
                    option_invalid = *argv;
                    break;
            }
        }
        argv ++;
        argc --;
    }

    file_in_descriptor = fopen(option_file_in, "rb");
    if (file_in_descriptor == NULL) {
        exception_handler(10004);
    }

    file_out_descriptor = fopen(option_file_out, "w");
    if (file_out_descriptor == NULL) {
        exception_handler(10005);
    }
    
    while (!feof(file_in_descriptor)) {
         
            fscanf(file_in_descriptor, "%c", &temp1);
            fscanf(file_in_descriptor, "%c", &temp2);
            fscanf(file_in_descriptor, "%c", &temp3);
            fscanf(file_in_descriptor, "%c", &temp4);

            if(!feof(file_in_descriptor)) {
             fprintf(file_out_descriptor, "%02x", temp1);
             fprintf(file_out_descriptor, "%02x", temp2);
             fprintf(file_out_descriptor, "%02x", temp3);
             fprintf(file_out_descriptor, "%02x", temp4);
             fprintf(file_out_descriptor, "\n");
            } 
    }

    exception_handler(0);
    return 0;
}

编写Makefile文件

为了得到指令存储器初始化文件,我们需要输入4条命令, 点麻烦,最好只输入一条命令就可以了,这需要使用Makefile 文件。
在汇编程序inst_rom.s所在目录下新建一个Document,文件名为Makefile,内容如下。

ifndef CROSS_COMPILE
	CROSS_COMPILE = mips-linux-gnu-
endif

CC = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld

OBJCOPY = $(CROSS_COMPILE)objcopy

OBJECTS = inst_rom.o
export CROSS_COMPILE

all: inst_rom.data

%.o:%.s
	$(CC) -mips32 $< -o $@

inst_rom.om: ram.ld $(OBJECTS) 
	$(LD) -T ram.ld $(OBJECTS) -o $@

inst_rom.bin: inst_rom.om
	$(OBJCOPY) -O binary $< $@

inst_rom.data: inst_rom.bin
	./Bin2Mem.exe -f $< -o $@

clean:
	rm -f *.o *.om *.bin *.data

接下来,在终端使用以下命令安装make工具。

sudo apt install make

输入用户密码即可完成安装。
接着使用make all命令就可以通过makefile文件完成前面的四个步骤。
makefile可以通过@haoel:跟我一起写 Makefile学习。
Mecklenburg的书《MANAGING PROJECTS WITH GNU MAKE》更好。

参考

1.雷思磊著.自己动手写CPU[M].电子工业出版社,2014.
2.CherryYang~: Linux点点滴滴(二):在Linux上安装GNU工具链并进行编译
https://blog.youkuaiyun.com/qq_42650988/article/details/103532682

————————————————
感谢您的阅读,如果您有收获,请给我一个三连吧!
如果您觉得这还不够,可以点击 打赏 按钮,告诉我: 你币有了!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

城外南风起

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值