欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-07-14 21:38:10
...

在看《自己动手写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汇编对应的机器码

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

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

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

我们会用到的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 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		# $<表示输入文件, aaa@qq.com表示输出文件
    $(CC) -mips32 $< -o aaa@qq.com	# $< 对应inst_rom.S,aaa@qq.com对应inst_rom.o
inst_rom.om: ram.ld $(OBJECTS)
    $(LD) -T ram.ld $(OBJECTS) -o aaa@qq.com
inst_rom.asm: inst_rom.om
    $(OBJDUMP) -D $< > aaa@qq.com
inst_rom.data: inst_rom.asm
    ./myfun.exe $< aaa@qq.com

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就可以完成所有的操作了

相关标签: 小技巧