寻求有关安装和使用mips gcc交叉编译器生成自定义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

我正在尝试为我的自定义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 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编译器,因为我的处理器没有编译器(在本例中)