Laman

Jumat, 12 April 2013

Program Komplit

Berikut adalah program yang telah selesai. Simbol global telah dibuat. Pelajari bagaimana setiap module menggunakan direktive .text dan .data untuk mendeskripsikan bagiannya.

# addthree.asm --- read in three integers and print their sum
#
# This program uses simple linkage.  
#
# Settings: Load delays  ON;  Branch delays ON
#           Trap file    ON;  Pseudoinstructions ON   
#

         .text
         .globl  main
main:
         jal     pread            # read first integer
         nop                      #  
         move    $s0,$v0          # save it in $s0

         jal     pread            # read second integer
         nop                      #  
         move    $s1,$v0          # save it in $s1

         jal     pread            # read third integer
         nop                      #  
         move    $s2,$v0          # save it in $s2
         
         addu    $s0,$s0,$s1      # compute the sum
         addu    $a0,$s0,$s2
         
         li      $v0,1            # print the sum
         syscall
         
         li      $v0,10           # exit
         syscall


# pread -- prompt for and read an integer
#
# on entry:
#    $ra -- return address
#
# on exit:
#    $v0 -- the integer

         .text
         .globl  pread
pread:   
         la    $a0,prompt        # print string
         li    $v0,4             # service 4
         syscall
        
         li    $v0,5             # read int into $v0
         syscall                 # service 5
        
         jr    $ra               # return
         nop                     #  
        
         .data
prompt:
         .asciiz "Enter an integer: "

Berikut adalah tampilan jendela konsol setelah program dijalankan.

Quest 15: Bisakan alamat .phread digunakan oleh program yang lain?
Jawab: boleh asalkan diikuti dengan konvensi linkage sederhana

Simbol Global

Ingat lagi bahwa subroutine dan main routine tidak boleh menggunakan nama yang sama untuk memory dengan alamat yang berbeda, ini artinya penamaan memori untuk keduanya tidak boleh sama, karena hal ini bisa merusak gagasan tentang modularitas.

Tapi kadang alamat yang sama juga digunakan oleh kedua subroutine maupun main routine.

Simbol atau nama yang sama digunakan oleh kedua modul ini disebut simbol global. Simbol global biasanya adalah entry point, simbol yang tidak global disebut local simbol. Di bahasa assembly MIPS alamat-alamat yang diperuntukkan untuk global biasanya ditaruh di tempat yang mengikuti direktiv .global. Beberapa bahasa ada yang menyebutnya sebagai variabel gobal.

Di dalam bahasa C, alamat yang tersedia untuk modul yang lain disebut simbol eksternal.

Source code SPIM berada di dalam sebuah file, yang mencakup semua sobroutine-subroutine. Bagaimanapun, di dalam pengembangan software profesional tiap-tiap subroutine bisa saja diletakkan ke dalam file-file yang berbeda. Tiap-tiap file ini akan menempati address symboliknya masing-masing, alamat ini adalah global dan boleh direferensi oleh software-software yang lain.

Main Program (main routine)

Setelah subroutine dibuat, kamu sekarang bisa menggunakannya untuk dipanggil dari main routine. Berikut adalah main programnya:

         .text
         .globl  main

main:
         jal     pread            # read first integer
         nop                      #  
         move    $s0,$v0          # save it in $s0
         jal     pread            # read second integer
         nop                      # 
         move    $s1,$v0          # save it in $s1
         jal     pread            # read third integer
         nop                      #  
         move    $s2,$v0          # save it in $s2
         
         addu    $s0,$s0,$s1      # compute the sum
         addu    $a0,$s0,$s2      # result in $a0
         
         li      $v0,1            # print the sum in $a0
         syscall
         
         li      $v0,10           # exit
         syscall

Perintah untuk memasukkan integer

Subroutine memerintahkan user untuk menginputkan interger. integer ini disimpan ke dalam register $v0. Berikut adalah awal subroutinenya:

