





Preview text:
lOMoAR cPSD| 59994889 5/13/23, 9:24 AM Hợp ngữ MIPS - VietCodes 5/13/23, 9:24 AM Hợp ngữ MIPS - VietCodes 4 Comments 1 Login Hợp ngữ MIPS Comments Join the discussion… Hợp ngữ MIPS
ALSO ON VIE T CODES
let menu = ["Home", "Algorithms", "CodeHub", "VNOI Statistics"];L OG IN WI TH Cont ents
OR SIGN UP WITH DISQUS ? CISC và RISC 5 y ears ago • Thanh ghi 1 comment
Đ o ạ n con có t ổ ng 6 y ears a Name Các cấu trúc ệ l nh của MIPS R-format
l ớ n nh ấ t Hành I-format 4 Share J-format Các ệ l nh tính toán Best Newest Oldest Lệnh cộng và trừ Các l nh ệ tính toán logic Tính toán với các hằn g s ố 32 bit Lệnh dịch Lê Bảo Lộc − ⚑ L Các lệ nh thao tác b ộ nhớ a year ago Mô hình bộ nhớ của MIPS
Tại sao trong cấu trúc câu lệnh Rformat, trường opcode và funct không nằm liền nhau? Lệnh load/store Các l ệnh điều khiển 1 0 Reply • Share › Lệnh nhảy Lệnh rẽ nhánh
Thủ t ục trong hợp ngữ Đặng Huỳnh Đức − ⚑ Vị trí quay về 3 years ago $sp - B ộ nhớ stack Cảm ơn a ạ
T ruyền tham số - g iá trị trả về Kham khảo thêm 0 0 Reply • Share ›
Hợp ngữ (Assembly language) là ngôn ngữ có khả năng chuyển đổi 1-1 sang ngôn ngữ máy.
cực kì chất lượng.
Bài viết này sẽ trình bày hợp ngữ dành cho các dòng máy có kiến trúc MIPS.
Chúc ad thành công hơn nữa và
có thêm những bài viết chất
MIPS có tư tưởng register-to-register - load/store, nghĩa là các lệnh đều thao tác trên thanh
Để lập trình và chạy hợp ngữ MIPS, có thể dùng Mars: lượng nữa ạ ^^
ghi. Khi cần sử dụng bộ nhớ, ta sẽ có các lệnh riêng để nạp dữ liệu từ bộ nhớ vào thanh ghi.
courses.missouristate.edu/KenVollmar/mars/ 0 0 Reply •
Mỗi thanh ghi lưu trữ một giá trị 32-bit. Không như khái niệm biến ngôn ngữ lập trình Share › Trần vinh − ⚑ 3 years ago edited
Thank ad nhiều nhiều!! Bài viết
cấp cao, thanh ghi trong hợp ngữ không có kiểu dữ liệu, cách ta sử dụng thanh ghi sẽ Tuấn Đạt − ⚑
CISC và RISC4 years ago
quyết định kiểu dữ liệu là gì. Thanh ghi R-format có 6 tham số: Tên
MIPS có tổng cộng 32 thanh ghi (register) để lưu giá trị, được đánh số từ 0 đến 31. Để truy cập và thao tác trên một thanh ghi, ta dùng cú pháp op rs rt rd shamt funct
$ + số thứ tự thanh tham số ghi. Ví dụ: Độ dài 6 5 5 5 5 6 $0, $1, $10,… (bit)
Ngoài ra, MIPS có quy ước mục đích sử dụng của mỗi thanh ghi, khi lập trình nên tuân thủ các quy ước này. Vì thế, người ta thường truy cập thanh ghi thông qua tên của chúng: Giải thích: 1 2
file:///C:/Users/PC/OneDrive - VNU-HCMUS/Documents/Hợp ngữ MIPS - VietCodes.html /9 file:///C:/Users/PC/OneDrive - VNU-HCMUS/Documents/Hợp ngữ MIPS - VietCodes.html /9 lOMoAR cPSD| 59994889 Thanh ghi Tên Ý nghĩa 5/13/23, 9:24 AM Hợp ngữ MIPS - VietCodes 5/13/23, 9:24 AM Hợp ngữ MIPS - VietCodes
op: opcode, trường này sẽ cho máy biết lệnh này là lệnh nào. Trong trường hợp R-
Khác biệt giữa addu và add: add sẽ báo lỗi khi có tràn số, còn addu thì không.
Tương tự với format thì các lệnh đều dùng chung opcode là 0. các lệnh có u và không có u khác. rs, rt: source register và destination register, 2 thanh ghi $zero 0
Thanh ghi này luôn chứa giá trị 0
cần thực hiện tính toán.
rd: register destination, thanh ghi lưu kết quả của lệnh.
Các lệnh tính toán logic $at 1
Assembler Temporary - Được dành riêng cho các mục đích
shamt: shift amount, số bit cần dịch trong lệnh dịch trái và dịch phải.
khác, khi viết hạn chế dùng thanh ghi này Có 3
lệnh: and, or, nor. NOR là thao tác “NOT OR”: A nor B = not (A or B). Cú pháp của 3 funct: Vì các lệnh R-format đều có chung opcode bằng 0 nên ta thêm trường
này để lệnh này tương tự như lệnh add ở trên. cho máy biết cần thực hiện lệnh nào. Tương tự, ta cũng có lệnh andi và ori để tính AND/OR của một thanh ghi với một hằng 2, 3
Lưu giá trị trả về của hàm $v0, I-format $v1 số.
Lệnh I-format dùng cho thao tác giữa thanh ghi và một hằng số được lưu sẵn trong lệnh. 4 - 7
Lưu tham số truyền vào của hàm $a0 - $a3 8 - 15 Lưu biến tạm $t0 - $t7 16 - 23 Lưu biến $s0 - $s7 $t8, 24, 25 Như các $t ở trên $t9 26, 27
Được dùng cho nhân HĐH sử dụng $k0, $k1 $gp 28 Pointer to global area $sp 29 Stack pointer $fp 30 Frame pointer $ra 31
Return address, sử dụng cho việc gọi hàm
Hợp ngữ và kiến trúc máy tính được chi làm 2 loại: CICS và RISC. Đại diện tiêu biểu cho CISC
Các cấu trúc lệnh của MIPS
Phần lệnh rẽ nhánh code ví dụ
là x86 - được sử dụng trên các máy tính cá nhân và server. Đại diện cho RISC là ARM và bị sai nha admin ơi
MIPS. ARM được sử dụng trong các thiết bị di động và MIPS được sử dụng trong một số addi $s0, $0, 1000 # n = 1000
Phần này trình bày cấu trúc của các lệnh hợp ngữ khi được dịch sang ngôn ngữ máy. Mỗi lệnh
siêu máy tính, và các thiết bị như router, Nintendo 64, Sony Playstation 2.
addi $s1, $0, 0 # s = 0 addi $s2,
trong MIPS đều có độ dài là 32 bit.
$0, 1 # i = 1 FOR: slt $t0, $s2,
$s0 # $t0 = i < n? bne beq $t0,
Khác biệt giữa CISC và RISC:
Có thể xem mỗi lệnh như một hàm trong ngôn ngữ lập trình. Vì vậy, ta cần có tên lệnh, các
$0, END # if !(i < n) goto END
CISC là Complex insrtuction set computer và RICS là Reduced instruction set computer. Hợp
tham số truyền vào và kiểu của các tham số truyền vào - trong trường hợp này là kích thước
ngữ của CISC rất phức tạp và ngược lại RISC thì đơn giản hơn, vì vậy các máy CISC tiêu tốn
của mỗi tham số truyền vào (vì không có khái niệm kiểu dữ liệu trong hợp ngữ).
điện năng nhiều hơn các máy RISC.
MIPS chú trọng tính đơn giản của tập lệnh, vì vậy chỉ có 3 kiểu lệnh chính: R-format, Iformat, J-
Các bạn có thể đọc thêm về so sánh CISC và RISC ở đây: format.
cs.stanford.edu/peo ple/eroberts/courses/soco/pro j ects/risc/risccisc/ R-format
file:///C:/Users/PC/OneDrive - VNU-HCMUS/Documents/Hợp ngữ MIPS - VietCodes.html /9 file:///C:/Users/PC/OneDrive - VNU-HCMUS/Documents/Hợp ngữ MIPS - VietCodes.html /9 lOMoAR cPSD| 59994889 5/13/23, 9:24 AM Hợp ngữ MIPS - VietCodes 5/13/23, 9:24 AM Hợp ngữ MIPS - VietCodes Tên tham Các phép op rs rt immediate số
toán logic khác có thể được tính từ 3 phép trên: Cấu trúc như sau: Độ dài
not A = A nor 0 A xor B = (A or B) and (not A or not B) = (A and not B) 6 5 5 16 or (not A and B (bit)
Giải thích: T ính t o án với các hằng số 32 bit
Dễ thấy các lệnh thao tác với hằng số ở trên đều có giới hạn 16 bit cho hằng số. Để giải
op: opcode, cho máy biết đây là lệnh gì. Vì I-format không có trường funct nên các quyết vấn đề này, MIPS cung cấp lệnh lui (load upper immediate) với chức năng ghi một
lệnh I-format không dùng chung opcode như các lệnh R-format. hằng số 16-bit vào 2 byte cao của thanh ghi, 2 byte thấp sẽ được gán bằng 0. rs, rt: source register và target register. immediate: Một giá trị hằng số mà lệnh sử dụng.
Ví dụ, ta cần cộng $s0 cho giá trị 0x12345678: J-format lui $t0, 0x1234 ori $t0, $t0, 0x5678 add
J-format dành cho các lệnh nhảy (goto trong C), có cấu trúc: $s0, $s0, $t0 Tên tham target op số address Lệnh dịch Độ dài (bit) 6 26
2 lệnh sll và srl dùng để dịch trái và dịch phải.
Đây là dịch logic, các giá trị trống sau khi dịch luôn là 0. Giải thích:
Cú pháp tương tự như addi ở trên, tuy nhiên số bit cần dịch luôn là một số không âm từ 0
op: opcode, cho máy biết đây là lệnh gì.
đến 31. target address: Địa chỉ rút gọn của lệnh cần nhảy đến, địa chỉ gốc có 32 bit, ta rút
gọn 6 bit như sau: Các lệnh thao tác bộ nhớ
Xóa 2 bit thấp nhất của địa chỉ. Vì địa chỉ của các lệnh trong MIPS luôn chia hết
cho 4 nên 2 bit thấp nhất luôn bằng 0.
4 bit cao nhất xem như bằng với 4 bit cao nhất của lệnh hiện tại.
Mô hình bộ nhớ của MIPS
Các lệnh tính toán
Khi cần tính toán với các giá trị được lưu trên RAM, ta phải nạp giá trị lên thanh ghi trước
khi tính, sau đó lưu lại kết quả vào RAM (nếu cần). Lệnh cộng và trừ Đơn vị nhớ nhỏ
nhất mà MIPS có thể xử lý là byte (8 bit). MIPS cung cấp các lệng
load/store với các kích thước 1, 2 và 4 byte. Tuy nhiên có quy tắc Alignment Restriction
4 lệnh add, sub, addu, subu dùng để cộng/trừ giá trị của 2 thanh ghi, và lưu kết quả vào
sau: “Địa chỉ vùng nhớ cần truy cập phải chia hết cho kích thước cần truy cập”. Ví dụ, đọc thanh ghi đích. Cú pháp:
4 byte bắt đầu từ ô nhớ có địa chỉ 10 là không hợp lệ. < tên lệnh> , ,
Ngoài ra, MIPS lưu trữ dữ liệu theo dạng Big Endian, tức là byte cao sẽ được lưu ở địa chỉ
thấp. Ví dụ, số 12345678h (thập lục phân) khi được lưu trong bộ nhớ thì byte đầu tiên sẽ là 12h, byte tiếp theo là 34,… 2 lệnh addi, addiu dùng để cộng một thanh ghi với 1 hằng số, rồi lưu vào thanh ghi đích.
Cú pháp: Lệnh load/store , , Cú pháp: tên lệnh r1, offset(r2) Ví dụ:
add $s0, $s1, $s2 # $s0 = $s1 + $s2 Trong đó:
sub $s0, $s1, $s2 # $s0 = $s1 - $s2
addi $s0, $s0, 123 # $s0 = $s0 + 123
addi $s0, $s2, -123 # $s0 = $s2 - 123
r1: thanh ghi cần nạp dữ liệu vào / lấy dữ liệu ra.
r2: thanh ghi lưu địa chỉ gốc.
offset: hằng số nguyên (16 bit), giá trị này sẽ được cộng với giá trị của r2 để được địa chỉ cần nạp vào / lấy ra. 3 4 Tên các lệnh:
Có 2 lệnh rẽ nhánh là beq (branch if equal) và bne (branch if not equal). Cú pháp:
< Tên lệnh> , , <địa chỉ hoặc nhãn >
lw (load word), lh (load halfword), lb (load byte): Đọc 4/2/1 byte. Đối với lh và lb, vì thanh ghi có độ dài 4 byte, nhiều hơn lượng dữ liệu đọc được nên các bit
trống sẽ được gán bằng bit dấu của số đọc được. lhu (load halfword unsigned), lbu (load byte unsigned): tương tự như trên, tuy nhiên
Lệnh beq sẽ so sánh giá trị trong 2 thanh ghi, nếu bằng nhau thì nhảy đến nhãn chỉ định.
các bit trống được gán bằng 0.
Lệnh bne thì ngược lại, nhảy khi 2 giá trị khác nhau. Khi không nhảy, chương trình sẽ thực hiện lệnh tiếp theo. sw (store word), sh (store halfword), sb (store byte): lưu 4/2/1 byte dữ liệu trong thanh ghi vào bộ nhớ.
Địa chỉ truyền vào là địa chỉ tương đối và có dấu, PC sẽ được tính lại như sau: PC = PC + 4
file:///C:/Users/PC/OneDrive - VNU-HCMUS/Documents/Hợp ngữ MIPS - VietCodes.html /9 file:///C:/Users/PC/OneDrive - VNU-HCMUS/Documents/Hợp ngữ MIPS - VietCodes.html /9 lOMoAR cPSD| 59994889 5/13/23, 9:24 AM Hợp ngữ MIPS - VietCodes 5/13/23, 9:24 AM Hợp ngữ MIPS - VietCodes
Ví dụ, ta có một mảng int *x được lưu trong $s0: +
imm, với imm là địa chỉ truyền vào. lw $s1, 0($s0) # $s1 = *x slt rt, rs, rd lw $s1, 4($s0) # $s1 = x[1] sw $s1, 8($s0) # x[2] = $s1
Để so sánh lớn hơn/bé hơn, MIPS đưa thêm lệnh slt (set on less than). Cú pháp:
Với rt, rs, rd là các thanh ghi. Lệnh này sẽ gán rt bằng 1 khi rs < rd, bằng 0 trong trường
Một số lưu ý: hợp ngược lại.
Các lệnh trên đều phải tuân theo quy tắc Alignment Restriction ở trên.
So sánh trong lệnh trên là so sánh có dấu (bù 2). Để so sánh không dấu, MIPS hỗ trợ lệnh
Đối với sh và sb sẽ lưu các byte thấp trong thanh ghi vào bộ nhớ. stlu, cách dùng tương tự như trên. Dữ liệu trong thanh ghi và bộ nhớ đều tuân theo quy tắc Big Endian.
Ngoài ra, cũng có lệnh để so sánh với một hằng số, là slti và sltiu. Cú pháp tương tự
Các lệnh điều khiển như các lệnh tính toán với hằng số ở trên.
Khi chương trình được thực thi, máy sẽ nạp chương trình lên bộ nhớ, đồng thời có một
Kết hợp các lệnh đã tìm hiểu, ta có thể dịch đoạn chương trình C sau sang hợp ngữ MIPS: thanh ghi dành riêng để lưu địa chỉ của lệnh đang được thực
thi, đây gọi là thanh ghi PC (program counter). Mỗi lần thực hiện xong một lệnh, mặc định PC sẽ được tự động tăng lên để chuyển sang lệnh tiếp theo. int n = 1000; int s = 0; for
(int i=1; iCông việc của các lệnh điều khiển như nhảy, rẽ nhánh là gán lại địa chỉ của thanh ghi PC, để chương trình chuyển sang một đoạn khác. addi $s0, $0, 1000 # n = 1000 addi $s1, $0, 0 # s = 0 Lệnh nhảy addi $s2, $0, 1 # i = 1 FOR:
Lệnh nhảy tương tự như
slt $t0, $s2, $s0 # $t0 = i < n?
goto trong C, có 2 lệnh nhảy là j và jr, ngoài ra còn có jal nhưng ta sẽ tìm hiểu lệnh này sau.
j <đỉa chỉ cần nhảy tới hoặc nhãn>
bne $t0, $0, END # if !(i < n) goto END Cú pháp lệnh
add $s1, $s1, $s2 # s = s + i addi $s2, j: $s2, 1 # i = i + 1 j FOR END:
Thông thường, khi viết hợp ngữ ta chỉ cần dùng nhãn, trình dịch hợp ngữ sẽ tự chuyển đổi sang địa chỉ, ví dụ: loop: addi $s0, $s0, 1
Thủ tục trong hợp ngữ j loop
Trong hợp ngữ, sử dụng thủ thục thực chất là nhảy đến đoạn code của thủ tục đó. Tuy nhiên có một số vấn đề phát sinh:
Làm thế nào để biết lệnh nào được thực thi sau khi kết thúc thủ tục?
Đoạn chương trình tên là một vòng lặp vô hạn.Truyền các tham số vào thủ tục như thế nào?
Thanh ghi nào để lưu giá trị trả về?
jr cũng tương tự như j, tuy nhiên ta đọc địa chỉ lệnh cần nhảy đến trong một thanh ghi.
Quản lý việc sử dụng thanh ghi giữa các thủ tục như thế nào? Vì thủ tục được gọi có
Ví dụ: thể thay đổi các thanh ghi được dùng trong thủ tục gọi. jr $ra
MIPS giải quyết các vấn đề này bằng một số quy ước, khi lập trình ta nên tuân thủ theo các quy ước này để code có tính tái sử dụng cao và hạn chế sai lầm từ người lập trình.
Cách hoạt động của lệnh nhảy: Vị trí quay về
Lệnh jr sẽ gán PC bằng với thanh ghi được chỉ định
Ví dụ đoạn code C sau được dịch sang hợp ngữ ở dưới:
Ở lệnh j vì, tham số truyền vào chỉ có 26 bit, mà PC lại có đến 32 bit nên ta tính lại
PC như sau: PC = (PC & 0xf0000000) | (imm << 2), với imm là tham số truyền vào. Lệnh rẽ nhánh
Lệnh rẽ nhánh sẽ thực hiện 2 thao tác: so sánh và nhảy khi thỏa điều kiện. 5 6
Đối với các thanh ghi $s0 - $s7 và $sp, E phải khôi phục lại đúng giá trị ban đầu sau khi thực thi xong.
Đối với các thanh ghi khác: $t, $v, $a, $ra, E có quyền thay đổi giá trị các thanh ghi này, vì vậy R có trách nhiệm sao lưu và khôi phục lại các thanh ghi này trước và sau khi gọi E (nếu cần sử dụng).
Để quản lý sao lưu / khôi phục các thanh ghi như yêu cầu ở trên, ta dùng bộ nhớ stack.
Trong MIPS, thanh ghi $sp có giá trị trỏ tới đỉnh stack. Ở đầu hàm, ta lưu các biến cần sao lưu vào stack, sau đó ở cuối hàm, ta khôi phục lại các biến đó. Viết lại đoạn chương trình trên như sau:
Sau khi thực hiện xong hàm die thì chương trình sẽ nhảy về L1 để tiếp tục thực thi hàm man. Nhưng chuyện xảy ra nếu có một hàm khác cũng gọi die:
Ta thấy nếu hàm woman gọi die thì địa chỉ nhảy về sẽ khác với khi man gọi die. baz:
addi $sp, $sp, -4 # Mở rộng stack để sử dụng
sw $s0, 0($sp) # Lưu $s0 vào stack ori $s0, $0,
file:///C:/Users/PC/OneDrive - VNU-HCMUS/Documents/Hợp ngữ MIPS - VietCodes.html /9 file:///C:/Users/PC/OneDrive - VNU-HCMUS/Documents/Hợp ngữ MIPS - VietCodes.html /9 lOMoAR cPSD| 59994889 5/13/23, 9:24 AM Hợp ngữ MIPS - VietCodes 5/13/23, 9:24 AM Hợp ngữ MIPS - VietCodes
Để giải quyết vấn đề này, MIPS cung cấp lệnh jal (jump and link). jal sẽ gán giá trị thanh ghi $ra bằng với địa chỉ của lệnh tiếp theo trước khi thực hiện nhảy. Như 0 # Thay đổi $s0 lw $s0, 0($sp) # Khôi phục
vậy, sau khi thực hiện xong, hàm được gọi chỉ cần jr $ra để nhảy về đúng lệnh cần nhảy:
lại $s0 như ban đầu addi $sp, $sp, 4 # Khôi phục lại $sp jr $ra void woman() { die() ; int x = $sp - Bộ nhớ stack bar: 0x0000ffff; }
Giả sử có 3 hàm gọi nhau, sử dụng
addi $sp, $sp, -12 # Vì có 3 thanh ghi cần lưu nên ta mở rộng stack $ra như trên:
sw $ra, 0($sp) # Lưu $ra sw $s0, 4($sp) # Lưu $s0 sw void die() { die:
$s1, 8($sp) # Lưu $s1 ori $s0, $0, 1 # Thay đổi $s0 jal int x = 0xffffffff; nor $s0, $0, $0
baz # Gọi baz, $ra bị thay đổi slt $s1, $0, $s0 # Thay } j L1
đổi $s1 lw $s1, 8($sp) # Khôi phục $s1 lw $s0, 4($sp) #
Khôi phục $s0 lw $ra, 0($sp) # Khôi phục $ra addi $sp, $sp, void man() { man: 12 # Khôi phục $sp jr $ra die(); int j die x = 0; L1: foo: } or $s0, $0, $0 addi $sp, $sp, -8 sw $ra, 0($sp) sw die: $s0, 4($sp) ori nor $s0, $0, $0 $s0, $0, 2 jal jr $ra bar lw $s0, 4($sp) lw $ra, 0($sp) addi $sp, man: $sp, 8 jr $ra jal die or $s0, $0, $0 woman: void baz() { jal die lui $t0, int x = 0; } baz:
T ruyền tham số - giá trị trả về 0x0000 ori $s0, $t0, ori $s0, $0, 0 0xffff void bar() { jr $ra bar:
4 thanh ghi $a0 đến $a3 được quy ước dùng riêng cho các tham số
truyền vào. Và 2 thanh ghi int x = 1;
$v0, $v1 được dùng cho giá trị trả về. Ví dụ: baz(); int y = ori $s0, $0, 1 x > 0; } jal baz slt $s1, int sub(int a, int b) { $0, $s0 jr $ra return a - b; } int void foo() { foo: calc(int a, int b) { int x = 2; return sub(b, a) + b; bar(); ori $s0, $0, 2 jal bar jr $ra } Ta thấy ngay 2 vấn đề: }
Thanh ghi $ra sẽ bị thay đổi khi bar gọi baz, vì vậy sau đó bar sẽ không trả về đúng địa chỉ nữa.
Thanh ghi $s0 bị thay đổi trong hàm khác, vì thế code sẽ không chạy đúng như mong muốn nữa.
Để giải quyết vấn đề này, MIPS đưa ra một số thỏa hiệp giữa hàm gọi (caller - R) và hàm được gọi (callee - E): 7 8
file:///C:/Users/PC/OneDrive - VNU-HCMUS/Documents/Hợp ngữ MIPS - VietCodes.html /9 file:///C:/Users/PC/OneDrive - VNU-HCMUS/Documents/Hợp ngữ MIPS - VietCodes.html /9 lOMoAR cPSD| 59994889 sub: sub $v0, $a0, $a1 jr $ra 5/13/23, 9:24 AM Hợp ngữ MIPS - VietCodes calc: addi $sp, $sp, -8 sw $ra, 0($sp)
sw $a1, 4($sp) # Lưu lại $a1 vì ta cần dùng nó sau khi gọi hàm s or $t0, $0, $a0 #
or $a0, $0, $a1 # Hoán đổi giá trị $a0 và $a1, dùng biến tạm $t0 or $a1, $0, $t0 # Kham khảo thêm
https://en.wikibooks.or g /wiki/MIPS_Assembly jal sub
lw $a1, 4($sp) # Khôi phục lại $a1
add $v0, $v0, $a1 lw $ra, 0($sp) addi $sp, $sp, 8 jr $ra
© 2019 VietCodes • Products 9
file:///C:/Users/PC/OneDrive - VNU-HCMUS/Documents/Hợp ngữ MIPS - VietCodes.html 9/
Downloaded by Bao Han (hanbao3006@gmail.com)