1

I'm trying to understand how simple C code is translated into assembly MIPS.

int main(){
int a;
a = 9;
return 0;
}

is being translated into

main:
    .frame  $fp,16,$31      # vars= 8, regs= 1/0, args= 0, gp= 0
    .mask   0x40000000,-4
    .fmask  0x00000000,0
    .set    noreorder
    .set    nomacro
    addiu   $sp,$sp,-16
    sw  $fp,12($sp)
    move    $fp,$sp
    li  $2,9            # 0x2
    sw  $2,0($fp)
    move    $2,$0
    move    $sp,$fp
    lw  $fp,12($sp)
    addiu   $sp,$sp,16
    jr  $31
    nop

I find a bit weird the use of $fp and $sp: it seems to me that there are unnecessary backups and restore. Probably it is just the way the compiler translates to assembly.

But I just can't understand why it reserves 16 bytes on the stack: 4 for the local variable, 4 for the $fp backup ... and the other 8 bytes? I'm talking about MIPS, I'm using gcc with toolchain mips-mti-elf.


I modified the code, now the variable is global. Guess what? Stack size is 8 bytes (4 for $fp, but the other 4 bytes?).

Surfer on the fall
  • 721
  • 1
  • 8
  • 34
  • 3
    As usual, make sure you have optimization enabled (funny you even tagged it _"compiler-optimization"_). Then again, for this simple code that will mean it will get reduced to `return 0;`. – Jester Oct 30 '17 at 15:58
  • @HansPassant please look at the last line. 16B alignment does not seem to explain the fact. – Surfer on the fall Oct 30 '17 at 16:03
  • Stack is not part of C language, the compiler can do anything to it, what it finds appropriate. It's not important if it does -16 or -100, that's only affecting efficiency of resulting machine code, but from the C language point of view both are identically correct, that's implementation detail of compiler. If you would use some optimization, it would probably remove the useless instructions, but then again, compiler is not supposed to produce perfect optimal machine code. They are supposed to produce "correct" machine code with reasonable performance **within reasonable time** = not perfect. – Ped7g Oct 30 '17 at 20:18
  • `gcc -O0` is explicitly required to spill/reload everything after every C statement, to support using `gdb` to *modify* variables in memory when stopped at a breakpoint. Also to support `jump` to continue execution at a different line of the C source. https://stackoverflow.com/a/46043760/224132 – Peter Cordes Oct 31 '17 at 06:58
  • 1
    Yeah, yeah, compiler can do whatever it wants, it's not part of standard and so on. But the question is actually good. Compiler does want to leave empty space on stack and I'm also curious to hear the reason. Imagine yourself a compiler developer. You wouldn't say "c'mon, its -O0 so I can use 16 or 100 or whatever for stack size, where is my 1d100 dice to decide required space". The should be some intent, but it's hard to find it. I really respect curiosity shown in this question and would really appreciate answer, but doubt if I would ever see it. – nnovich-OK Oct 31 '17 at 21:21
  • 1
    @nnovich-OK we don't know. It's probably an artefact of code generation, where the stack frame is set up for some worst case scenario which doesn't happen and the extra space is optimized away later. One obvious possibility is reserving space for the return address register. Turns out this is a leaf function, so it doesn't need that. – Jester Oct 31 '17 at 23:11

0 Answers0