Subrutiner och stacken

Innehåll

  1. Bakgrund
    • Uppgifter
      • Frågor
        • Tyck till

          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:

          1. stacken hanteras i MIPS-processorn,
          2. hur subrutiner skrivs i MIPS-assembler,.
          3. samt varför register-konventionen måste följas.

          Senast uppdaterat: Tue Nov 29 16:34:56 CET 2005

          ~ karl

          Bakgrund

          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[]);

          Uppgifter

          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:

          [ download ][ maximera ]

          uppgift_ett.s

          ##############################################################################
          ##
          ## 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.

          Obs!

          Subrutinerna skall betraktas som självständiga enheter helt frikopplade från anropande kodavsnitt. Konventionerna för parameteröverföring och register-användning för MIPS-assembler (se Appendix A.6) måste följas.

          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.

          Frågor

          I denna uppgift har vi bekantat oss med stacken och hur den kan användas av till exempel en kompilator vid parameteröverföring.

          Stacken

          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).

          Något som kommer att bli viktigt när vi fortsätter och skriver större MIPS-program är den så kallade registerkonventionen.

          Registerkonventionen

          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).

          Längst ner i koden skall ni skriva svaren på dessa frågor. Glöm inte att varje rad måste börja med '#', dvs svaren skall ges som kommentarer. Gör ni inte detta kommer det inte att gå att köra programmet.

          Tyck till

          Som vanligt vill jag veta vad du tycker om denna uppgift. Detta är viktigt för att vi tillsammans skall kunna fortsätta att göra kursen bättre!

          Som helhet tycker jag att uppgiften var:

          Bra
          Hyffsad
          Dålig

          Kommentar:

          Som helhet tycker jag att svårighetsgraden var:

          Lätt
          Lagom
          Svår

          Kommentar:

          Vad kan göras bättre:

          Något som du uppskattade speciellt:

          Tidsuppskattning

          Det tog ungefär att göra klart uppgiften

          Kommentar:

          Övrigt: