1.5. HELLO, WORLD!
We see here that register FP is used as a pointer to the stack frame. We also see 3NOPs. The second
and third of which follow the branch instructions. Perhaps the GCC compiler always addsNOPs (because
ofbranch delay slots) after branch instructions and then, if optimization is turned on, maybe eliminates
them. So in this case they are left here.
Here is alsoIDAlisting:
Listing 1.35: Non-optimizing GCC 4.4.5 (IDA)
1 .text:00000000 main:
2 .text:00000000
3 .text:00000000 var_10 = -0x10
4 .text:00000000 var_8 = -8
5 .text:00000000 var_4 = -4
6 .text:00000000
7 ; function prologue.
8 ; save the RA and FP in the stack:
9 .text:00000000 addiu $sp, -0x20
10 .text:00000004 sw $ra, 0x20+var_4($sp)
11 .text:00000008 sw $fp, 0x20+var_8($sp)
12 ; set the FP (stack frame pointer):
13 .text:0000000C move $fp, $sp
14 ; set the GP:
15 .text:00000010 la $gp, __gnu_local_gp
16 .text:00000018 sw $gp, 0x20+var_10($sp)
17 ; load the address of the text string:
18 .text:0000001C lui $v0, (aHelloWorld >> 16) # "Hello, world!"
19 .text:00000020 addiu $a0, $v0, (aHelloWorld & 0xFFFF) # "Hello, world!"
20 ; load the address of puts() using the GP:
21 .text:00000024 lw $v0, (puts & 0xFFFF)($gp)
22 .text:00000028 or $at, $zero ; NOP
23 ; call puts():
24 .text:0000002C move $t9, $v0
25 .text:00000030 jalr $t9
26 .text:00000034 or $at, $zero ; NOP
27 ; restore the GP from local stack:
28 .text:00000038 lw $gp, 0x20+var_10($fp)
29 ; set register $2 ($V0) to zero:
30 .text:0000003C move $v0, $zero
31 ; function epilogue.
32 ; restore the SP:
33 .text:00000040 move $sp, $fp
34 ; restore the RA:
35 .text:00000044 lw $ra, 0x20+var_4($sp)
36 ; restore the FP:
37 .text:00000048 lw $fp, 0x20+var_8($sp)
38 .text:0000004C addiu $sp, 0x20
39 ; jump to the RA:
40 .text:00000050 jr $ra
41 .text:00000054 or $at, $zero ; NOP
Interestingly,IDArecognized theLUI/ADDIUinstructions pair and coalesced them into oneLA(“Load Ad-
dress”) pseudo instruction at line 15. We may also see that this pseudo instruction has a size of 8 bytes!
This is a pseudo instruction (ormacro) because it’s not a real MIPS instruction, but rather a handy name
for an instruction pair.
Another thing is thatIDAdoesn’t recognizeNOPinstructions, so here they are at lines 22, 26 and 41. It is
OR $AT, $ZERO. Essentially, this instruction applies the OR operation to the contents of the $AT register
with zero, which is, of course, an idle instruction. MIPS, like many otherISAs, doesn’t have a separate
NOPinstruction.
Role of the stack frame in this example
The address of the text string is passed in the register. Why setup a local stack anyway? The reason
for this lies in the fact that the values of registersRAand GP have to be saved somewhere (because
printf()is called), and the local stack is used for this purpose. If this was aleaf function, it would have
been possible to get rid of the function prologue and epilogue, for example:1.4.3 on page 8.