Kiến trúc máy tính là một lĩnh vực rộng lớn và đầy thách thức, trong đó chương 2 tập trung vào kiến trúc tập lệnh (Instruction Set Architecture – ISA) đóng vai trò nền tảng. Bài viết này của maytinhgiaphat.vn sẽ cung cấp một cái nhìn toàn diện về các khái niệm cốt lõi trong kiến trúc tập lệnh MIPS, đồng thời lồng ghép các ví dụ và tình huống thực hành như những bài tập kiến trúc máy tính chương 2 giúp bạn củng cố kiến thức và hiểu sâu hơn về cách CPU thực thi các lệnh. Nội dung hướng đến sinh viên ngành công nghệ thông tin, kỹ sư phần cứng, hoặc bất kỳ ai muốn nắm vững cấu tạo và hoạt động bên trong của một hệ thống máy tính.
Tổng Quan Về Kiến Trúc Tập Lệnh và Vai Trò Của MIPS
Kiến trúc tập lệnh (ISA) chính là giao diện giữa phần mềm và phần cứng, định nghĩa tập hợp các lệnh mà một bộ vi xử lý có thể hiểu và thực thi. ISA quy định cách bộ nhớ được tổ chức, các loại dữ liệu được hỗ trợ, cách các lệnh được mã hóa và giải mã, và cách các chương trình tương tác với phần cứng. MIPS (Microprocessor without Interlocked Pipeline Stages) là một kiến trúc tập lệnh rút gọn (RISC) phổ biến, được sử dụng rộng rãi trong giảng dạy và nghiên cứu về kiến trúc máy tính nhờ sự đơn giản, rõ ràng và hiệu quả. Việc nắm vững MIPS sẽ cung cấp một nền tảng vững chắc để hiểu các ISA phức tạp hơn như x86 hay ARM.
Sự Tiến Hóa Của ISA và Chu Kỳ Thực Thi Lệnh Cơ Bản
Các kiến trúc tập lệnh không ngừng phát triển để đáp ứng yêu cầu hiệu suất và tính năng ngày càng cao của máy tính. Ví dụ, từ 8086 đến Pentium 4 hay các phiên bản MIPS như MIPS-I, MIPS-II, MIPS-64 đều cho thấy sự cải tiến liên tục trong cách tổ chức và thực thi lệnh. Chu kỳ thực thi lệnh cơ bản là một quy trình lặp đi lặp lại mà CPU thực hiện để xử lý một chương trình. Quy trình này bao gồm sáu bước chính, mỗi bước đóng góp vào việc biến một lệnh phần mềm thành hành động vật lý của phần cứng.
Các bước trong chu kỳ thực thi lệnh cơ bản gồm:
- Instruction Fetch (IF): Lấy lệnh từ bộ nhớ chương trình.
- Instruction Decode (ID): Giải mã lệnh để xác định hành động cần thực hiện và kích thước lệnh.
- Operand Fetch (OF): Xác định và lấy dữ liệu toán hạng cần thiết cho lệnh.
- Execute (EX): Thực hiện phép tính toán hoặc logic theo yêu cầu của lệnh.
- Result Store (RS): Lưu trữ kết quả vào thanh ghi hoặc bộ nhớ để sử dụng sau này.
- Next Instruction (NI): Xác định địa chỉ của lệnh tiếp theo để tiếp tục chu trình.
Những bước này diễn ra tuần tự và lặp lại liên tục, tạo nên nhịp đập hoạt động của một bộ xử lý.
Cách Bộ Xử Lý Thực Thi Chương Trình
Bộ xử lý thực thi một chương trình bằng cách lặp lại chu kỳ thực thi lệnh. Mỗi lần lặp, nó xử lý một lệnh từ chương trình. Quá trình này có thể được hình dung như sau:
Xem Thêm Bài Viết:
- Hộp mực máy in HP LaserJet Pro M402: Chọn loại nào?
- Hộp Mực Máy In Brother 2520D Chính Hãng
- Giá máy khoan Bosch Made in Germany: Đánh giá chi tiết
- Cách Tính Công Suất Tiêu Thụ Điện Của Máy Tính Hiệu Quả
- Giá máy in tem mã vạch: Cập nhật và yếu tố ảnh hưởng
- Tải lệnh: Bộ xử lý lấy lệnh từ bộ nhớ chính.
- Tìm ra toán tử được sử dụng: Giải mã lệnh để biết các toán hạng nào (dữ liệu đầu vào) sẽ được sử dụng.
- Tìm ra dữ liệu nào được sử dụng: Lấy các giá trị của toán hạng từ thanh ghi hoặc bộ nhớ.
- Thực hiện tính toán: Đơn vị số học/logic (ALU) thực hiện phép toán được chỉ định bởi lệnh.
- Tìm lệnh tiếp theo: Cập nhật bộ đếm chương trình (PC) để trỏ đến lệnh tiếp theo.
Quá trình này được lặp lại cho đến khi chương trình kết thúc. Hiểu rõ quy trình này là chìa khóa để giải quyết các bài tập kiến trúc máy tính chương 2 liên quan đến luồng điều khiển và xử lý dữ liệu.
Kiến Trúc Princeton vs. Harvard: Tối Ưu Hóa Bộ Nhớ
Trong kiến trúc máy tính, cách bộ nhớ được tổ chức ảnh hưởng đáng kể đến hiệu suất. Hai mô hình phổ biến là kiến trúc Princeton (Von Neumann) và kiến trúc Harvard.
Kiến Trúc Princeton (Von Neumann)
- Đặc điểm: Dữ liệu và lệnh được trộn lẫn trong cùng một bộ nhớ hợp nhất. Bộ xử lý sử dụng một bus duy nhất để truy cập cả lệnh và dữ liệu.
- Ưu điểm: Linh hoạt trong việc sử dụng bộ nhớ (chương trình có thể coi dữ liệu là chương trình và ngược lại), tận dụng tối đa không gian lưu trữ.
- Nhược điểm: Gây ra “nút cổ chai Von Neumann” vì CPU không thể đồng thời đọc lệnh và ghi/đọc dữ liệu, làm giảm hiệu suất trong các ứng dụng đòi hỏi truy cập bộ nhớ cao.
- Ví dụ ứng dụng: Hầu hết các máy tính cá nhân hiện đại sử dụng biến thể của kiến trúc Von Neumann.
Kiến Trúc Harvard
- Đặc điểm: Dữ liệu và lệnh được lưu trữ trong các bộ nhớ riêng biệt. Bộ xử lý sử dụng các bus riêng biệt để truy cập bộ nhớ lệnh và bộ nhớ dữ liệu.
- Ưu điểm: Cho phép CPU đồng thời đọc lệnh và truy cập dữ liệu, cải thiện đáng kể thông lượng và hiệu suất. Mỗi bộ nhớ có thể được tối ưu hóa riêng biệt cho mục đích của nó.
- Nhược điểm: Kém linh hoạt hơn trong việc phân bổ bộ nhớ.
- Ví dụ ứng dụng: Các bộ xử lý tín hiệu số (DSP), vi điều khiển, và một số kiến trúc hiệu năng cao thường sử dụng kiến trúc Harvard hoặc biến thể của nó.
Khi phân tích hiệu suất trong các bài tập kiến trúc máy tính chương 2, việc lựa chọn giữa hai kiến trúc này có thể là một yếu tố quan trọng.
Các Kiểu Toán Hạng và Tập Thanh Ghi Trong MIPS
Cách mà các toán hạng (operands) được xử lý và lưu trữ là một khía cạnh cơ bản của ISA.
So Sánh Số Lượng Toán Hạng
Các kiến trúc CPU khác nhau xử lý số lượng toán hạng khác nhau trong một lệnh. Việc so sánh này thường được thực hiện qua ví dụ C = A + B:
-
Stack-based architecture (0 toán hạng):
Push APush BAdd(lấy 2 giá trị trên cùng stack, cộng, push kết quả)Pop C- Yêu cầu nhiều lệnh nhưng đơn giản hóa thiết kế CPU.
-
Accumulator-based architecture (1 toán hạng):
Load A(tải A vào thanh ghi tích lũy – accumulator)Add B(cộng B vào accumulator)Store C(lưu accumulator vào C)- Giảm số lượng lệnh so với stack, nhưng giới hạn bởi một thanh ghi duy nhất.
-
Register-memory architecture (2 toán hạng):
Load R1, AAdd R1, B(cộng B từ bộ nhớ vào R1)Store C, R1- Kết hợp ưu điểm của thanh ghi và truy cập bộ nhớ trực tiếp.
-
Load-store architecture (3 toán hạng – MIPS):
Load R1, A(tải A từ bộ nhớ vào thanh ghi R1)Load R2, B(tải B từ bộ nhớ vào thanh ghi R2)Add R3, R1, R2(cộng R1 và R2, lưu vào R3)Store C, R3(lưu R3 vào bộ nhớ C)- MIPS thuộc loại này, tất cả các phép toán số học/logic đều thực hiện trên các thanh ghi, đòi hỏi lệnh
LoadvàStoreriêng biệt để di chuyển dữ liệu giữa thanh ghi và bộ nhớ. Điều này giúp đơn giản hóa thiết kế CPU và tối ưu hóa đường ống lệnh.
Tập Thanh Ghi Trong MIPS
MIPS có một tập hợp 32 thanh ghi đa dụng (General Purpose Registers – GPRs), được đánh số từ R0 đến R31 (hoặc $0 đến $31). Các thanh ghi này đóng vai trò cực kỳ quan trọng trong việc lưu trữ dữ liệu tạm thời trong quá trình thực thi chương trình.
- R0 ($zero): Luôn có giá trị 0. Thanh ghi này rất hữu ích cho các phép toán như khởi tạo giá trị 0, di chuyển giá trị (ví dụ:
add dest, src, R0tương đương vớimove dest, src), hoặc so sánh. - R29 ($sp): Con trỏ ngăn xếp (stack pointer), được sử dụng để quản lý ngăn xếp bộ nhớ.
- R31 ($ra): Thanh ghi địa chỉ trả về (return address), lưu trữ địa chỉ của lệnh tiếp theo sau khi một hàm con được gọi hoàn tất.
- PC (Program Counter): Bộ đếm chương trình, lưu trữ địa chỉ của lệnh hiện tại đang được thực thi.
- HI & LO: Các thanh ghi đặc biệt dùng để lưu trữ kết quả của các phép nhân (phần cao và phần thấp) và phép chia.
- Thanh ghi dấu phẩy động: Dùng cho các phép toán số thực.
- Thanh ghi điều khiển: Dùng để kiểm soát lỗi hoặc trạng thái của hệ thống.
Bài tập ví dụ: Giải thích tại sao việc có thanh ghi R0 luôn bằng 0 lại hữu ích trong kiến trúc MIPS.
- Giải thích: R0 giúp đơn giản hóa tập lệnh. Thay vì cần một lệnh
MOVEriêng biệt, bạn có thể dùngADD destination, source, $zero. Nó cũng hữu ích trong các phép so sánh (ví dụ: so sánh một thanh ghi với 0) và việc khởi tạo các biến với giá trị 0. Sự có mặt của R0 giúp giảm số lượng lệnh cần thiết trong ISA, từ đó đơn giản hóa thiết kế phần cứng và trình biên dịch.
Tổ Chức Bộ Nhớ Trong MIPS
Bộ nhớ trong MIPS được tổ chức như một mảng một chiều các byte, nơi mỗi ô nhớ có kích thước 1 byte (8 bits). Địa chỉ của mỗi ô nhớ được xác định theo địa chỉ byte, và các địa chỉ này được đánh chỉ số trên mảng.
Kích Thước Bộ Nhớ và Từ (Word)
- Máy tính 32-bit: Có khả năng truy cập 2^32 ô nhớ (4 Gigabytes). Mỗi “từ” (word) trong MIPS là 32 bit (4 byte). Các từ này được lưu trữ tại các địa chỉ byte chia hết cho 4 (0, 4, 8, C…).
- Máy tính 64-bit: Có khả năng truy cập 2^64 ô nhớ (16 Exabytes). Tuy nhiên, trên thực tế, các kiến trúc 64-bit như x86 thường chỉ sử dụng khoảng 48-bit địa chỉ vật lý, cho phép truy cập tới 4 PetaByte.
- Bài tập ví dụ: Một chương trình cần lưu trữ một mảng 100 số nguyên 32-bit. Nếu số nguyên đầu tiên được lưu tại địa chỉ 0x1000, hãy xác định địa chỉ của số nguyên thứ 50 trong mảng (tính theo byte).
- Giải thích: Mỗi số nguyên là 32 bit = 4 byte. Số nguyên thứ 50 (index 49 nếu tính từ 0) sẽ cách số nguyên đầu tiên 49 4 byte.
- Địa chỉ của số nguyên thứ 50 = 0x1000 + (49 4) = 0x1000 + 0xC4 = 0x10C4.
- Bài tập ví dụ: Một chương trình cần lưu trữ một mảng 100 số nguyên 32-bit. Nếu số nguyên đầu tiên được lưu tại địa chỉ 0x1000, hãy xác định địa chỉ của số nguyên thứ 50 trong mảng (tính theo byte).
Alignment (Căn Chỉnh Địa Chỉ)
MIPS yêu cầu dữ liệu phải được “căn chỉnh” (aligned). Điều này có nghĩa là một từ (word) 4 byte phải bắt đầu ở địa chỉ byte chia hết cho 4. Tương tự, một half-word (2 byte) phải bắt đầu ở địa chỉ chia hết cho 2.
- Mục đích: Căn chỉnh giúp CPU truy cập dữ liệu hiệu quả hơn. Nếu dữ liệu không được căn chỉnh, CPU có thể phải thực hiện nhiều lần truy cập bộ nhớ hoặc các thao tác phức tạp hơn để đọc một giá trị duy nhất, làm giảm hiệu suất.
- Ví dụ: Một từ có thể được lưu ở địa chỉ 0, 4, 8, 12… nhưng không thể ở địa chỉ 1, 2, 3, 5…
Endianness (Thứ Tự Byte)
Endianness mô tả thứ tự các byte trong một từ được lưu trữ trong bộ nhớ. Có hai loại chính:
- Little Endian: Byte ít quan trọng nhất (least significant byte) được lưu tại địa chỉ thấp nhất của từ.
- Ví dụ: Với số nguyên 0x12345678, byte 0x78 sẽ ở địa chỉ thấp nhất, 0x56 ở địa chỉ tiếp theo, v.v.
- Kiến trúc sử dụng: Intel x86, DEC Vax, DEC Alpha (Windows NT).
- Big Endian: Byte quan trọng nhất (most significant byte) được lưu tại địa chỉ thấp nhất của từ.
- Ví dụ: Với số nguyên 0x12345678, byte 0x12 sẽ ở địa chỉ thấp nhất, 0x34 ở địa chỉ tiếp theo, v.v.
- Kiến trúc sử dụng: IBM 360/370, Motorola 68k, MIPS, Sparc, HP PA.
Sự khác biệt về Endianness là một vấn đề quan trọng khi trao đổi dữ liệu giữa các hệ thống có kiến trúc khác nhau. Việc này thường xuất hiện trong các bài tập kiến trúc máy tính chương 2 về giao tiếp mạng hoặc tương thích dữ liệu.
Dạng Chỉ Thị MIPS và Các Chế Độ Đánh Địa Chỉ
Các lệnh trong MIPS có độ dài cố định 32 bit và sử dụng ba dạng chỉ thị chính (R, I, J) cùng với một số chế độ đánh địa chỉ để truy cập dữ liệu.
Các Chế Độ Đánh Địa Chỉ
- Register (Direct): Toán hạng là giá trị trực tiếp trong một thanh ghi.
- Ví dụ:
add $t1, $t2, $t3(cộng nội dung thanh ghi $t2 và $t3, lưu vào $t1).
- Ví dụ:
- Immediate: Toán hạng là một hằng số được nhúng trực tiếp trong lệnh.
- Ví dụ:
addi $t1, $t2, 100(cộng giá trị 100 vào thanh ghi $t2, lưu vào $t1).
- Ví dụ:
- Base + Index (Displacement): Địa chỉ của toán hạng trong bộ nhớ được tính bằng cách cộng một hằng số (displacement) vào nội dung của một thanh ghi cơ sở (base register).
- Ví dụ:
lw $t1, 100($t2)(tải một từ từ địa chỉ $t2 + 100 vào $t1). Chế độ này thường được sử dụng để truy cập các phần tử trong mảng hoặc các trường của cấu trúc.
- Ví dụ:
- PC-relative: Địa chỉ đích cho các lệnh rẽ nhánh được tính bằng cách cộng một độ lệch (offset) vào giá trị của bộ đếm chương trình (PC) hiện tại. Điều này cho phép các lệnh rẽ nhánh nhảy đến các vị trí tương đối gần trong chương trình.
- Ví dụ:
beq $t1, $t2, Label(rẽ nhánh đếnLabelnếu $t1 bằng $t2). Địa chỉ củaLabelđược tính tương đối so với PC.
- Ví dụ:
Thống kê cho thấy các thao tác trên thanh ghi chiếm khoảng 51% tổng số tham chiếu, trong khi chế độ displacement và immediate chiếm khoảng 75%, và cả ba (displacement, immediate, register indirect) chiếm tới 85%. Điều này nhấn mạnh tầm quan trọng của các chế độ đánh địa chỉ này trong việc thiết kế và tối ưu hóa ISA.
Phân Loại Tập Lệnh MIPS
Các lệnh MIPS được phân loại dựa trên chức năng của chúng:
- Toán tử (Data Operations):
- Số học:
add,sub,mul,div,addi(add immediate). - Logic:
and,or,nor,xor,andi,ori(logic immediate). - Dịch chuyển bit:
sll(shift left logical),srl(shift right logical),sra(shift right arithmetic).
- Số học:
- Dịch chuyển dữ liệu (Data Transfer):
lw(load word): Tải một từ từ bộ nhớ vào thanh ghi.sw(store word): Lưu một từ từ thanh ghi vào bộ nhớ.lb(load byte),sb(store byte),lh(load half),sh(store half): Tải/lưu byte hoặc half-word.
- Điều khiển dòng chảy chương trình (Sequencing/Control Flow):
- Rẽ nhánh có điều kiện:
beq(branch if equal),bne(branch if not equal),slt(set on less than),slti(set on less than immediate). - Nhảy không điều kiện:
j(jump),jr(jump register),jal(jump and link).
- Rẽ nhánh có điều kiện:
Mỗi loại lệnh này có vai trò riêng biệt và được thiết kế để hoạt động hiệu quả trong môi trường load-store của MIPS.
Thực Thi Các Lệnh Cơ Bản Trong MIPS
Để hiểu sâu hơn về kiến trúc MIPS, chúng ta sẽ xem xét cách các lệnh cơ bản được thực thi.
Lệnh Toán Học/Logic (ADD/SUB)
Các lệnh add và sub thực hiện các phép cộng và trừ trên các giá trị trong thanh ghi.
- Ví dụ lệnh:
add $t1, $t2, $t3thực hiện$t1 = $t2 + $t3. - Cách thức hoạt động:
- Bộ đếm chương trình (PC) trỏ đến lệnh
add. - Lệnh được nạp vào thanh ghi lệnh và giải mã.
- Bộ điều khiển ra tín hiệu cho ALU và tệp thanh ghi biết phải làm gì (lấy $t2 và $t3, thực hiện phép cộng).
- ALU tính toán kết quả.
- Kết quả được ghi vào thanh ghi đích ($t1).
- Bộ điều khiển cập nhật PC để trỏ đến lệnh tiếp theo.
- Bộ đếm chương trình (PC) trỏ đến lệnh
Bài tập ví dụ: Chuyển biểu thức C sau sang MIPS assembly: f = (g + h) - (i + j). Giả sử f, g, h, i, j được ánh xạ tới các thanh ghi $s0, $s1, $s2, $s3, $s4 tương ứng.
- Giải thích và lời giải:
add $t0, $s1, $s2 # $t0 = g + h add $t1, $s3, $s4 # $t1 = i + j sub $s0, $t0, $t1 # $s0 = $t0 - $t1 (tức f = (g+h) - (i+j))Trong ví dụ này, chúng ta sử dụng các thanh ghi tạm thời
$t0và$t1để lưu trữ kết quả trung gian, minh họa cách các phép toán phức tạp được chia nhỏ thành các lệnh đơn giản trong MIPS.
Lệnh Dịch Chuyển Dữ Liệu (Load Word/Store Word)
Các lệnh lw (load word) và sw (store word) là cầu nối giữa các thanh ghi và bộ nhớ.
- Lệnh
lw(load word):- Cú pháp:
lw $rt, offset($base) - Ý nghĩa: Tải một từ (4 byte) từ địa chỉ bộ nhớ được tính bằng
$base + offsetvào thanh ghi$rt. - Ví dụ:
lw $t0, 8($s1)sẽ tải từ địa chỉ$s1 + 8vào thanh ghi$t0.
Bá»™ nhá»› là má»™t mảng 1 chiá»u lưu trữ dữ liệu
- Cú pháp:
- Lệnh
sw(store word):- Cú pháp:
sw $rt, offset($base) - Ý nghĩa: Lưu một từ (4 byte) từ thanh ghi
$rtvào địa chỉ bộ nhớ được tính bằng$base + offset. - Ví dụ:
sw $t0, 12($s1)sẽ lưu nội dung của$t0vào địa chỉ$s1 + 12.
- Cú pháp:
Bài tập ví dụ: Giả sử một mảng số nguyên A được lưu bắt đầu tại địa chỉ mà thanh ghi $s0 đang trỏ tới. Hãy viết đoạn mã MIPS để lấy giá trị A[5] và lưu nó vào thanh ghi $t0, sau đó cập nhật A[10] với giá trị 100.
- Giải thích và lời giải:
- Mỗi phần tử trong mảng là một từ (4 byte).
A[5]có độ lệch5 4 = 20byte so với địa chỉ gốc.A[10]có độ lệch10 4 = 40byte.lw $t0, 20($s0) # Tải A[5] vào $t0 (địa chỉ $s0 + 20) li $t1, 100 # Nạp giá trị 100 vào $t1 (li = load immediate) sw $t1, 40($s0) # Lưu 100 vào A[10] (địa chỉ $s0 + 40)
- Mỗi phần tử trong mảng là một từ (4 byte).
Lệnh Điều Khiển Rẽ Nhánh (Branch) và Nhảy (Jump)
Các lệnh này thay đổi luồng điều khiển của chương trình, cho phép thực hiện các cấu trúc điều kiện (if/else) và vòng lặp.
- Lệnh rẽ nhánh có điều kiện:
beq $rs, $rt, Label: Rẽ nhánh đếnLabelnếu nội dung của$rsbằng$rt.bne $rs, $rt, Label: Rẽ nhánh đếnLabelnếu nội dung của$rskhông bằng$rt.- Địa chỉ của
Labelđược tính tương đối so với PC hiện tại. Độ lệch tối đa thường là 16 bit, giới hạn khoảng nhảy.
Bài giảng Kiến trúc máy tÃnh – Chương 2: Kiến trúc táºp lệnh trang 2
- Lệnh nhảy không điều kiện:
j Label: Nhảy không điều kiện đếnLabel. Địa chỉ củaLabelđược tính tuyệt đối (sử dụng 26 bit địa chỉ từ lệnh, nhân 4 và kết hợp với các bit cao của PC).jr $ra: Nhảy đến địa chỉ lưu trong thanh ghi$ra. Thường được sử dụng để quay về từ một hàm con.
Bài tập ví dụ: Chuyển đoạn mã C sau sang MIPS assembly:
if (a == b) {
c = 1;
} else {
c = 2;
}
Giả sử a, b, c được lưu trong $s0, $s1, $s2 tương ứng.
- Giải thích và lời giải:
beq $s0, $s1, IfBlock # Nếu a == b, nhảy đến IfBlock # ElseBlock (nếu a != b) li $s2, 2 # c = 2 j EndIf # Nhảy đến EndIf IfBlock: li $s2, 1 # c = 1 EndIf: # Tiếp tục chương trình
Biên Dịch Thành Mã Máy và Các Định Dạng Lệnh MIPS
Để một máy tính có thể thực thi các lệnh MIPS assembly, chúng phải được chuyển đổi thành mã máy (machine code) – một chuỗi các bit 0 và 1. Quá trình này được gọi là biên dịch (assembly).
Mã Hóa và Các Trường Lệnh MIPS
Mỗi lệnh MIPS có độ dài 32 bit, được chia thành nhiều trường (fields) khác nhau, mỗi trường mang một ý nghĩa cụ thể:
opcode: Mã hoạt động, xác định loại phép toán (ví dụ:add,lw,beq).rs: Chỉ số thanh ghi chứa toán hạng nguồn 1.rt: Chỉ số thanh ghi chứa toán hạng nguồn 2 (hoặc thanh ghi đích cholw/addi).rd: Chỉ số thanh ghi lưu trữ kết quả.shamt: Số lượng dịch chuyển (dùng cho các lệnh dịch bit).funct: Mã chức năng bổ sung, dùng để phân biệt các lệnh có cùngopcode(ví dụ:addvàsubcó cùngopcodenhưngfunctkhác nhau).
Ví dụ: Lệnh add $s0, $s1, $s2 (tức $s0 = $s1 + $s2) khi biên dịch có thể trông như sau (giả sử $s0, $s1, $s2 tương ứng là R16, R17, R18):
000000 10001 10010 10000 00000 100000
opcode(6 bit):000000(dành cho các lệnh R-format)rs(5 bit):10001(R17 hay $s1)rt(5 bit):10010(R18 hay $s2)rd(5 bit):10000(R16 hay $s0)shamt(5 bit):00000(không dùng cho lệnh add)funct(6 bit):100000(mã chức năng cho lệnh add)
Ba Dạng Chỉ Thị MIPS (R, I, J Format)
MIPS sử dụng ba định dạng lệnh để mã hóa tất cả các lệnh 32-bit của nó:
- R-format (Register format): Dùng cho các phép toán giữa các thanh ghi (ví dụ:
add,sub,sll).opcode (6) | rs (5) | rt (5) | rd (5) | shamt (5) | funct (6)
Bài giảng Kiến trúc máy tÃnh – Chương 2: Kiến trúc táºp lệnh trang 3
- I-format (Immediate format): Dùng cho các lệnh có toán hạng là hằng số (immediate) hoặc các lệnh
lw/sw,beq/bne.opcode (6) | rs (5) | rt (5) | immediate (16)- Trường
immediate16 bit có thể biểu diễn các hằng số từ -32,768 đến +32,767.
Bài giảng Kiến trúc máy tÃnh – Chương 2: Kiến trúc táºp lệnh trang 4
- J-format (Jump format): Dùng cho các lệnh nhảy không điều kiện
jvàjal.opcode (6) | address (26)- Trường
address26 bit được sử dụng để tính toán địa chỉ nhảy tuyệt đối.
Bài giảng Kiến trúc máy tÃnh – Chương 2: Kiến trúc táºp lệnh trang 5
Bài tập ví dụ: Lệnh addi $t0, $t1, 100 (cộng 100 vào $t1, lưu vào $t0) là loại định dạng nào và trường immediate cần bao nhiêu bit?
- Giải thích: Đây là lệnh
addi(add immediate), thuộc loại I-format. Trườngimmediatetrong I-format là 16 bit, đủ để lưu trữ giá trị 100.
Bài giảng Kiến trúc máy tÃnh – Chương 2: Kiến trúc táºp lệnh trang 6
Xử Lý Hằng Số Lớn Trong MIPS
Vì trường immediate chỉ có 16 bit, làm thế nào để xử lý các hằng số lớn hơn 32,767 hoặc nhỏ hơn -32,768? MIPS giải quyết vấn đề này bằng cách sử dụng hai lệnh kết hợp:
lui $rt, immediate(load upper immediate): Nạp giá trị 16 bitimmediatevào 16 bit cao của thanh ghi$rtvà đặt 16 bit thấp thành 0.ori $rt, $rs, immediate(or immediate): Thực hiện phép OR bitwise giữa nội dung thanh ghi$rsvà giá trịimmediate16 bit, lưu vào$rt.
Ví dụ: Để tải hằng số 0xAAAA_BBBB vào thanh ghi $t0:
lui $t0, 0xAAAA # $t0 = 0xAAAA0000
ori $t0, $t0, 0xBBBB # $t0 = 0xAAAA0000 | 0x0000BBBB = 0xAAAABBBB
Sự kết hợp này cho phép chúng ta xây dựng các hằng số 32 bit tùy ý vào thanh ghi, một kỹ thuật quan trọng trong các bài tập kiến trúc máy tính chương 2 về quản lý bộ nhớ hoặc khởi tạo biến.
Thủ Tục Gọi Hàm và Ngăn Xếp Trong MIPS
Việc quản lý các hàm con (subroutines hoặc procedures) là một phần thiết yếu của lập trình. MIPS cung cấp các cơ chế để hỗ trợ việc gọi và trả về từ các thủ tục, sử dụng quy ước thanh ghi và ngăn xếp.
Cơ Chế Gọi Hàm
Khi một hàm con được gọi, cần thực hiện các bước sau:
- Truyền tham số: Đưa các đối số cần thiết vào nơi mà hàm con có thể truy cập.
- Chuyển quyền điều khiển: Nhảy đến địa chỉ của hàm con.
- Thực thi hàm con: Hàm con thực hiện công việc của nó, có thể sử dụng các thanh ghi.
- Trả về kết quả: Lưu kết quả của hàm con vào nơi mà hàm gọi có thể truy cập.
- Trả quyền điều khiển: Quay về lệnh tiếp theo sau lệnh gọi hàm trong hàm gọi.
MIPS sử dụng các thanh ghi cụ thể cho việc này:
$a0-$a3: 4 thanh ghi đối số, dùng để truyền tham số vào hàm con.$v0-$v1: 2 thanh ghi giá trị, dùng để trả về kết quả từ hàm con.$ra: Thanh ghi địa chỉ trả về, được sử dụng để lưu địa chỉ lệnh ngay sau lệnhjal(jump-and-link) để hàm con biết nơi quay về.- Lệnh
jal ProcedureAddress: Nhảy đến địa chỉ thủ tục và lưuPC + 4(địa chỉ của lệnh tiếp theo saujal) vào$ra. - Lệnh
jr $ra: Nhảy đến địa chỉ được lưu trong$rađể quay về từ hàm con.
Bài tập ví dụ: Chuyển đoạn mã C sau sang MIPS assembly. Giả sử a, b được lưu trong $s0, $s1.
int main() {
int result;
result = sum(a, b);
// ...
}
int sum(int x, int y) {
return x + y;
}
-
Giải thích và lời giải:
.data .text .globl main main: # Chuẩn bị tham số cho hàm sum add $a0, $s0, $zero # x = a ($a0 = $s0) add $a1, $s1, $zero # y = b ($a1 = $s1) jal sum # Gọi hàm sum. $ra = địa chỉ của lệnh tiếp theo (ReturnPoint) ReturnPoint: add $s2, $v0, $zero # Lấy kết quả từ $v0 và lưu vào $s2 (result = $v0) # ... Tiếp tục chương trình main ... sum: add $v0, $a0, $a1 # Tính tổng x + y, lưu vào $v0 jr $ra # Quay về địa chỉ trong $ra (ReturnPoint)
Bài giảng Kiến trúc máy tÃnh – Chương 2: Kiến trúc táºp lệnh trang 7
Ngăn Xếp (Stack) và Quản Lý Thanh Ghi
Khi một hàm con cần nhiều thanh ghi hơn số lượng thanh ghi đối số/kết quả có sẵn, hoặc khi nó gọi một hàm con khác (nested call), các thanh ghi cần được lưu trữ tạm thời để tránh bị ghi đè. Ngăn xếp (stack) là một vùng bộ nhớ được sử dụng cho mục đích này.
- Con trỏ ngăn xếp (
$sp): Thanh ghi$sp(R29) luôn trỏ đến đỉnh (cuối cùng) của ngăn xếp. Trong MIPS, ngăn xếp “lớn lên” về phía địa chỉ thấp hơn trong bộ nhớ. - Lưu trữ thanh ghi:
- Caller-saved registers ($t0-$t9, $a0-$a3, $v0-$v1): Hàm gọi (caller) chịu trách nhiệm lưu các thanh ghi này vào ngăn xếp nếu nó muốn bảo toàn giá trị của chúng trước khi gọi hàm con.
- Callee-saved registers ($s0-$s7, $ra, $fp, $sp): Hàm con (callee) chịu trách nhiệm lưu các thanh ghi này vào ngăn xếp nếu nó định sử dụng chúng, và khôi phục chúng trước khi trả về.
- Stack Frame: Mỗi lần một hàm con được gọi, một “stack frame” mới được tạo trên ngăn xếp để lưu trữ các biến cục bộ, các tham số thừa, và các thanh ghi được lưu.
$fp(frame pointer) có thể được sử dụng để trỏ đến một điểm cố định trong stack frame, giúp truy cập các biến cục bộ dễ dàng.
Bài tập ví dụ: Một hàm factorial(n) đệ quy cần lưu trữ thanh ghi $s0 (chứa n) và địa chỉ trả về $ra trên ngăn xếp. Viết đoạn mã MIPS cho việc lưu và khôi phục các thanh ghi này.
-
Giải thích và lời giải:
factorial: addi $sp, $sp, -8 # Cấp phát 8 byte trên ngăn xếp (2 word) sw $ra, 4($sp) # Lưu $ra vào stack (tại địa chỉ $sp + 4) sw $s0, 0($sp) # Lưu $s0 vào stack (tại địa chỉ $sp + 0) # ... mã xử lý của hàm factorial ... lw $s0, 0($sp) # Khôi phục $s0 từ stack lw $ra, 4($sp) # Khôi phục $ra từ stack addi $sp, $sp, 8 # Giải phóng 8 byte trên ngăn xếp jr $ra # Quay vềĐây là một ví dụ điển hình về việc sử dụng ngăn xếp để quản lý bối cảnh hàm con trong các bài tập kiến trúc máy tính chương 2 liên quan đến đệ quy hoặc hàm lồng nhau.
Bài giảng Kiến trúc máy tÃnh – Chương 2: Kiến trúc táºp lệnh trang 8
Các Kiến Trúc Tập Lệnh Khác và So Sánh CISC vs. RISC
Ngoài MIPS, có nhiều kiến trúc tập lệnh khác nhau, mỗi loại có những đặc điểm và triết lý thiết kế riêng.
Các Kiến Trúc Tập Lệnh Phổ Biến Khác
- x86 (Intel/AMD): Kiến trúc CISC (Complex Instruction Set Computer) phổ biến nhất trong máy tính cá nhân và máy chủ. Nổi tiếng với số lượng lệnh lớn và phức tạp, khả năng xử lý biến độ dài lệnh và nhiều chế độ đánh địa chỉ.
- ARM (ARM Holdings): Kiến trúc RISC (Reduced Instruction Set Computer) thống trị thị trường thiết bị di động, nhúng và ngày càng phổ biến trong trung tâm dữ liệu. Đặc trưng bởi hiệu suất trên mỗi watt cao và tập lệnh đơn giản, hiệu quả.
- JVM (Java Virtual Machine): Không phải là kiến trúc phần cứng, mà là một máy ảo cung cấp môi trường thực thi cho các chương trình Java (bytecode), cho phép tính di động trên nhiều nền tảng phần cứng.
- PPC (PowerPC – IBM, Motorola): Kiến trúc RISC được sử dụng trong các máy trạm, máy chủ và một số hệ thống nhúng.
- SPARC (Oracle, Fujitsu): Kiến trúc RISC mã nguồn mở, thường dùng trong các máy chủ và hệ thống doanh nghiệp.
- PTX (Parallel Thread eXecution – Nvidia): Kiến trúc tập lệnh ảo được sử dụng bởi các GPU Nvidia, được thiết kế để lập trình song song.
Phân Loại Tập Lệnh Cơ Bản Theo Số Lượng Địa Chỉ
Các kiến trúc có thể được phân loại dựa trên số lượng địa chỉ bộ nhớ hoặc thanh ghi mà một lệnh có thể tham chiếu:
- Accumulator (1 địa chỉ):
ADD A(acc = acc + Mem[A]). - Register (load/store – 3 địa chỉ):
ADD R1, R2, R3(R1 = R2 + R3). Các lệnh Load/Store riêng biệt để truy cập bộ nhớ. MIPS thuộc loại này. - Register-Memory (2 địa chỉ):
ADD R1, B(R1 = R1 + Mem[B]). Cho phép một toán hạng nằm trong bộ nhớ. - Stack (0 địa chỉ):
ADD(tos = tos + next_tos). Hoạt động trên các giá trị trên đỉnh ngăn xếp.
CISC vs. RISC: Hai Triết Lý Thiết Kế
- CISC (Complex Instruction Set Computer):
- Đặc điểm: Tập lệnh lớn và phức tạp, mỗi lệnh có thể thực hiện nhiều thao tác cấp thấp (ví dụ: truy cập bộ nhớ, thực hiện phép tính, cập nhật cờ trạng thái). Độ dài lệnh có thể thay đổi.
- Ưu điểm: Chương trình nhỏ gọn, ít lệnh hơn để hoàn thành một tác vụ.
- Nhược điểm: Thiết kế CPU phức tạp, khó tối ưu hóa pipeline, chu kỳ thực thi mỗi lệnh có thể lâu hơn.
- Ví dụ: x86.
Bài giảng Kiến trúc máy tÃnh – Chương 2: Kiến trúc táºp lệnh trang 9
- RISC (Reduced Instruction Set Computer):
- Đặc điểm: Tập lệnh nhỏ và đơn giản, mỗi lệnh thực hiện một thao tác cơ bản duy nhất. Độ dài lệnh cố định. Tất cả các phép toán thực hiện trên thanh ghi (load-store architecture).
- Ưu điểm: Thiết kế CPU đơn giản, dễ tối ưu hóa pipeline, chu kỳ thực thi mỗi lệnh thường nhanh (1 chu kỳ).
- Nhược điểm: Yêu cầu nhiều lệnh hơn để hoàn thành một tác vụ, chương trình lớn hơn.
- Ví dụ: MIPS, ARM, SPARC.
Bài giảng Kiến trúc máy tÃnh – Chương 2: Kiến trúc táºp lệnh trang 10
Trong những năm gần đây, hầu hết các kiến trúc mới đều theo triết lý RISC. Tuy nhiên, các kiến trúc CISC như x86 đã áp dụng nhiều “thủ thuật RISC” bên trong (gọi là microarchitecture) để đạt được hiệu suất cao, biên dịch các lệnh CISC phức tạp thành các micro-ops đơn giản hơn để thực thi trên pipeline RISC nội bộ. Điều này cho thấy sự hội tụ giữa hai triết lý thiết kế.
Việc hiểu rõ sự khác biệt và ưu nhược điểm của từng loại kiến trúc là rất quan trọng khi đánh giá hiệu suất của một hệ thống máy tính trong các bài tập kiến trúc máy tính chương 2 thực tế.
Kết Luận
Chương 2 về kiến trúc tập lệnh là một phần cốt yếu trong hành trình khám phá thế giới máy tính. Từ cấu trúc bộ nhớ, cách CPU thực thi lệnh, các kiểu toán hạng, cho đến việc quản lý hàm con và ngăn xếp, mỗi khái niệm đều đóng vai trò quan trọng trong việc xây dựng một hệ thống máy tính hiệu quả. Bằng cách thực hành các bài tập kiến trúc máy tính chương 2 và vận dụng kiến thức về MIPS, bạn không chỉ hiểu sâu hơn về lý thuyết mà còn có thể áp dụng vào việc phân tích và tối ưu hóa hiệu suất phần mềm lẫn phần cứng. Tiếp tục tìm hiểu và trải nghiệm, bạn sẽ thấy lĩnh vực này vô cùng thú vị và đầy tiềm năng. Để cập nhật thêm kiến thức chuyên sâu và các sản phẩm công nghệ, đừng quên truy cập maytinhgiaphat.vn!

