If you put a jr $ra at the end of a MIPS assembly language regime in MARS, girlfriend will acquire an error article saying:

invalid program counter value: 0x00000000

Example 1 below fails:

.datatheMsg: .asciiz "Hello World ".text.globl mainmain: li $v0, 4 la $a0, theMsg syscall jr $ra Example 2 listed below works:

.datatheMsg: .asciiz "Hello World ".text.globl mainmain: li $v0, 4 la $a0, theMsg syscall MARS states "program is finished to run (dropped turn off bottom)" but there space no error messages.

You are watching: Attempt to execute non-instruction mips

Now, if you run example 2 in QtSpim, friend will gain an error saying:

Attempt come execute non-instruction at 0x00400030

If girlfriend run example 1 in QtSpim, it works just fine.

Can anyone shed some light on this?Which MIPS simulator is right?

asked on ridge Overflow Feb 5, 2021 by kris • edited Feb 6, 2021 by
Sep Roland

2 Answers


The standard works-everywhere method is do an exit(0) system call (http://courses.missouristate.edu/kenvollmar/mars/help/syscallhelp.html).

li $v0, 10 # contact number li $a0, 0 # arg syscall # exit(0)That additionally avoids having to save the incoming $ra almost everywhere in main if you want to usage jal inside her program, therefore it"s convenient.

That"s also more "realistic" for real-world hand-written asm programs to run in a mainstream OS prefer Linux, not just the "toy" system that MARS/SPIM simulate.

In MARS, reportedly dropping turn off the bottom is a valid choice for the "toy" mechanism that it simulates. That never ever works in any real-hardware CPU, though; there"s constantly something next in memory and the CPU will shot to fetch and also execute it1.

Neither MARS no one SPIM space trying to emulate a actual OS choose Linux, just administer their own particular environment2. The equipment that MARS vs. SPIM simulate have actually some minor differences from each other, consisting of the one girlfriend found.

Neither one is best or wrong, just different: over there is no real-world setting that they"re make the efforts to enhance / emulate.

SPIM can even have actually an choice to encompass some kernel code or something prefer that in the simulated system"s memory, IIRC. I might be misremembering, yet if not then several of the syscall handling might actually be done by an ext MIPS code, coming closer to a genuine MIPS CPU running an OS. (As protest to MARS whereby the system-call implementation is completely in Java inside the simulator the you"re calling into via syscall, not in terms of MIPS indict and an equipment drivers because that simulated hardware.)

Under a actual OS (e.g. GNU/Linux v gcc and also glibc), main would it is in a proper role called normally from the _start procedure entry suggest (indirectly via __libc_start_main to do some more init stuff before actually call main). _start is the real process entry point, an initial instruction the runs in user-space (modulo dynamic linking), and also is not a function (no return address anywhere); your just option is to do an leave system contact (or crash or keep running forever). When key returns, _start overcome its return worth (an int therefore in $v0) as an arg to the exit library function which go cleanup stuff favor flushing stdio buffers, then renders an _exit device call.

Apparently SPIM intends their main label come be favor a C key function, or at least it it s okay a valid return address. IDK if it it s okay int argc and char *argv<> in $a0 and $a1.

For jr $ra come work, SPIM have to be setting the early $ra to part address, prefer your key was called from somewhere. You"ll probably uncover code that which copies $v0 to $a0, then makes an leave system call.

Some people do confusingly use main as a name for entry-points that can"t return, unfortunately, ns think also in real-world installed development. In traditional toolchains for GNU/Linux equipment (gcc / clang), the process entry point is by default referred to as _start.

main is confusing because it"s the standard name for a C duty (called by asm startup stuff), i beg your pardon is allowed to return. Something you can"t return indigenous isn"t a function, however in C, main definitely is a function. C is the low-level language that Unix/Linux solution programming, and also many other languages develop on optimal of that standard toolchain that libc and also CRT startup code.

Footnote 1: many ISAs have rules for just how PC have the right to wrap from 0xffffffc to 0 or whatever, so even putting your code at the an extremely end that the address an are can"t do it protect against by itself as soon as reaching the end. Or if it does, it will certainly be some sort of fault, not exiting come the OS. (In this instance the MARS or SPIM room acting as the OS, dealing with the syscall instructions friend run among other things). Note that an really OS on ceiling metal has no means to "exit", only reset or power-off the machine. It"s not running "under" something it deserve to exit back to.

Footnote 2: v very minimal system calls, e.g. No cursor movement, and some syscalls which perform things the library functions (not syscalls) would perform in a actual system, e.g. Intstring conversion. Yet MARS/SPIM only carry out that as component of I/O, no atoi or sprintf(buf, "%d", num). This is why the "toy" label applies, specifically to the collection of device calls they provide, i beg your pardon is really much not prefer Linux"s set of mechanism calls.

But additionally to stuff like the basic bitmap graphics MARS has, and also to the no-branch-delay default option both MARS and also SPIM default to. Genuine MIPS CPUs have actually a branch-delay slot, until MIPS32r6 re-arranged the opcodes and noted new no-delay-slot branch instructions.

MARS at least (and maybe SPIM) have actually pretty minimal support for assemble-time constants in their integrated assembler together well, e.g. Friend can"t carry out .equ or msglen = . - msg to compute a length of a msg: .ascii "hello" at assemble time like you can in GNU assembler for MIPS.

answered on stack Overflow Feb 5, 2021 by
Peter Cordes • edited Feb 6, 2021 by
Peter Cordes
Peter"s very an excellent answer:

SPIM has the alternative to incorporate kernel code, via Simulator->Settings->Load exception Handler (you deserve to pick a file or usage the default), the handler is assembly source. The default setting is to use the default handler (as opposed to using no handler).

When you create such a handler, girlfriend can incorporate code in .ktext & .kdata, but additionally include user .text & .data. Any type of exception handler is assembled and also loaded very first before the user code.

The standard exception handler paper includes — for placement in user .text — loading that argc/argv and then walk jal main followed by syscall #10 (so the is a little like _start in crt0), which means we have the right to return (jr $ra) to that startup code. This is why user code shows up at <00400020> in SPIM vice versa, in MARS your user password starts in ~ 00400000.

SPIM additionally does not report missing symbols until runtime!!! So, if key is not uncovered then the absent symbol key is reported once the jal main executes.

However, when you do have a valid main symbol, it does not have to be an initial in the document — it deserve to be anywhere.

See more: Detective Ken Penrod How Did He Die, Was The First 48 Cancelled

Though MARS additionally starts execution in ~ the start of .text, by contrast, the default exemption handler in MARS provides no _start equivalent, so we have to start assembly program with main code (but us don"t really require a main symbol) or else placed a j somewhere there. SPIM will behave an ext like MARS if you forgo the use of the default handler.