Trước đến giờ, chúng ta sử dụng thuật ngữ “gọi hàm” nhưng chưa đi vào chi tiết. Chúng ta chỉ đơn giản giả định rằng các lời gọi hàm thực hiện công việc của nó một cách tự động. Và bây giờ đã đến lúc để chúng ta đi sâu tìm hiểu và giải thích cơ chế hoạt động của chúng như thế nào.
Hãy xem ví dụ sau →
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#include <iostream> using namespace std; int function(int parameter) { return parameter * 2; } int main(void) { int var = 1; var = function(var); var = function(var); var = function(var); cout << var << endl; return 0; } |
function là một hàm lấy tham số đầu vào nhân với 2 rồi trả về kết quả cho invoker. Hàm này được gọi 3 lần bên trong hàm main. OK, rất rõ ràng, giờ chúng ta sẽ đi tiếp. Chúng ta sẽ phần tích code dưới góc nhìn của trình biên dịch. Nó sẽ đọc code của hàm function, dịch nó sang mã máy và lưu lại ở một nới khác trong bộ nhớ. Nhưng mã máy đó vẫn chưa thể sử dụng được nếu chưa thực hiện thêm một số bước nữa. Mã code của mỗi hàm cần phải được bổ sung thêm 2 thành phần quan trọng nữa có tên là prologue và epilogue.
Prologue là một phần code được chạy ngầm trước khi hàm được chạy, nó chịu trách nhiệm lấy những tham số được truyền từ invoker và lưu vào một vùng bộ nhớ gọi là “stack“.
Epilogue là một phần code được chạy ngầm ngay sau mã code của hàm và chịu trách nhiệm chuyển kết quả của hàm về cho invoker và xóa những giá trị được lưu vào stack bởi prologue.