Functions 3 Passing parameters by value Passing parameters
Functions (3) § Passing parameters by value § Passing parameters by reference 10/28/2021 CMPUT 229 1
Parameter passing § In C, all parameters are passed by value copies are made of all arguments before function begins function works on these copies function cannot affect caller’s environment 10/28/2021 CMPUT 229 2
Parameter passing § Sometimes, want function to modify variable belonging to caller pass address of variable as parameter function treats parameter as pointer to variable function must dereference pointer to access variable § This is how to implement pass by reference in C (and MIPS) functions 10/28/2021 CMPUT 229 3
Passing by reference 0 x 7 FFF 311 C void remquo(int num, int den, int *rem. Ptr , int *quo. Ptr ); *rem. Ptr, *quo. Ptr); 0 x 7 FFF 3120 int main() { int a, b, c, d; 0 x 7 FFF 3124 0 x 7 FFF 3128 scanf("%d%d", &a, &b); remquo(a, b, &c, &d); 0 x 7 FFF 312 C printf("%d %dn", c, d); 0 x 7 FFF 3130 } $sp = 0 x 7 FFF 3134 void remquo(int num, int den, int *rem. Ptr , int *quo. Ptr ) *rem. Ptr, *quo. Ptr) { *quo. Ptr = num / den; *rem. Ptr = num % den; } a 64 0 x 7 FFF 3134 b 15 0 x 7 FFF 3138 c ? ? ? 0 x 7 FFF 313 C d ? ? ? 0 x 7 FFF 3140 $fp = 0 x 7 FFF 3144 10/28/2021 CMPUT 229 0 x 7 FFF 3144 4
Passing by reference $sp = fp = 0 x 7 FFF 3144 these parameters are passed by reference rem. Ptr points to c quo. Ptr points to d saved $fp 0 x 7 FFF 3144 0 x 7 FFF 311 C saved $ra 0 x 004006 C 0 x 7 FFF 3120 num 64 0 x 7 FFF 3124 den 15 0 x 7 FFF 3128 rem. Ptr 0 x 7 FFF 313 C 0 x 7 FFF 312 C quo. Ptr 0 x 7 FFF 3140 0 x 7 FFF 3130 a 64 0 x 7 FFF 3134 b 15 0 x 7 FFF 3138 c ? ? ? 0 x 7 FFF 313 C d ? ? ? 0 x 7 FFF 3140 0 x 7 FFF 3144 10/28/2021 CMPUT 229 5
Passing by reference main: . text move $fp , $sp $fp, subu $sp, 16 # Read a and b. li $v 0, 5 syscall sw $v 0, -16($fp) # a li $v 0, 5 syscall sw $v 0, -12($fp) # b # Call remquo. subu $sp, 16 lw $t 0, -16($fp) sw $t 0, 0($sp) lw $t 0, -12($fp) sw $t 0, 4($sp) la $t 0, -8($fp) sw $t 0, 8($sp) la $t 0, -4($fp) sw $t 0, 12($sp) jal remquo addu $sp, 16 10/28/2021 # # # # a arg b arg &c arg &d arg # Print li $v 0, lw $a 0, syscall out c and d. 1 #print -8($fp) # c li $v 0, 11 li $a 0, 32 syscall # print char # ASCII space li $v 0, 1 # print 2 nd int lw $a 0, -4($fp) # d syscall 1 2 #clear stack args & exit addu $sp, 16 li $v 0, 10 # exit syscall 3 4 CMPUT 229 6
Passing by reference # function computes remainder and # quotient of dividing param 1 by # param 2. Pointers for writing # answers passed as params 3 & 4 remquo: subu $sp, 8 sw $ra , 4($sp) $ra, sw $fp , 0($sp) $fp, move $fp , $sp $fp, # quotient = num / lw $t 0, 8($fp) # lw $t 1, 12($fp) # div $t 0, $t 1 # *rem. Ptr =. . . lw $t 1, 16($ fp) ) # rem. Ptr 16($fp sw $t 0, 0($t 1) # *rem. Ptr = *rem. Ptr= # restore $ra, $fp, $sp lw $fp , 0($sp) $fp, lw $ra , 4($sp) $ra, addu $sp, 8 jr $ra den num den # *quo. Ptr =. . . lw $t 1, 20($ fp) ) # quo. Ptr 20($fp sw $t 0, 0($t 1) # *quo. Ptr = *quo. Ptr= # remainder = num % den lw $t 0, 8($fp) # num lw $t 1, 12($fp) # den rem $t 0, $t 1 10/28/2021 CMPUT 229 7
Passing large parameters § Arrays always passed by reference including strings (arrays of char) this is why you can write char x[] or char *x in function parameter lists 10/28/2021 CMPUT 229 8
Passing large parameters § Structures can be passed by value in C, but probably should always be passed by reference instead see next example for why 10/28/2021 CMPUT 229 9
Passing by value snafu. org 101 58 178 37 i saved $fp saved $ra ? ? ? 0 x 7 FFF 3318 0 x 0040009 C machine snafu. org int main() { print. IP(mycomputer); } 101 58 178 $sp $fp stack segment void print. IP(const struct Host machine) { int i; for (i = 0; i < 4; i++) printf("%d ", machine. ip[i]); } data segment struct Host { char name[20]; int ip[4]; } mycomputer = { "snafu. org", { 101, 58, 178, 37 } }; 37 10/28/2021 CMPUT 229 10
Passing by value struct Host { char name[20]; int ip[4]; } mycomputer = { "snafu. org", { 101, 58, 178, 37 } }; . data mycomputer: . asciiz "snafu. org". space 10 # 20 bytes total. word 101, 58, 178, 37 void print. IP(const struct Host machine) { int i; for (i = 0; i < 4; i++) printf("%d ", machine. ip[i]); } int main() { print. IP(mycomputer); } 10/28/2021 CMPUT 229 11
Passing by value. text # Print. IP function # 1 st, main next slide li $v 0, 11 # print char li $a 0, ' ' syscall print. IP: subu $sp, 8 sw $ra , 4($sp) $ra, sw $fp , 0($sp) $fp, move $fp , $sp $fp, lw $t 0, -4($fp) add $t 0, 1 sw $t 0, -4($fp) j loop subu $sp, 4 sw $zero, -4($fp) # i=0 loop: lw $t 2, -4($fp) bge $t 2, 4, end # i li $v 0, 1 la $t 0, 28($fp) # lw $t 2, -4($fp) # sll $t 1, $t 2, 2 add $t 0, $t 1 lw $a 0, 0($t 0) # syscall 10/28/2021 # i=i+1 # kill local i, restore $fp, $ra end: addu $sp, 4 lw $fp , 0($sp) $fp, lw $ra , 4($sp) $ra, addu $sp, 8 #fix sp jr $ra ip i pass-by-value print. IP takes 75 instructions to run ip[i] CMPUT 229 12
Passing by value main: move $fp , $sp $fp, # Copy whole struct! # 20*1 + 4*4 = 36 bytes subu $sp, 36 lw $t 0, mycomputer+0 sw $t 0, 0($sp) lw $t 0, mycomputer+4 sw $t 0, 4($sp) lw $t 0, mycomputer+8 sw $t 0, 8($sp) lw $t 0, mycomputer+12 sw $t 0, 12($sp) lw $t 0, mycomputer+16 sw $t 0, 16($sp) lw $t 0, mycomputer+20 sw $t 0, 20($sp) lw $t 0, mycomputer+24 sw $t 0, 24($sp) lw $t 0, mycomputer+28 sw $t 0, 28($sp) lw $t 0, mycomputer+32 sw $t 0, 32($sp) #phew! 10/28/2021 # now we call the function jal print. IP # caller must now clear structure # from stack and exit addu $sp, 36 # easy! li $v 0, 10 syscall pass-by-value main takes 21 instructions to call print. IP CMPUT 229 13
Passing by reference snafu. org 101 58 178 37 data segment struct Host { char name[20]; int ip[4]; } mycomputer = { "snafu. org", { 101, 58, 178, 37 } }; void print. IP(const struct Host *machine) { int i; for (i = 0; i < 4; i++) printf("%d ", machine->ip[i ]); machine->ip[i]); } 10/28/2021 CMPUT 229 i saved $fp saved $ra ? ? ? 0 x 7 FFF 3318 0 x 00400038 machine 0 x 10010000 $sp $fp 14 stack segment int main() { print. IP(&mycomputer); }
Passing by reference struct Host { char name[20]; int ip[4]; } mycomputer = { "snafu. org", { 101, 58, 178, 37 } }; . data mycomputer: . asciiz "snafu. org". space 10. word 101, 58, 178, 37 void print. IP(const struct Host *machine) { int i; for (i = 0; i < 4; i++) printf("%d ", machine->ip[i ]); machine->ip[i]); } int main() { print. IP(&mycomputer); } 10/28/2021 CMPUT 229 15
Passing by reference li $v 0, 11 # print char li $a 0, ' ‘ # quote char ok syscall . text print. IP: subu $sp, 8 sw $ra , 4($sp) $ra, sw $fp , 0($sp) $fp, move $fp , $sp $fp, lw $t 0, -4($fp) add $t 0, 1 sw $t 0, -4($fp) j loop subu $sp, 4 sw $zero, -4($fp) # i loop: lw $t 2, -4($fp) bge $t 2, 4, end: # i li $v 0, 1 lw $t 0, 8($fp) # machine lw $t 2, -4($fp) # i sll $t 1, $t 2, 2 add $t 0, $t 1 lw $a 0, 20($t 0) # ip syscall 10/28/2021 CMPUT 229 # i addu $sp, 4 lw $fp , 0($sp) $fp, lw $ra , 4($sp) $ra, addu $sp, 8 jr $ra pass-by-reference print. IP still takes 75 instructions to run 16
Passing by reference # # This version passes its parameters by reference. That is address of the “mycomputer ” structure is passed. “mycomputer” This is a 32 bit (4 byte) value. main: move $fp , $sp $fp, subu $sp, 4 la $t 0, mycomputer # get addr sw $t 0, 0($sp) # put on stk jal print. IP # call function addu $sp, 4 li $v 0, 10 syscall pass-by-reference main takes just 5 instructions to call print. IP instead of 21 10/28/2021 CMPUT 229 17
Parameter passing § Pass by reference is more efficient when size of parameter is larger than size of pointer • especially obvious for large structures slight penalty in time efficiency in callee • usually no more than one instruction per variable reference huge saving in time efficiency in caller • because structure does not need to be copied § Compiler can’t handle this automatically need to write different C code 10/28/2021 CMPUT 229 18
- Slides: 18