0

I want to transfer c codes into MIPS which can be ran in QTSpim. For example: Convert

#include<stdio.h>

int main() {
   printf("Hello, World!");
   return 0;
}

into

.data
msg:   .asciiz "Hello World"
    .extern foobar 4

        .text
        .globl main
main:   li $v0, 4       # syscall 4 (print_str)
        la $a0, msg     # argument: string
        syscall         # print the string
        lw $t1, foobar
        
        jr $ra          # retrun to caller

I tried gcc -S helloWorld.c in my mac, then I got helloWorld.s below:

.section    __TEXT,__text,regular,pure_instructions
    .build_version macos, 11, 0 sdk_version 11, 3
    .globl  _main                           ## -- Begin function main
    .p2align    4, 0x90
_main:                                  ## @main
    .cfi_startproc
## %bb.0:
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register %rbp
    subq    $16, %rsp
    movl    $0, -4(%rbp)
    leaq    L_.str(%rip), %rdi
    movb    $0, %al
    callq   _printf
    xorl    %ecx, %ecx
    movl    %eax, -8(%rbp)                  ## 4-byte Spill
    movl    %ecx, %eax
    addq    $16, %rsp
    popq    %rbp
    retq
    .cfi_endproc
                                        ## -- End function
    .section    __TEXT,__cstring,cstring_literals
L_.str:                                 ## @.str
    .asciz  "Hello, World!"

.subsections_via_symbols

I have searched a few but there are no clear answers for that. I am quite new to MIPS as I found there are a lot of assembly languages of MIPS? Any explanation or solution will be appreciated. Thanks in advance.

  • You haven't asked any question – Eugene Sh. Jun 04 '21 at 14:45
  • Probably there were no clear answers because you haven't formulated a clear question. Are you asking how to cross-compile for MIPS? Or why the compiler generated more output than you expected? – Useless Jun 04 '21 at 14:46
  • You won't be able to take GCC output and run it in QtSPIM as-is. QtSPIM only supports a subset of the directives that GCC supports. It also doesn't have libc (so no `printf` etc), and instead provides you with [a bunch of system calls](https://www.doc.ic.ac.uk/lab/secondyear/spim/node8.html). You could use the GCC output as a starting point, but it's going to take some manual editing to get it running in QtSPIM. – Michael Jun 04 '21 at 14:51

1 Answers1

0

The popular simulators, MARS and QTSpim, have their own environment, which is to say, they don't have printf and getChar.

Instead they use syscalls for I/O.  The syscalls are not a complete programming environment, so while they can do some things that printf can do, they do not have many features (for example, features of sprintf are wholly missing).

Here's the documentation for the syscalls available in MARS (QTSPim supports the first set of these but not the higher numbered ones.)

http://courses.missouristate.edu/kenvollmar/mars/help/syscallhelp.html

To translate a printf statement into syscall form, we need to decompose somewhat:

printf ( "hello %d\n", 10 ); 

would become three different syscalls:

  1. print "hello " — using syscall #4 (print string)
  2. print 10 — using syscall #1 (print integer)
  3. print "\n" — using syscall #4 (print string), or, syscall #11 (print character)

Next what you need to understand is that syscalls themselves are a bit like function calls, so we need to understand parameter passing.  Syscalls take in $v0 a function code that says what operation to perform.  Each function interprets the values of $a0, $a1, etc.. according to its specification in the above link.

Values need to be placed into the registers for parameter passing, but the ordering of placement of values into the registers is arbitrary — so as long as $v0 has 4 and $a0 has a pointer to a string in memory, then syscall instruction will print that string.


I don't know of any compiler that will automatically translate printf statements into the form needed for MARS/QTSpim.  However, the available compilers (e.g. godbolt.org has several MIPS compilers available) are generally good for showing assembly translation of non-I/O C statements and expressions (though their output is noisy for what the simulators want).


Programming for the simulators is often simplified.  Local variables, especially arrays, are often done as global variables instead, because creating arrays on the stack requires additional work and understanding of stack handling and stack offsets, whereas global variables are easy to declare with names.

Erik Eidt
  • 23,049
  • 2
  • 29
  • 53