I think I need to paste the full code although it looks long.
I write a simple code for test.
#include <stdio.h>int funadd(int a, int b){ int x = 0; x = a + b; return x;}int fun(int a, int b){ int y = 17; int returnvalue = 0; returnvalue = funadd(a, b); returnvalue = returnvalue - y; return returnvalue;}int main(){ int a = 32; int b = 24; int c = 0; c = fun(a, b); printf("%d\n", c); return c;}
After assembly:
.file 1 "testfuncall.c" .section .mdebug.abi32 .previous .nan legacy .module fp=xx .module nooddspreg .abicalls .text .align 2 .globl funadd .set nomips16 .set nomicromips .ent funadd .type funadd, @functionfunadd: .frame $fp,24,$31 # vars= 8, regs= 1/0, args= 0, gp= 8 .mask 0x40000000,-4 .fmask 0x00000000,0 .set noreorder .set nomacro addiu $sp,$sp,-24 sw $fp,20($sp) move $fp,$sp sw $4,24($fp) sw $5,28($fp) sw $0,8($fp) lw $3,24($fp) lw $2,28($fp) addu $2,$3,$2 sw $2,8($fp) lw $2,8($fp) move $sp,$fp lw $fp,20($sp) addiu $sp,$sp,24 jr $31 nop .set macro .set reorder .end funadd .size funadd, .-funadd .align 2 .globl fun .set nomips16 .set nomicromips .ent fun .type fun, @functionfun: .frame $fp,40,$31 # vars= 8, regs= 2/0, args= 16, gp= 8 .mask 0xc0000000,-4 .fmask 0x00000000,0 .set noreorder .cpload $25 .set nomacro addiu $sp,$sp,-40 sw $31,36($sp) sw $fp,32($sp) move $fp,$sp .cprestore 16 sw $4,40($fp) sw $5,44($fp) li $2,17 # 0x11 sw $2,24($fp) sw $0,28($fp) lw $5,44($fp) lw $4,40($fp) lw $2,%got(funadd)($28) move $25,$2 .reloc 1f,R_MIPS_JALR,funadd1: jalr $25 nop lw $28,16($fp) sw $2,28($fp) lw $3,28($fp) lw $2,24($fp) subu $2,$3,$2 sw $2,28($fp) lw $2,28($fp) move $sp,$fp lw $31,36($sp) lw $fp,32($sp) addiu $sp,$sp,40 jr $31 nop .set macro .set reorder .end fun .size fun, .-fun .rdata .align 2$LC0: .ascii "%d\012\000" .text .align 2 .globl main .set nomips16 .set nomicromips .ent main .type main, @functionmain: .frame $fp,48,$31 # vars= 16, regs= 2/0, args= 16, gp= 8 .mask 0xc0000000,-4 .fmask 0x00000000,0 .set noreorder .cpload $25 .set nomacro addiu $sp,$sp,-48 sw $31,44($sp) sw $fp,40($sp) move $fp,$sp .cprestore 16 li $2,32 # 0x20 sw $2,24($fp) li $2,24 # 0x18 sw $2,28($fp) sw $0,32($fp) lw $5,28($fp) lw $4,24($fp) lw $2,%got(fun)($28) move $25,$2 .reloc 1f,R_MIPS_JALR,fun1: jalr $25 nop lw $28,16($fp) sw $2,32($fp) lw $5,32($fp) lw $2,%got($LC0)($28) addiu $4,$2,%lo($LC0) lw $2,%call16(printf)($28) move $25,$2 .reloc 1f,R_MIPS_JALR,printf1: jalr $25 nop lw $28,16($fp) lw $2,32($fp) move $sp,$fp lw $31,44($sp) lw $fp,40($sp) addiu $sp,$sp,48 jr $31 nop .set macro .set reorder .end main .size main, .-main .ident "GCC: (Debian 6.3.0-18+deb9u1) 6.3.0 20170516"
I realize after each function call, there is a lw $28,16($fp)
instruction. But I don't see any code that would have stored a value there first in either the caller or callee.
I can read MIPS assembly. I know that lw
is load word, and how $fp and $sp are frame pointer and stack pointer.
I just can't understand how it makes sense to load anything from 16($fp)
; it seems there is an uninitialized space.
I know $28
is $gp
, and can see it being used as a GOT pointer to load function addresses before calls, but it seems nothing initializes that register either before its used in functions.
Does the MIPS calling convention require $28
to already be pointing at the GOT on function entry?