1

So, I have a problem which translates a C program that calculates the sum of n numbers with a function with a variable number of parameters.

#include<stdarg.h>
  int sum(int n, ...){
    int i,s;
    va_list l;
    va_start(l,n);
    s=0;
    for(i=0;i<n;++i) s+=va_arg(l,int);
    va_end(l);
    return s;
  }
  int s;
  void main(){
    s=sum(3,1,2,3);  
    s=sum(2,10,20);
  }

Here is the MIPS code (ignore the comments), but I can't understand the part below bge, specifically the $t0 operations, what exactly happens when it adds 4 to $t0, I know that if it stores an integer it will simply add 4 to that number, and if I refer to the $sp, then add $sp, 4 would mean the pop operation. I'm really confused about what is happening on that part.

.data
  s: .space 4
.text
main:
  subu $sp,16   # incarcam parametrii, conform conventiei C
  li $t0,3
  sw $t0,12($sp)
  li $t0,2
  sw $t0,8($sp)
  li $t0,1
  sw $t0,4($sp)
  li $t0,3
  sw $t0,0($sp)
  jal sum      # functia returneaza in $v0
  addu $sp,16    # descarcam atatia par. cati am incarcat (adica 4 parametri)
  sw $v0,s       # val. ret. este in $v0
    # acum s contine 6
  subu $sp,12
  li $t0,20
  sw $t0,8($sp)
  li $t0,10
  sw $t0,4($sp)
  li $t0,2
  sw $t0,0($sp)
  jal sum
  addu $sp,12     # acum am incarcat doar 3 par., deci descarc doar 3 par.
  sw $v0,s
    # acum s contine 30
li $v0,10
syscall
sum:   # primeste o stiva de forma $sp:(n)()()()...
  subu $sp,16      # rezerv loc pt. salvat $fp si pentru i,s,l din functie
  sw $fp,12($sp)
  addiu $fp,$sp,12
    # acum stiva este $sp:(l)(s)(i)$fp:($fp v)(n)()()()...
  addu $t0,$fp,8
  sw $t0,-12($fp)  # va_start(l,n); avem $sp:(l)(s)(i)$fp:($fp v)(n)l:()()...
  sw $zero,-8($fp) # s=0
  sw $zero,-4($fp) # i=0
  sum_et1:
  lw $t0,-4($fp)
  lw $t1,4($fp)
  bge $t0,$t1,sum_et2  # daca i>=n iesim
    lw $t0,-12($fp)
    addu $t0,4           # 4 este sizeof(int)
    sw $t0,-12($fp)
    lw $t0,-4($t0)       # 4 este sizeof(int)
    lw $t1,-8($fp)
    add $t1,$t1,$t0
    sw $t1,-8($fp)       # s+=va_arg(i,int)
    lw $t0,-4($fp)
    add $t0,1
    sw $t0,-4($fp)       # ++i
    b sum_et1
  sum_et2:
    # in aceasta implementare nu avem ce executa pentru va_end(l)
  lw $v0,-8($fp)
  lw $fp,0($fp)
  addu $sp,16
jr $ra

1 Answers1

0

My MIPS assembly is very rusty, but it would seem:

lw $t0,-12($fp)   # load va_list l
addu $t0,4        # increment l to the next int argument
sw $t0,-12($fp)   # store l

lw $t0,-4($t0)    # load the argument pointed to by l (still in $t0)
lw $t1,-8($fp)    # load sum
add $t1,$t1,$t0   # add the argument to sum
sw $t1,-8($fp)    # store sum

lw $t0,-4($fp)    # load i
add $t0,1         # increment i by 1
sw $t0,-4($fp)    # store i

I suppose the confusing part is that va_list l contains a pointer internally, and is incremented inside the va_arg macro.

Arkku
  • 41,011
  • 10
  • 62
  • 84