# pread -- prompt for and read an integer
#
# on entry:
#    $ra -- return address
#
# on exit:
#    $v0 -- the integer

pread:   
         la    $a0,prompt        # print string
         li    $v0,4             # service 4
         syscall
        
         li    $v0,5             # read int into $v0
         syscall                 # service 5
        
         jr    $ra               # return
         nop                     # branch delay slot
        
         .data
prompt:
         .asciiz "Enter an integer: "

Contoh Program

Mari kita membuat sebuah program yang menggunakan konvensi linkage sederhana. Programnya adalah membaca tiga buah input yang diinputkan oleh user dan mengkomputasikannya. Rencananya adalah:

                # baca integer pertama
                # baca integer kedua
                # baca integer ketiga
                # hitung jumlahnya
                # tulis hasilnya

Quest 11: lihat pada rencana, manakah yang cocok untuk dijadikan sebagai subroutine?
Jawab: baca integer

Gambaran Ringkas

Gambar di bawah ini menunjukkan main memanggil mysub. Dua argumen yang dilewatkan ke subroutine berada di dalam register $a0 dan $a1.

Di dalam gambar, argumen tersebut diload menggunakan intruksi move dan li, instruksi yang lain juga boleh digunakan.

Konvensi linkage sederhana sangat terbatas untuk beberapa permasalahan. Konvensi linkage yang lebih maju akan di bahas di bab berikutnya.

CALLER melewatkan argumen-argumen ke sebuah subroutine dengan cara menyimpannya ke dalam register. Ini adalah satu-satunya cara bagaimana sebuah data bisa dilewatkan ke dalam subroutine. Subroutine juga mengembalikan nilai dari hasil pekerjaannya dia dalam bentuk register. Ini adalah satu-satunya cara bagaimana sebuah subroutine menimbalbalikkan nilai kepada CALLER. Subroutine tidak boleh menggunakan memory yang dipakai oleh CALLER. dan CALLER juga tidak boleh menggunakan memory yang digunaka oleh subroutine.

Konvensi Linkage Sederhana

Berikut adalah contoh dari calling convention. Konvensi ini sederhana dan tidak cocok untuk program yang lebih rumit. Tapi ini mengilustrasikan ide yang bisa digunakan untuk program yang kompleks selanjutnya. Mari kita sebut saja sebagai konvensi linkage sederhana. Aturannya adalah:

  1. Sebuah subroutine dipanggil dengan intruksi jal
  2. Sebuah subroutine tidak boleh memanggil subroutine yang lain
  3. Subroutine kemmbali ke CALLER dengan cra jr $ra
  4. Register yang digunakan adalah sebagai berikut:
    • $t0 - $t9 — Subroutine bebas menggunakan register ini
    • $s0 - $s7 — Subroutine tidak boleh mengubah isi dari register ini
    • $a0 - $a3 — Register ini berisi argumen tentang subroutine. Subroutine boleh mengubahnya
    • $v0 - $v1 — Register ini berisi nilai yang dihasilkan oleh subroutine
  5. Main routine mengembalikan kontrol ke user menggunakan exception handler
Secara subroutine tidak boleh memanggil subroutine yang lain maka program yang kita buat akan menggunakan main routine yang memanggil beberapa subroutine dan setiap subroutine harus kembali ke main routine.

Quest 9: Pertimbangkan ini, kenapa sebuah subroutine tidak boleh memanggil subroutine yang lain?
Jawab: karena register yang digunakan untuk menyimpan return address hanya satu sehingga kalau subroutine memanggil subroutine maka address untuk kembali ke main routine bisa hilang.

Penggunaan Register

Salah satu tujuan dari penulisan subroutine adalah, untuk membuat modul yang mandiri dengan sumberdaya yang masih bebas / tersisa.

Isu yang lain adalah bagaimana data dilewatkan dan dikeluarkan dari subroutine. Sementara main routine atau routine-routine lainnya mungkin juga sedang membutuhkan tempat data itu (register).

