如何获取MIPS汇编对应的机器码

在看《自己动手写CPU》的时候,里面需要将MIPS转换成机器码作为输入的指令,不过书上的工具以及一些步骤在实际中是不能用的,因此在这里将“从MIPS汇编转换成机器码”的完整过程下来

安装Linux虚拟机

因为汇编工具需要在Linux的环境下运行,所以需要安装Linux虚拟机,我用的软件是VMware,Linux系统是Ubuntu 18.04,具体的安装过程网上有很多教程,这里就不再详细的叙述了

安装GNU工具链

下载

百度云下载链接:https://pan.baidu.com/s/13RMZTfJNdQwe6hTz2S8Ndw
提取码:9z9w

添加环境变量

下载完成解压之后,在根目录使用vi .bashrc修改.bashrc的内容,在最后一行添加 export PATH=“$PATH:[工具链解压路径]/bin”,如下图所示

如何获取MIPS汇编对应的机器码_第1张图片

添加完成之后重启系统,重启完成后打开终端输入mips-linux-gnu-,然后按两次tab键就会列出刚刚安装的所有编译工具

如何获取MIPS汇编对应的机器码_第2张图片

这样,安装就算完成了,如果没有出现编译工具,那么应该是环境变量没有添加成功,请自行在网上搜索如何添加环境变量

我们会用到的GNU汇编工具

(前面都有mips-linux-gnu-前缀)

as: GNU汇编器,用来将汇编程序编译为目标文件

ld: GNU链接器,将目标文件通过ld链接、重定位数据生成可执行文件

objdump: 用于列出关于二进制文件的各种信息

使用GNU工具链进行编译

新建一个汇编程序文件

文件名为inst_rom.S(因为我是用来生成指令的,你可以替换为相应的文件),文件内容如下:

.org 0x0		#程序从地址0x0开始
.global _start	#定义一个全局符号 _start
.set noat		#允许使用寄存器 $1
_start:
    ori $1,$0,0xf
    mtc0 $1,$11,0x0

    lui $1,0x1000
    ori $1,$1,0x401
    mtc0 $1,$12,0x0
    mfc0 $2,$12,0x0

_loop:
    j _loop
    sync

一个简单的mips汇编程序

编译

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

使用 as 来进行编译,“-mips32” 选项表示按照MIPS32 指令集架构进行编译,”-o” 选项用于指令生成的目标文件

链接

使用 ld 来进行链接,在 ld 的参数中需要声明一个链接描述脚本,链接描述脚本用于描述输入文件各个Section如何映射到输出文件的各个Section中,并控制输出文件中Section和符号的内存布局

新建一个链接描述脚本文件

文件名为 ram.ld,文件内容如下:

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

	.data :
	{
		*(.data)
	} > ram

	.bss :
	{
		*(.bss)
	} > ram
}

ENTRY (_start)

其中定义了一个存储块——ram,并且权限为wrx,wrx在Linux中表示可读、可写以及可运行(我个人的理解,并且没有这个就不能使用),其起始地址为0x0,长度为0x1000,然后只是编译器输出文件包含三个Section,分别是 .text、.data、.bss,这三个Section从ram的起始地址开始依次存放,并且与输入文件中的这三个Section意义对应,最后的ENTRY指定程序的入口地址,也就是前面汇编程序中定义的那个全局符号 _start

链接

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

得到对应的机器码

获取反编译文件

mips-linux-gnu-objdump -D inst_rom.om > inst_rom.asm

书上是用的 objcopy得到 二进制文件,然后用他的那个工具从中提取出机器码的内容,因为我是看的电子书,没有光盘,在网上也没找到那个小程序,所以只能改为使用 objdump 获取反编译文件

利用小程序提取机器码

小程序的获取:百度云链接:https://pan.baidu.com/s/1uFx2Oae7EMfTz_M0a9hMRA
提取码:2fh3

./myfun.exe inst_rom.asm inst_rom.data

最后生成的inst_rom.data中就是我们需要的机器码文件了

通过Makefile来简化操作

从一个汇编程序打机器码文件,需要四步操作:编译、链接、反编译、提取,有些繁琐,如果对输入文件以及输出文件的名称没有要求的话,可以使用Makefile来简化操作,如果有要求,也可以通过修改Makefile来完成操作,相对来说也很简便

编写Makefile文件

新建一个文件,名为Makefile,文件内容如下

ifndef CROSS_COMPILE                              
CROSS_COMPILE = mips-linux-gnu-
endif
CC = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
OBJDUMP = $(CROSS_COMPILE)objdump
OBJECTS = inst_rom.o
export CROSS_COMPILE
# 前面的应该都好理解,就是一些别名
all:inst_rom.data			# 最后要获取的文件
inst_rom.o: inst_rom.S		# $<表示输入文件, $@表示输出文件
    $(CC) -mips32 $< -o $@	# $< 对应inst_rom.S,$@对应inst_rom.o
inst_rom.om: ram.ld $(OBJECTS)
    $(LD) -T ram.ld $(OBJECTS) -o $@
inst_rom.asm: inst_rom.om
    $(OBJDUMP) -D $< > $@
inst_rom.data: inst_rom.asm
    ./myfun.exe $< $@

build:
    touch inst_rom.data
clean:	# make clean时清除以下文件
    rm -f *.o *.om *.asm *.data

在makefile中最后要获取的是inst_rom.data文件,而获取inst_rom.data需要inst_rom.asm文件,所以执行 ./myfun 那一步操作,而inst_rom.asm需要inst_rom.om ,以此类推依次执行makefile中的内容

以后在命令行使用make就可以完成所有的操作了

你可能感兴趣的:(小技巧)