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, @function
funadd:
.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, @function
fun:
.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,funadd
1: 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, @function
main:
.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,fun
1: 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,printf
1: 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?
sw $5,28($fp)earlier infunadd, before the reload of that register arg from the same address it was spilled to. You seem to have removed the stores fromfunandmainso of course the code looks like it's reading uninitialized memory. Unless the source is doing that, that's unlikely. In fun and main, I think$28is a GOT pointer. - Peter Cordesfunandmaindoesn't store anyting to the 16($fp), but load 16($fp) to $28. Stackoverflow says I paste too much code so I remove some code, let me try to paste the full code. - 50u1w4y-fverbose-asmto make GCC annotate each instruction with the C name of the operands. - Peter Cordes$2does not affect$28. Those are different registers. As you know,$2is$v0(return val in the standard calling convention), while$28 = $gp, "Global Area Pointer (base of global data segment)". So yeah, it's clear GCC is using it as a GOT pointer, but agreed I don't see where it's initialized. Maybe in PIC code, it's already part of the calling convention? That is strange; it's getting reloaded after calls but I don't see where it's initially stored.16($fp)is different memory in each func. - Peter Cordes