Laman

Senin, 15 April 2013

Masalah Register

Pada konvensi linkage sederhana sebelumnya, register $s0 - $s7 tidak boleh diubah oleh subroutine. Tapi keterbatasan seperti ini akan menimbulkan masalah jika subroutine memanggil subroutine yang lain.

Misal main memanggil subA dan subA memanggil subB. subA tidak boleh menyimpan nilai ke $s0 -$s7, tapi nilai yang ada di $t0 - $t9 mungkin bercampur dengan subB secara subA dan subB sama-sama subroutine. Efeknya membuat subroutine tidak bisa saling berbagi register, dan ini tidak baik.

Solusinya adalah subA boleh menggunakan $s0 - $s7 tetapi dia musti menumpuk dulu nilai sebelumnya ke dalam stack, nanti setelah subA kembali ke callernya dia mengembalikan lagi nilai yang telah ditumpuk di stack kembali ke register.

Quest 4: Apakah tidak apa-apa menumpuk $s0 - $s7 dan $ra ke dalam stack?
Jawab: Yes, hanya saja pastikan urutan menge-push dan menge-pop nilai untuk kembali ke tempatnya dengan benar.

Rantai Subroutine

Sekarang mari kita lihat pada contoh mengenai subroutine yang memanggil subroutine yang lain. Sebuah subroutine yang memanggil subroutine yang lain harus menumpuk return address ke dalam stack. Saat dia akan kembali ke callernya maka dia menge-pop return address tersebut dari stack.

Di gambar, main dipanggil oleh OS. Selama main memakai kontrol dia menumpuk $ra ke dalam stack (step 1). Main bekerja sebentar dan kemudian memanggi subA. subA langsung menumpuk $ra ke dalam stack (step 2). Sekarang return address yang digunakan subA untuk kembali ke main sedang ditumpuk ke stack.

Selanjutnya subA memanggil subB yang mana langsung saja subB menumpuk $ra ke dalam stack (step 3). Return address buat subB untuk kembali sekarang ada di tumpukan stack.

Sekarang subB memanggil subC, subC tidak memanggil lagi subroutine sehingga $ra tidak perlu ditumpuk lagi. subC bekerja sebentar dan akhirnya kembali ke caller dengan intruksi jr $ra (step 5).

Sekarang subB  mendapat kontrol lagi. subB kembali ke callernya dengan cara mengepop return address dan mengeksekusi jr $ra (step 6).

Sekarang subA dapat kontrol lagi, return address yang dia perlukan ada di atas stack. subA kembali ke caller dengan cara mengepop stack ke $ra dan melakukan jr $ra (step 7).

Akhirnya main mendapat kontrol kembali, setelah melakukan tugasnya dia mengembalikan kontrol ke OS dengan menge-pop stack ke $ra dan menggunakan instruksi jr $ra (step 8).

Menge-Push Return Address

Untuk kembali ke caller, subroutine harus memiliki return address yang benar di dalam $ra saat intruksi jr dilaksanakan. Tetapi alamat ini tidak harus terus menerus menetap di dalam $ra selama subroutine berjalan. Lebih baik menyimpan nilai ini ke suatu tempat dan sewaktu-waktu bisa dikembalikan lagi.

Di dalam gambar, operating system memanggil main. Return address untuk kembali ke operating system ada di $ra. Selama dia mendapatkan kontrol, main menge-push return address ke dalam stack (step 1). Return addres yang akan digunakan main untk kembali ke operating system kini sedang ditumpuk ke dalam stack.

Push dan pop yang berada di gambar adalah secara konsep. Code yang sebenarnya di dalam melaksanakan hal ini adalah dengan cara biasa.

Setelah menge-push return address, main melakukan komputasi beberapa dan kemudian memanggil subC menggunakan intruksi jal (step2). dan akhirnya mengubah isi dari $ra menjadi return address untuk subC kembali ke main, beruntungnya return address untuk main kembali ke operating system telah disimpan dengan aman di dalam stack.

subC kemudian mendapat kontrol untuk mengerjakan bagiannya. Karena dia tidak memanggil subroutine yang lain, subC tidak melakukan tindakan untuh mengubah $ra, dan tidak perlu menumpuknya ke dalam stack. Saat subC ingin kembali ke main maka dia hanya perlu menggunakan intruksi jr $ra (step 3).

Setelah kontrol kembali ke main, kemudian dia bekerja sebentar dan akhirnya dia harus mengembalikan kontrol ke OS dengan cara menge-pop return addres dari stack baru kemudian melakukan instruksi jr $ra (step 4).

Exception handler adalah salah satu cara untuk mengembalikan kontrol ke OS, tapi untuk sekarang kita tidak menggunakan itu dlu.