Subrutiner och stacken |
I den här uppgiften lär vi oss hur en kompliator och en MIPS-maskin hanterar funktionsanrop. Uppgiften syftar till att ge kunskap och förståelse för hur:
Senast uppdaterat: Tue Nov 29 16:34:56 CET 2005
~ karl
I högnivåspråk är det vanligt att parametrar till funktioner och procedurer överförs via den underliggande maskinens stack. Ett delsyfte med uppgiften är att ge förståelse för de mekanismer som på maskinnivå ligger bakom parameteröverföring. När parametrar överförs via stacken i den första deluppgiften nedan ska det tolkas som att subrutinen får lokala kopior av parametervärdena. I den andra deluppgiften överförs en pekare (adress/referens) till originaldatat vilket då innebär att subrutinen inte använder lokalt data. Två förenklade liknelser i C/C++:
int sum_by_value(int antal, int tal_1, int tal_2, int tal_3, int tal_4, ...);
int sum_by_reference(int antal, int tal[]);
Ni ska skriva två subrutiner (sum_by_value och sum_by_reference) som kan addera heltal. Parametrar till subrutinen är antalet tal som ska adderas samt samtliga tal som ska adderas. Varje subrutin ska returnera summan av talen. Sedan ska ni skriva klart ett huvudprogram som använder subrutinerna för att summera
Ni skall bygga vidare på koden nedan:
############################################################################## ## ## DESCRIPTION: Computer Systems 1 - part 1 (DARK) ## ## Assignment 1: Introduction to MIPS assembler ## ## A first look at subroutines. Paramteters can be passed by ## value or by reference. ## ## ## AUTHOR(S): Student One <student.one@student.uu.se> ## Student Two <student.two@student.uu.se> ## ## HISTORY: November XX, 2004. First version. ## ## November ZZ, 2004. Fixed the zero length bug. ## ############################################################################## ############################################################################## ## Data Segment ############################################################################## .data antal: .word 10 tal: .word 1,2,3,4,5,6,7,8,9,10 NL: .ascii "\n" ############################################################################## ## Text Segment ############################################################################## .text .globl main #----------------------------------------------------------------------------- # Main Start #----------------------------------------------------------------------------- main: addi $sp, $sp, -4 # push return address on stack sw $ra, 0($sp) ## prepare for call by value, i.e., ## place stuff on the stack ## ... write your code here ... ## call subroutine and print result jal sum_by_value add $a0, $v0, $zero # integer to print, the total sum li $v0, 1 # system call code for print_int syscall # print the integer ## print new-line li $v0, 4 # system call for print_str la $a0, NL # address of string to print syscall # print the string ## prepare for call by reference, i.e., ## place stuff in registers ### ... write your code here ... ## call subroutine and print result jal sum_by_reference add $a0, $v0, $zero # integer to print, the total sum li $v0, 1 # system call code for print_int syscall # print the integer lw $ra, 0($sp) # pop return address addi $sp, $sp, 4 jr $ra # return to caller #----------------------------------------------------------------------------- # Main End #----------------------------------------------------------------------------- #----------------------------------------------------------------------------- # PROCEDURE: sum_by_value # # DESCRIPTION: This procedure returns the total sum for # given numbers. All numbers are passed to this # subroutine via the stack. # # INPUT: All numbers are placed on the stack. The top # of the stack contains the amount of numbers # to sum. # # OUTPUT: $v0 - the total sum #----------------------------------------------------------------------------- sum_by_value: addi $v0, $zero, 0 # $v0 = sum = 0 ## ... write your code here ... jr $ra # return to caller #----------------------------------------------------------------------------- # PROCEDURE: sum_by_reference # # DESCRIPTION: This procedure returns the total sum for # given numbers. All numbers are passed to the # subroutine via a special/standard MIPS- # registers for parameter passing. # # INPUT: $a0 - the amount of numbers to sum # $a1 - the start address of given numbers # # OUTPUT: $v0 - the total sum #----------------------------------------------------------------------------- sum_by_reference: addi $v0, $zero, 0 # $v0 = sum = 0 ### ... write your code here ... jr $ra # return to caller ############################################################################## # SVAR PÅ FRÅGOR # ############################################################################## # FRÅGA 1: # # Rita hur stacken ser ut för talen 1,2,3,4,5 (inkl. $ra och antal=5) # precis innan proceduren sum_by_value skall anropas (se Appendix A.5 -- # Memory Usage). # SVAR: # # Stacken "växer" neråt. # # Precis innan anrop till sum_by_value ser det ut så här # # (Färdigställ figuren nedan) # # [ ] # . # . # . # [ ] # [ ] <--- SP (Stack pointer) # FRÅGA 2: # # Motivera kort (med max. 3 meningar) varför register $s0-$s7 och $ra # måste sparas på stacken i fall dessa ändras i subrutiner (se Appendix # A.6, speciellt Figur A.10 och texten på sidan A-25). # SVAR: # # Skriv ditt svar här! # #
Skriv klart sum_by_value. Skriv en subrutin som tar all sin data från stacken. Antalet tal ska även det ges till subrutinen via stacken. Tänk på att antalet tal ska kunna variera (tänk särskillt på fallet antal=0) så antalet tal måste ligga överst på stacken! Glöm inte att återställa stacken efter exekveringen av sum_by_value.
Skriv klart sum_by_reference. Att skicka med alla tal som ska summeras till subrutinen är både omständigt och inte heller effektivt. I stället gör man så att man endast skickar två parametrar: antalet tal samt adressen till talen som ska summeras (det vill säga adressen "tal" i exemplet ovan). Notera att det i detta fall handlar om att referera data som inte är lokalt för subrutinen.
Rita hur stacken ser ut för talen 1,2,3,4,5 (inkl. $ra och antal=5) precis innan proceduren sum_by_value skall anropas (se Appendix A.5 -- Memory Usage).
Motivera kort (med max. 3 meningar) varför register $s0-$s7 och $ra måste sparas på stacken i fall dessa ändras i subrutiner (se Appendix A.6, speciellt Figur A.10 och texten på sidan A-25).