Trong phần này của chuỗi bài viết về kiến trúc MIPS, chúng ta sẽ tìm hiểu về cách chuyển đổi các câu lệnh điều kiện và vòng lặp từ ngôn ngữ lập trình C++ sang MIPS Assembly. Trước khi đi vào phần chính, hãy tóm tắt lại những gì chúng ta đã học ở bốn phần trước.
Sơ lược về 4 phần trước của loạt bài MIPS Architecture
Phần 1: Datapath
Chúng ta đã tìm hiểu về cấu trúc tổng quan của datapath trong kiến trúc MIPS, bao gồm các thành phần chính như thanh ghi (register), bộ nhớ (memory), bộ điều khiển (control unit) và ALU (Arithmetic Logic Unit). Datapath chịu trách nhiệm thực hiện các phép tính và lưu trữ dữ liệu trong quá trình thực thi chương trình.
Phần 2: Lệnh
Chúng ta đã xem xét các loại lệnh cơ bản trong MIPS Assembly như lệnh di chuyển, lệnh logic, lệnh nhảy và lệnh điều kiện. Mỗi lệnh có định dạng và tác dụng riêng, và chúng được biểu diễn dưới dạng các mã máy thích hợp.
Phần 3: Syscall
Chúng ta đã tìm hiểu về các lệnh syscall trong MIPS, cho phép chương trình tương tác với hệ điều hành để thực hiện các thao tác nhập xuất thông qua bộ điều khiển.
Phần 4: MARS
Chúng ta đã khám phá công cụ MARS (MIPS Assembler and Runtime Simulator), một môi trường giả lập cho phép chạy các chương trình MIPS và xem kết quả.
Giới thiệu về lệnh rẽ nhánh và nhảy trong MIPS
Trong MIPS, có các lệnh rẽ nhánh (branch) và lệnh nhảy (jump) để điều khiển luồng thực thi của chương trình. Lệnh rẽ nhánh kiểm tra một điều kiện nào đó và dựa trên kết quả, quyết định xem chương trình tiếp tục thực hiện ở địa chỉ nào tiếp theo. Lệnh nhảy cho phép chương trình nhảy tới một địa chỉ được chỉ định.
Rẽ nhánh (branch)
Lệnh rẽ nhánh trong MIPS Assembly thường được sử dụng để kiểm tra một điều kiện và nhảy tới một địa chỉ kh
ác dựa trên kết quả của điều kiện đó. Cú pháp của lệnh rẽ nhánh như sau:
beq rs, rt, label # Nhảy tới 'label' nếu giá trị của rs và rt bằng nhau bne rs, rt, label # Nhảy tới 'label' nếu giá trị của rs và rt khác nhau
Trong đó:
rs
vàrt
là các thanh ghi mà chúng ta muốn so sánh.label
là một nhãn (label) mà chúng ta muốn nhảy tới nếu điều kiện đúng.
Ví dụ, để kiểm tra xem giá trị trong thanh ghi $s0
có bằng 0 hay không, chúng ta có thể sử dụng lệnh beq
như sau:
beq $s0, $zero, label
Nếu $s0
bằng 0, chương trình sẽ nhảy tới nhãn label
.
Nhảy (jump)
Lệnh nhảy trong MIPS Assembly cho phép chương trình nhảy tới một địa chỉ cụ thể. Cú pháp của lệnh nhảy như sau:
j label # Nhảy tới 'label'
Trong đó:
label
là một nhãn (label) mà chúng ta muốn nhảy tới.
Ví dụ, để nhảy tới nhãn loop
, chúng ta có thể sử dụng lệnh j
như sau:
j loop
Chương trình sẽ tiếp tục thực hiện từ địa chỉ của nhãn loop
.
Áp dụng lệnh rẽ nhánh để chuyển đổi câu lệnh if-else trong C++ sang MIPS
Để chuyển đổi câu lệnh if-else trong C++ sang MIPS, chúng ta có thể sử dụng lệnh rẽ nhánh. Ví dụ, giả sử chúng ta có một đoạn mã C++ như sau:
if (a > b) { // Khối lệnh A } else { // Khối lệnh B }
Chúng ta có thể chuyển đổi nó sang MIPS Assembly như sau:
slt $t0, $s0, $s1 # so sánh a và b beq $t0, $zero, else # nếu a <= b, nhảy tới else # Khối lệnh A j end # nhảy tới cuối khối if-else else: # Khối lệnh B end:
Ở đây, $s0
và $s1
là thanh ghi lưu trữ giá trị của a
và b
tương ứng. Lệnh slt
so sánh giá trị của $s0
và $s1
, và kết quả được lưu trong thanh ghi $t0
. Lệnh beq
kiểm tra xem $t0
có bằng 0 hay không (tức là a <= b), nếu có, chương trình nhảy tới nhãn else
. Nếu không, chương trình tiếp tục thực hiện khối lệnh A và sau đó nhảy tới nhãn end
.
Áp dụng lệnh rẽ nhánh để chuyển đổi câu lệnh lặp C++ sang MIPS
Để chuyển đổi câu lệnh lặp trong C++ sang MIPS, chúng ta có thể sử dụng lệnh rẽ nhánh kết hợp với các lệnh di chuyển. Ví dụ, giả sử chúng ta có một đoạn mã C++ như sau:
for (int i = 0; i < 10; i++) { // Khối lệnh }
Chúng ta có thể chuyển đổi nó sang MIPS Assembly như sau:
li $t0, 0 # Khởi tạo biến đếm i = 0 loop: bge $t0, 10, end # Nếu i >= 10, thoát khỏi vòng lặp # Khối lệnh addi $t0, $t0, 1 # Tăng giá trị của i lên 1 j loop # Quay lại đầu vòng lặp end:
Ở đây, $t0
là thanh ghi lưu trữ giá trị của biến đếm i
. Lệnh li
được sử dụng để khởi tạo giá trị ban đầu của i
là 0. Lệnh bge
kiểm tra xem $t0
có lớn hơn hoặc bằng 10 hay không. Nếu có, chương trình nhảy tới nhãn end
, kết thúc vòng lặp. Nếu không, chương trình tiếp tục thực hiện khối lệnh và sau đó tăng giá trị của i
lên 1 bằng lệnh addi
. Cuối cùng, chương trình nhảy lại đầu vòng lặp bằng lệnh j
.
Kết luận
Trong phần này, chúng ta đã tìm hiểu về cách chuyển đổi các câu lệnh if-else và lệnh lặp từ ngôn ngữ lập trình C++ sang MIPS Assembly. Bằng cách sử dụng lệnh rẽ nhánh và nhảy trong MIPS, chúng ta có thể điều khiển luồng thực thi của chương trình một cách linh hoạt. Việc hiểu và áp dụng các lệnh này sẽ giúp chúng ta xây dựng các chương trình MIPS mạnh mẽ và hiệu quả.
References: Bài giảng môn Tổ chức và Cấu trúc Máy tính, khoa KTMT – Trường ĐH CNTT (UIT)