Dengan menggunakan konvensi software, register dinamai dengan berbagai maksud dan tujuan.
  • $t0 - $t9 — Subroutine bebas menggunakan register ini
  • $s0 - $s7 — Subroutine tidak boleh mengubah isi dari register ini
  • $a0 - $a3 — Register ini berisi argumen tentang subroutine. Subroutine boleh mengubahnya
  • $v0 - $v1 — Register ini berisi nilai yang dihasilkan oleh subroutine

Calling Convention

Diagram menunjukkan subroutine sub dipanggil dari beberapa lokasi. Tiap kali sub dipanggi, dia kembali ke address yang sesuai.

Calling convention adalah metode tentang bagaimana sebuah sub dipanggil dan cara mengembalikan sub mengembalikan kontrol ke CALLER. Seringnya ini disebut sebagai bagaimana sebuah software berhasil pada processor yang mendukung kemampuan subroutine.

Bahasa yang berbeda maupun processor yang berbeda biasanya memuat calling convention yang berbeda pula. Bab ini akan membahas beberapa jenis calling convention yang menunjuukkan seperti apa itu calling convention, bukan membahas calling convention yang ada di berbagai OS.

Instruksi jr

Intruksi jr bekerja mengembalikan kontrol ke CALLER, dia mengcopy nilai $ra ke PC.

Biasanya kamu menganggapnya sebagai intruksi yang jump ke alamat yang ada di $ra.

Untuk membuat instruksi ini lebih umum, dia bisa digunakan untuk jump ke address yang ada di register tidak hanya $ra. Seperti yang lainnya intruksi ini juga diikuti oleh branch delay slot.

Diagram menunjukkan subroutine mengembalikan ke return address yang sebelumnya telah dibuat oleh instruksi jal.

Contoh instruksi Jal

Diagram menunjukkan eksekusi dari instruksi jal. jal berada di address 0x00400014. Return address adalah 0x0040001C yang mana merupakan jal address plus delapan. (intruksi addu di bawah ini hanyalah sebagai contoh sebuah return address).

Mengembalikan subroutine ke return address disebut instruksi jr, akan kita bahas di halaman berikutnya.

Seperti inilah bagaimana intruksi jal dieksekusi:
  1. jal pertama-tama menunggu PC naik 4 angka ; PC = PC ↑ 4
  2. kemudian mengisi $ra dengan PC + 4; $ra = PC + 4
  3. kemudian mengubah PC dengan address subroutine
Intruksi yang berada di branch delay slot dieksekusi sebelum instruksi yang ada di subroutine. Kontrol telah diberikan kepada subroutine dan return address ada di $ra.

Instruksi Jal

Register yang digunakan untuk linkage adalah $31, yang disebut $ra. Dia memegang return address untuk subroutine. Instruksi yang berfungsi untuk meletakkan return address ke $ra disebut jal.

Register $31 adalah salah satu dari dua general purpose register yang berbeda dengan yang lain. Instruksi jal dan register $31 memberikan dukungan kepada hardware untuk bisa mengimplementasikan subroutine secara elegan.

Untuk memahami bagaimana jal bekerja, ingat lagi siklus mesin Instruksi jal melakukan sesuatu terhadap PC pada saat fase eksekusi siklus mesin.

jal sub    # $ra <― PC+4  (the address 8 bytes away from the jal) 
           # PC  <― sub   load the PC with the subroutine entry point
           # a branch delay slot follows this instruction

Sangat rumit: Step tengah dari siklus mesin telah menambah PC dengan +4, pada titik ini PC telah memegang alamat instruksi yang setelah jal. Kemudian karena jal telah dieksekusi bekerja dengan cara mengisi $ra dengan PC+4 itu artinya $ra memegang address yang berada 2 instruksi dibawah jal.

Return address yang benar adalah address dari jal ditambah 8. Ini karena (1) adanya delai slot (2) menyatakan return address di jal akan membingungkan karena jal akan dieksekusi lagi jika return address adalah jal.