寻求有关安装和使用mips gcc交叉编译器生成自定义ASM的帮助
我正在尝试为我的自定义ISA生成程序集,它类似于MIPS。我读过关于使用mips gcc交叉编译器从C程序生成mips asm,然后将其转换为我们所需的asm的内容,但当时我无法清楚地了解它。有人请给我解释一下程序,以及如何做到这一点寻求有关安装和使用mips gcc交叉编译器生成自定义ASM的帮助,c,gcc,assembly,mips,cross-compiling,C,Gcc,Assembly,Mips,Cross Compiling,我正在尝试为我的自定义ISA生成程序集,它类似于MIPS。我读过关于使用mips gcc交叉编译器从C程序生成mips asm,然后将其转换为我们所需的asm的内容,但当时我无法清楚地了解它。有人请给我解释一下程序,以及如何做到这一点 谢谢 我想你说的是二进制翻译 以这段代码为例 unsigned int fun ( unsigned int a, unsigned int b, unsigned int c ) { return((a+b)&c); } 假设我想使用mips
谢谢 我想你说的是二进制翻译 以这段代码为例
unsigned int fun ( unsigned int a, unsigned int b, unsigned int c )
{
return((a+b)&c);
}
假设我想使用mips C编译器,因为我的处理器没有编译器(在本例中,我将使用ARM只是为了演示,我们当然有ARM编译器)。此外,MIPS到ARM不是一对一的,但对于这个简单的示例,它可以很好地工作。因为ARM不使用延迟槽,所以我们要求gcc不要这样做,我们编译这个
mips-elf-gcc -O2 -c -fno-delayed-branch fun.c -o fun.o
mips-elf-objdump -D fun.o
我在作弊当然,你会想链接到某个地址,我走捷径,分解对象。翻译器首先读取MIPS二进制文件,您可能希望也可能不希望预扫描从入口点开始的指令,执行顺序遵循所有路径,并记录所有分支目的地。还要隔离哪些字节是指令,并假定哪些字节不是数据。但是,sine-mips是固定指令长度的(实际上不是这样,有一个16位的版本可以混用),你也可以采取从一开始就开始分解所有指令的方法,最终分解数据并产生额外的工作
所以我让gnu为我分解这个例子
00000000 <fun>:
0: 00851021 addu v0,a0,a1
4: 00461024 and v0,v0,a2
8: 03e00008 jr ra
c: 00000000 nop
以
addu r2 = r4 + r5
所以我们把它直接转化为arm等价物
add r2,r4,r5
第二指令
4: 00461024 and v0,v0,a2
00000000010001100001000000100100
000000 00010 00110 00010 00000 100100
000000 sssss ttttt ddddd 00000 100100 and rd,rs,rt
r2 r6 r2
and r2 = r2 & r6
8: 03e00008 jr ra
000000 11111 000000000000000 001000
000000 sssss 000000000000000 001000 jr rs
r31
jr r31 or return from function
c: 00000000 nop
手臂
第三条指令
4: 00461024 and v0,v0,a2
00000000010001100001000000100100
000000 00010 00110 00010 00000 100100
000000 sssss ttttt ddddd 00000 100100 and rd,rs,rt
r2 r6 r2
and r2 = r2 & r6
8: 03e00008 jr ra
000000 11111 000000000000000 001000
000000 sssss 000000000000000 001000 jr rs
r31
jr r31 or return from function
c: 00000000 nop
手臂
第四条指令
4: 00461024 and v0,v0,a2
00000000010001100001000000100100
000000 00010 00110 00010 00000 100100
000000 sssss ttttt ddddd 00000 100100 and rd,rs,rt
r2 r6 r2
and r2 = r2 & r6
8: 03e00008 jr ra
000000 11111 000000000000000 001000
000000 sssss 000000000000000 001000 jr rs
r31
jr r31 or return from function
c: 00000000 nop
手臂
因此,对于这四条mips指令,我们有一个到arm的直接静态二进制翻译
add r2,r4,r5
and r2,r2,r6
bx lr
nop
现在你可以做两件事之一,你可以在每个指令上贴上标签,然后是if/when
有一个分支,您可以分支该标签,或者为了清洁,您可以预览所有代码
并查找分支目的地,仅标记这些目的地。使用mips地址创建标签,使跟踪更容易
L00000000: add r2,r4,r5
L00000004: and r2,r2,r6
L00000008: bx lr
L0000000C: nop
在本例中,我创建了arm汇编语言,并将其输入
arm-none-eabi-as fun.s -o fun.o
arm-none-eabi-objdump -D fun.o
fun.o: file format elf32-littlearm
Disassembly of section .text:
00000000 <L00000000>:
0: e0842005 add r2, r4, r5
00000004 <L00000004>:
4: e0022006 and r2, r2, r6
00000008 <L00000008>:
8: e12fff1e bx lr
0000000c <L0000000C>:
c: e1a00000 nop ; (mov r0, r0)
如果我的目标有一个优化C编译器,但它不是一个mips目标,我只有一个我正在翻译的mips二进制文件,我没有原始源代码,然后翻译成类似的东西
...
unsigned int r2;
...
unsigned int r3;
unsigned int r4;
unsigned int r5;
unsigned int r6;
...
unsigned int PC;
switch(PC)
{
...
case L00000000:
L00000000:
r2=r4+r5;
r2=r2&r6;
PC=0x00000008;
break;
...
}
在这个开关周围包装一些代码来管理函数调用的进入和退出。当然,还有很多工作我没有描述
我知道使用链接是一种不好的方式,但格雷厄姆·托尔写了一个静态二进制翻译,你可以在谷歌上搜索并希望找到它,希望它仍然存在
当然,如果您的指令集非常接近mips,那么为什么不修改binutils使其对您的指令进行编码,或者修改gcc使其在汇编语言上生成变体呢?我假设您所说的是二进制翻译 以这段代码为例
unsigned int fun ( unsigned int a, unsigned int b, unsigned int c )
{
return((a+b)&c);
}
假设我想使用mips C编译器,因为我的处理器没有编译器(在本例中,我将使用ARM只是为了演示,我们当然有ARM编译器)。此外,MIPS到ARM不是一对一的,但对于这个简单的示例,它可以很好地工作。因为ARM不使用延迟槽,所以我们要求gcc不要这样做,我们编译这个
mips-elf-gcc -O2 -c -fno-delayed-branch fun.c -o fun.o
mips-elf-objdump -D fun.o
我在作弊当然,你会想链接到某个地址,我走捷径,分解对象。翻译器首先读取MIPS二进制文件,您可能希望也可能不希望预扫描从入口点开始的指令,执行顺序遵循所有路径,并记录所有分支目的地。还要隔离哪些字节是指令,并假定哪些字节不是数据。但是,sine-mips是固定指令长度的(实际上不是这样,有一个16位的版本可以混用),你也可以采取从一开始就开始分解所有指令的方法,最终分解数据并产生额外的工作
所以我让gnu为我分解这个例子
00000000 <fun>:
0: 00851021 addu v0,a0,a1
4: 00461024 and v0,v0,a2
8: 03e00008 jr ra
c: 00000000 nop
以
addu r2 = r4 + r5
所以我们把它直接转化为arm等价物
add r2,r4,r5
第二指令
4: 00461024 and v0,v0,a2
00000000010001100001000000100100
000000 00010 00110 00010 00000 100100
000000 sssss ttttt ddddd 00000 100100 and rd,rs,rt
r2 r6 r2
and r2 = r2 & r6
8: 03e00008 jr ra
000000 11111 000000000000000 001000
000000 sssss 000000000000000 001000 jr rs
r31
jr r31 or return from function
c: 00000000 nop
手臂
第三条指令
4: 00461024 and v0,v0,a2
00000000010001100001000000100100
000000 00010 00110 00010 00000 100100
000000 sssss ttttt ddddd 00000 100100 and rd,rs,rt
r2 r6 r2
and r2 = r2 & r6
8: 03e00008 jr ra
000000 11111 000000000000000 001000
000000 sssss 000000000000000 001000 jr rs
r31
jr r31 or return from function
c: 00000000 nop
手臂
第四条指令
4: 00461024 and v0,v0,a2
00000000010001100001000000100100
000000 00010 00110 00010 00000 100100
000000 sssss ttttt ddddd 00000 100100 and rd,rs,rt
r2 r6 r2
and r2 = r2 & r6
8: 03e00008 jr ra
000000 11111 000000000000000 001000
000000 sssss 000000000000000 001000 jr rs
r31
jr r31 or return from function
c: 00000000 nop
手臂
因此,对于这四条mips指令,我们有一个到arm的直接静态二进制翻译
add r2,r4,r5
and r2,r2,r6
bx lr
nop
现在你可以做两件事之一,你可以在每个指令上贴上标签,然后是if/when
有一个分支,您可以分支该标签,或者为了清洁,您可以预览所有代码
并查找分支目的地,仅标记这些目的地。使用mips地址创建标签,使跟踪更容易
L00000000: add r2,r4,r5
L00000004: and r2,r2,r6
L00000008: bx lr
L0000000C: nop
在本例中,我创建了arm汇编语言,并将其输入
arm-none-eabi-as fun.s -o fun.o
arm-none-eabi-objdump -D fun.o
fun.o: file format elf32-littlearm
Disassembly of section .text:
00000000 <L00000000>:
0: e0842005 add r2, r4, r5
00000004 <L00000004>:
4: e0022006 and r2, r2, r6
00000008 <L00000008>:
8: e12fff1e bx lr
0000000c <L0000000C>:
c: e1a00000 nop ; (mov r0, r0)
如果我的目标有一个优化C编译器,但它不是一个mips目标,我只有一个我正在翻译的mips二进制文件,我没有原始源代码,然后翻译成类似的东西
...
unsigned int r2;
...
unsigned int r3;
unsigned int r4;
unsigned int r5;
unsigned int r6;
...
unsigned int PC;
switch(PC)
{
...
case L00000000:
L00000000:
r2=r4+r5;
r2=r2&r6;
PC=0x00000008;
break;
...
}
在这个开关周围包装一些代码来管理函数调用的进入和退出。当然,还有很多工作我没有描述
我知道使用链接是一种不好的方式,但格雷厄姆·托尔写了一个静态二进制翻译,你可以在谷歌上搜索并希望找到它,希望它仍然存在
当然,如果您的指令集非常接近mips,那么为什么不修改binutils使其对您的指令进行编码,或者修改gcc使其在汇编语言上生成变体呢?我假设您所说的是二进制翻译 以这段代码为例
unsigned int fun ( unsigned int a, unsigned int b, unsigned int c )
{
return((a+b)&c);
}
假设我想使用mips C编译器,因为我的处理器没有编译器(在本例中)