Is there a way to use gcc to convert C to MIPS?

2020-01-25 02:00发布

问题:

I completed a C to MIPS conversion for a class, and I want to check it against the assembly. I have heard that there is a way of configuring gcc so that it can convert C code to the MIPS architecture rather than the x86 architecture (my computer users an Intel i5 processor) and prints the output.

Running the terminal in Ubuntu (which comes with gcc), what command do I use to configure gcc to convert to MIPS? Is there anything I need to install as well?

EDIT: Let me clarify. Please read this. I'm not looking for which compiler to use, or people saying "well you could cross-compile, but instead you should use this other thing that has no instructions on how to set up."

If you're going to post that, at least refer me to instructions. GCC came with Ubuntu. I don't have experience on how to install compilers and it's not easy finding online tutorials for anything other than GCC. Then there's the case of cross-compiling I need to know about as well. Thank you.

回答1:

GCC can produce assembly code for a large number of architectures, include MIPS. But what architecture a given GCC instance targets is decided when GCC itself is compiled. The precompiled binary you will find in an Ubuntu system knows about x86 (possibly both 32-bit and 64-bit modes) but not MIPS.

Compiling GCC with a target architecture distinct from the architecture on which GCC itself will be running is known as preparing a cross-compilation toolchain. This is doable but requires quite a bit of documentation-reading and patience; you usually need to first build a cross-assembler and cross-linker (GNU binutils), then build the cross-GCC itself.

I recommend using buildroot. This is a set of scripts and makefiles designed to help with the production of a complete cross-compilation toolchain and utilities. At the end of the day, you will get a complete OS and development tools for a target system. This includes the cross-compiler you are after.

Another quite different solution is to use QEMU. This is an emulator for various processors and systems, including MIPS systems. You can use it to run a virtual machine with a MIPS processor, and, within that machine, install an operating system for MIPS, e.g. Debian, a Linux distribution. This way, you get a native GCC (a GCC running on a MIPS system and producing code for MIPS).

The QEMU way might be a tad simpler; using cross-compilation requires some understanding of some hairy details. Either way, you will need about 1 GB of free disk space.



回答2:

It's not a configuration thing, you need a version of GCC that cross-compiles to MIPS. This requires a special GCC build and is quite hairy to set up (building GCC is not for the faint of heart).

I'd recommend using LCC for this. It's way easier to do cross-compilation with LCC than it is with GCC, and building LCC is a matter of seconds on current machines.



回答3:

You would need to download the source to binutils and gcc-core and compile with something like ../configure --target=mips .... You may need to choose a specific MIPS target. Then you could use mips-gcc -S.



回答4:

You can cross-compile the GCC so that it generates MIPS code instead of x86. That's a nice learning experience.

If you want quick results you can also get a prebuilt GCC with MIPS support. One is the CodeSourcery Lite Toolchain. It is free, comes for a lot of architectures (including MIPS) and they have ready to use binaries for Linux and Windows.

http://www.codesourcery.com/sgpp/lite/mips/portal/subscription?@template=lite



回答5:

You should compile your own version of gcc which is able to cross-compile. Of course this ain't easy, so you could look for a different approach.. for example this SDK.



回答6:

You should install a cross-compiler from the Ubuntu repositories. There are four GCC MIPS C cross-compilers provided in the repositories. Pick according to your needs:

  • gcc-mips-linux-gnu - 32-bit big-endian.
  • gcc-mipsel-linux-gnu - 32-bit little-endian.
  • gcc-mips64-linux-gnuabi64 - 64-bit big-endian.
  • gcc-mips64el-linux-gnuabi64 - 64-bit little-endian.

(Note for Debian users: if you usually like to install your regular compilers using the build-essential package, you would be interested to know of the existence of crossbuild-essential-mips, crossbuild-essential-mipsel and crossbuild-essential-mips64el)

In the following examples, I will assume that you chose the 32-bit little-endian version (sudo apt-get install gcc-mipsel-linux-gnu). The commands for other MIPS versions are similar.

To deal with MIPS instead of the native architecture of your system, use the mipsel-linux-gnu-gcc command instead of gcc. For example, mipsel-linux-gnu-gcc -fverbose-asm -S myprog.c produces a file myprog.s containing MIPS assembly.

Another way to see the MIPS assembly: run mipsel-linux-gnu-gcc -g -c myprog.c to produce an object file myprog.o that contains debugging information. Then view the disassembly of the object file using mipsel-linux-gnu-objdump -d -S myprog.o. For example, if myprog.c is this:

#include <stdio.h>

int main()
{
    int a = 1;
    int b = 2;
    printf("The answer is: %d\n", a + b);
    return 0;
}

And if it is compiled using mipsel-linux-gnu-gcc -g -c myprog.c, then mipsel-linux-gnu-objdump -d -S myprog.o will show something like this:

myprog.o:     file format elf32-tradlittlemips


Disassembly of section .text:

00000000 <main>:
#include <stdio.h>

int main() {
   0:   27bdffd8    addiu   sp,sp,-40
   4:   afbf0024    sw  ra,36(sp)
   8:   afbe0020    sw  s8,32(sp)
   c:   03a0f025    move    s8,sp
  10:   3c1c0000    lui gp,0x0
  14:   279c0000    addiu   gp,gp,0
  18:   afbc0010    sw  gp,16(sp)
    int a = 1;
  1c:   24020001    li  v0,1
  20:   afc20018    sw  v0,24(s8)
    int b = 2;
  24:   24020002    li  v0,2
  28:   afc2001c    sw  v0,28(s8)
    printf("The answer is: %d\n", a + b);
  2c:   8fc30018    lw  v1,24(s8)
  30:   8fc2001c    lw  v0,28(s8)
  34:   00621021    addu    v0,v1,v0
  38:   00402825    move    a1,v0
  3c:   3c020000    lui v0,0x0
  40:   24440000    addiu   a0,v0,0
  44:   8f820000    lw  v0,0(gp)
  48:   0040c825    move    t9,v0
  4c:   0320f809    jalr    t9
  50:   00000000    nop
  54:   8fdc0010    lw  gp,16(s8)
    return 0;
  58:   00001025    move    v0,zero
}
  5c:   03c0e825    move    sp,s8
  60:   8fbf0024    lw  ra,36(sp)
  64:   8fbe0020    lw  s8,32(sp)
  68:   27bd0028    addiu   sp,sp,40
  6c:   03e00008    jr  ra
  70:   00000000    nop
    ...