Trong chuỗi bài viết về Kiến trúc MIPS, chúng ta đã tìm hiểu về cấu trúc và đặc điểm chung của kiến trúc này. Tiếp theo, chúng ta sẽ khám phá các lệnh quan trọng trong MIPS. Các lệnh này cung cấp khả năng thực hiện các phép toán và điều khiển.
Giới thiệu về các loại lệnh trong MIPS
Trong kiến trúc MIPS, có ba loại lệnh chính: R (Register), I (Immediate), và J (Jump).
Lệnh R (Register)
Loại lệnh này sử dụng các thanh ghi (register) để thực hiện các phép toán. Cấu trúc 32 bit của một lệnh R trong MIPS như sau:
- Opcode (6 bit): Mã lệnh (định nghĩa phép toán).
- Rs (5 bit): Số hiệu thanh ghi đầu tiên.
- Rt (5 bit): Số hiệu thanh ghi thứ hai.
- Rd (5 bit): Số hiệu thanh ghi đích.
- Shamt (5 bit): Số lượng dịch bit (shift amount).
- Funct (6 bit): Mã chức năng (xác định phép toán cụ thể).
Lệnh I (Immediate)
Loại lệnh này thực hiện các phép toán sử dụng giá trị ngay tức thì (immediate value) và thanh ghi. Cấu trúc 32 bit của một lệnh I trong MIPS như sau:
- Opcode (6 bit): Mã lệnh (định nghĩa phép toán).
- Rs (5 bit): Số hiệu thanh ghi đầu tiên.
- Rt (5 bit): Số hiệu thanh ghi thứ hai hoặc thanh ghi đích.
- Immediate (16 bit): Giá trị ngay tức thì.
Lệnh J (Jump)
Loại lệnh này được sử dụng để thực hiện nhảy tới một địa chỉ cụ thể trong chương trình. Cấu trúc 32 bit của một lệnh J trong MIPS như sau:
- Opcode (6 bit): Mã lệnh (định nghĩa phép toán).
- Address (26 bit): Địa chỉ nhãn (label) cần nhảy tới.
MIPS Instruction References Table
Bảng mô tả lệnh của kiến trúc MIPS
Bạn có thể tham khảo đầy đủ References Table của MIPS tại đây: https://inst.eecs.berkeley.edu/~cs61c/resources/MIPS_Green_Sheet.pdf
Dưới đây là bảng tham khảo các lệnh thông dụng trong kiến trúc MIPS:
Tên lệnh | Mnemonic | Format | Operation trong Verilog | Opcode/Funct |
---|---|---|---|---|
Cộng | add | R | R[rd] = R[rs] + R[rt] | 100000 |
Trừ | sub | R | R[rd] = R[rs] – R[rt] | 100010 |
Cộng (immediate) | addi | I | R[rt] = R[rs] + Immediate | 001000 |
Cộng không xử lý tràn số | addu | R | R[rd] = R[rs] + R[rt] | 100001 |
Trừ (immediate) | subi | I | R[rt] = R[rs] – Immediate | 001001 |
Nhảy | j | J | PC = JumpAddress | 000010 |
Nhảy nếu bằng nhau | beq | I | if (R[rs] == R[rt]) PC = PC + 4 + (Immediate << 2) | 000100 |
Nhảy nếu khác nhau | bne | I | if (R[rs] != R[rt]) PC = PC + 4 + (Immediate << 2) | 000101 |
Nhảy nếu lớn hơn 0 | bgtz | I | if (R[rs] > 0) PC = PC + 4 + (Immediate << 2) | 000111 |
Load từ bộ nhớ | lw | I | R[rt] = Memory[R[rs] + Immediate] | 100011 |
Lưu vào bộ nhớ | sw | I | Memory[R[rs] + Immediate] = R[rt] | 101011 |
Giải thích các thuật ngữ:
- Immediate: Immediate là giá trị ngay tức thì được sử dụng trong các lệnh I để thực hiện phép toán. Giá trị Immediate được lưu trữ trong trường 16 bit của lệnh I và có thể là một số nguyên dương hoặc số nguyên âm. Khi thực hiện phép toán, giá trị Immediate sẽ được kết hợp với giá trị của thanh ghi để thực hiện phép tính tương ứng.
- Memory[]: Memory đề cập đến bộ nhớ trong kiến trúc MIPS. Nó là một không gian lưu trữ dùng để lưu trữ dữ liệu và các chỉ thị của chương trình. Trong lệnh lw, giá trị từ bộ nhớ được lấy từ địa chỉ được tính bằng cách cộng giá trị của thanh ghi Rs với giá trị của Immediate.
- R[]: R đề cập đến thanh ghi (register) trong kiến trúc MIPS. Các thanh ghi là nơi lưu trữ và xử lý dữ liệu trong các lệnh MIPS. Trong các lệnh, chúng ta thực hiện các phép toán trên các thanh ghi R thông qua các chỉ thị như Rs, Rt và Rd.
- JumpAddress: JumpAddress là địa chỉ đích mà lệnh nhảy (jump) trong MIPS sẽ nhảy tới. Trong lệnh j, giá trị JumpAddress là 26 bit cuối của lệnh J và được kết hợp với các bit cao của địa chỉ hiện tại để xác định địa chỉ mới mà chương trình sẽ nhảy tới.
- PC: PC (Program Counter) là một thanh ghi trong kiến trúc MIPS lưu trữ địa chỉ hiện tại của lệnh đang được thực thi. Khi chương trình thực hiện lệnh nhảy (jump), giá trị PC sẽ được thay đổi để chỉ định địa chỉ mới mà chương trình sẽ tiếp tục thực thi.
Giải thích và ví dụ các lệnh trong MIPS
Lệnh toán học
- Lệnh
add
thực hiện phép cộng hai số và lưu kết quả vào thanh ghi đích. Ví dụ:add $t0, $t1, $t2
thực hiện cộng giữa giá trị trong thanh ghi$t1
và$t2
, rồi lưu kết quả vào$t0
. - Lệnh
sub
trừ hai số và lưu kết quả vào thanh ghi đích. Ví dụ:sub $t0, $t1, $t2
thực hiện phép trừ giữa giá trị trong thanh ghi$t1
và$t2
, rồi lưu kết quả vào$t0
. - Lệnh
addi
thực hiện phép cộng số ngay tức thì với giá trị trong thanh ghi và lưu kết quả vào thanh ghi đích. Ví dụ:addi $t0, $t1, 5
cộng giá trị trong thanh ghi$t1
với 5, rồi lưu kết quả vào$t0
. - Lệnh
addu
thực hiện phép cộng hai số không xử lý tràn và lưu kết quả vào thanh ghi đích. Ví dụ:addu $t0, $t1, $t2
cộng giá trị trong thanh ghi$t1
và$t2
mà không quan tâm đến tràn số, rồi lưu kết quả vào$t0
. - Lệnh
subi
trừ số ngay tức thì với giá trị trong thanh ghi và lưu kết quả vào thanh ghi đích. Ví dụ:subi $t0, $t1, 5
trừ giá trị trong thanh ghi$t1
với 5, rồi lưu kết quả vào$t0
.
Lệnh nhảy
- Lệnh
j
thực hiện nhảy đến một địa chỉ cố định. Ví dụ:j loop
nhảy đến nhãnloop
trong chương trình. - Lệnh
beq
thực hiện nhảy nếu hai giá trị bằng nhau. Ví dụ:beq $t0, $t1, label
nếu giá trị trong thanh ghi$t0
và$t1
bằng nhau, thì nhảy đến nhãnlabel
trong chương trình. - Lệnh
bne
thực hiện nhảy nếu hai giá trị khác nhau. Ví dụ:bne $t0, $t1, label
nếu giá trị trong thanh ghi$t0
và$t1
khác nhau, thì nhảy đến nhãnlabel
trong chương trình. - Lệnh
bgtz
thực hiện nhảy nếu giá trị lớn hơn 0. Ví dụ:bgtz $t0, label
nếu giá trị trong thanh ghi$t0
lớn hơn 0, thì nhảy đến nhãnlabel
trong chương trình.
Lệnh thao tác bộ nhớ
- Lệnh
lw
load từ bộ nhớ vào thanh ghi. Ví dụ:lw $t0, 0($t1)
load giá trị từ địa chỉ0 + $t1
trong bộ nhớ và lưu vào thanh ghi$t0
. - Lệnh
sw
lưu từ thanh ghi vào bộ nhớ. Ví dụ:sw $t0, 0($t1)
lưu giá trị từ thanh ghi$t0
vào địa chỉ0 + $t1
trong bộ nhớ.
Mô phỏng chương trình đơn giản bằng MIPS
Dưới đây là một ví dụ mô phỏng chương trình đơn giản bằng MIPS. Chương trình này thực hiện các phép toán cộng, trừ, nhân, chia và giải phương trình bậc nhất.
.data A: .word 2 B: .word 3 C: .word 0 .text main: lw $t0, A # Load giá trị của A vào thanh ghi $t0 lw $t1, B # Load giá trị của B vào thanh ghi $t1 add $t2, $t0, $t1 # Tính tổng: $t2 = $t0 + $t1 sub $t3, $t0, $t1 # Tính hiệu: $t3 = $t0 - $t1 mul $t4, $t0, $t1 # Tính tích: $t4 = $t0 * $t1 div $t5, $t0, $t1 # Tính thương: $t5 = $t0 / $t1 sw $t2, C # Lưu giá trị tổng vào C # Giải phương trình bậc nhất Ax + B = 0 neg $t1, $t1 # Đảo dấu B div $t1, $t0 # Chia B cho A mflo $t6 # Lưu kết quả vào $t6 j end # Nhảy đến kết thúc chương trình end: # Kết thúc chương trình
Trong ví dụ này, chúng ta sử dụng các lệnh MIPS như lw
, add
, sub
, mul
, div
, sw
, neg
, mflo
, và j
để thực hiện các phép toán và điều khiển. Kết quả cuối cùng sẽ được lưu trong thanh ghi $t6
và được sử dụng để giải phương trình bậc nhất.
Tổng kết
Trên đây là một cái nhìn tổng quan về các lệnh quan trọng trong kiến trúc MIPS, bao gồm giải thích, ví dụ và một chương trình đơn giản. Hi vọng rằng thông qua bài viết này, bạn đã có cái nhìn sâu hơn về lệnh trong MIPS và cách chúng hoạt động.
One Reply to “MIPS Architecture Series – Phần 2: Lệnh”