Фреймы, локальные переменные, рекурсия

Ранее рассмотренная конвенция не обеспечивает некоторые возможности языков высокого уровня. Добавим некоторые из этих функций в новой конвенции о вызове процедур основе стека.

  1. Сохранение регистров в стеке
    • Сохранение адреса возврата в стеке($ra)
    • Сохранение и востаноление регистров $s0―$s7 в/из стеке/стека
  2. Конвенция о вызове процедур на основе стека.
    • Это не официальное соглашение. Однако оно может быть использовано для небольшого проекта на языке ассемблера. Конвенция не очень сложна и делает почти все, что может быть нужно. Если вы хотите использовать процедуры из программы на языке "C" или использовать процедуры из библиотек программ, то необходимо использовать официальные правила в полном объеме. (Что в эмуляторе MARS невозможно.)
    • Правила:
      1. Вызов подпрограммы (делает вызывающая процедура):
        • Сохранить в стеке регистры "$t0 - $t9", которые должны быть сохранены(будут использованы вызывающей процедурой после вызова подпрограммы). Подпрограмма может изменить эти регистры.
        • Загрузить значения аргументов в регистры "$a0 - $a3".
        • Вызов подпрограммы с помощью "jal".
      2. Пролог подпрограммы:
        • Сохранить регистр "$ra" в стек.
        • Сохранить в стек регистры "$s0 - $s7"(подпрограмма может изменять их).
      3. Тело подпрограммы:
        • Подпрограмма может изменять регистры "$t0 - $t9", или те из регистров "$s0 - $s7", которые были сохранены в прологе.
        • Из подпрограммы можно вызывать другую подпрограмму, тследуя этим правилам.
      4. Эпилог подпрограммы (непосредственно перед возвращением):
        • Загрузить возвращаемые значения в регистры "$v0 - $v1".
        • Извлечь из стека (в обратном порядке) сохраненые в прологе регистры "$s0 - $s7".
        • Извлечь из стека в регистр '$ra" адрес возврата.
        • Вернуться в вызывающую процедуру, используя "jr $ra".
      5. Восстановление состояния при выходе из подпрограммы:
        • Извлечь из стека (в обратном порядке) сохраненые регистры "$t0 - $t9".
  3. Пролог и эпилог вызываемой подпрограммы: ris
  4. Вызов и возврат. ris
  5. Вложенные вызовы подпрограмм и цепь активации. ris
  6. О реальных конвенциях(ABI).
  7. Пример программы:

   1 ## Driver --  main program for the application
   2 
   3          .text
   4          .globl main
   5  
   6 main:
   7          sub     $sp,$sp,4        # push the return address
   8          sw      $ra,($sp)
   9          sub     $sp,$sp,4        # push $s0
  10          sw      $s0,($sp)
  11          
  12          la      $a0,xprompt      # prompt the user
  13          li      $v0,4            # service 4
  14          syscall
  15          li      $v0,5            # service 5 -- read int
  16          syscall                  # $v0 = integer
  17          move    $s0,$v0          # save x
  18          
  19          la      $a0,yprompt      # prompt the user
  20          li      $v0,4            # service 4
  21          syscall
  22          li      $v0,5            # service 5 -- read int
  23          syscall                  # $v0 = integer
  24          
  25                                   # prepare arguments
  26          move    $a0,$s0          # x         
  27          move    $a1,$v0          # y
  28          jal     maxExp           # maximum expression
  29          nop                      # returned in $v0
  30          move    $s0,$v0          # keep it safe
  31 
  32          la      $a0,rprompt      # output title
  33          li      $v0,4            # service 4
  34          syscall
  35 
  36          move    $a0,$s0          # get maximum
  37          li      $v0,1            # print it out
  38          syscall
  39                                                       
  40          lw      $ra,($sp)        # pop $s0
  41          add     $s0,$sp,4
  42          lw      $ra,($sp)        # pop return address
  43          add     $sp,$sp,4
  44          
  45          li      $s0,0              # return to OS
  46          li      $v0,10
  47          syscall
  48          
  49          
  50          .data
  51 xprompt: .asciiz  "Enter a value for x --> "
  52 yprompt: .asciiz  "Enter a value for y --> "
  53 rprompt: .asciiz  "The maximum expression is: "
  54 
  55 ## maxInt -- compute the maximum of two integer arguments
  56 ##
  57 ## Input:
  58 ## $a0 -- a signed integer
  59 ## $a1 -- a signed integer
  60 ##
  61 ## Returns:
  62 ## $v0 -- maximum
  63 
  64          .text
  65          .globl maxInt
  66 
  67 maxInt:
  68          # body
  69          move   $v0,$a0          # max = $a0
  70          bgt    $a0,$a1,endif    # if $a1 > $a0  
  71          nop
  72          move   $v0,$a1          #    max = $a1
  73 endif:                           # endif 
  74          # epilog
  75          jr     $ra              # return to caller
  76          nop
  77           
  78 ## maxExp -- compute the maximum of three expressions
  79 ##
  80 ## Input:
  81 ## $a0 -- a signed integer, x
  82 ## $a1 -- a signed integer, y
  83 ##           
  84 ## Returns: 
  85 ## $v0 -- the maximum of x*x,  x*y, or 5*y
  86 ##
  87 ## Registers:
  88 ## $s0 --  x*x
  89 ## $s1 --  x*y
  90 ## $s2 --  5*y
  91 
  92          .text
  93          .globl maxExp
  94 
  95 maxExp:
  96          # prolog
  97          sub     $sp,$sp,4        # push the return address
  98          sw      $ra,($sp)
  99          sub     $sp,$sp,4        # push $s0
 100          sw      $s0,($sp)
 101          sub     $sp,$sp,4        # push $s1
 102          sw      $s1,($sp)
 103          sub     $sp,$sp,4        # push $s2
 104          sw      $s2,($sp)
 105 
 106          # body
 107          mul     $s0,$a0,$a0      # x*x
 108          mul     $s1,$a0,$a1      # x*y
 109          li      $t0,5
 110          mul     $s2,$t0,$a1      # 5*y
 111          
 112          move    $a0,$s0          # compute max of x*x
 113          move    $a1,$s1          # and x*y
 114          jal     maxInt           # current max in $v0
 115          nop
 116 
 117          move    $a0,$v0          # compute max of
 118          move    $a1,$s2          # current max, and 5*y 
 119          jal     maxInt           # total max will be in $v0
 120          nop
 121          
 122          # epilog
 123          lw      $s2,($sp)        # pop $s2 
 124          add     $sp,$sp,4                                    
 125          lw      $s1,($sp)        # pop $s1 
 126          add     $sp,$sp,4                                    
 127          lw      $s0,($sp)        # pop $s0 
 128          add     $sp,$sp,4                                    
 129          lw      $ra,($sp)        # pop return address
 130          add     $sp,$sp,4         
 131          jr      $ra              # return to caller 
 132          nop