You are on page 1of 11

ĐẠI HỌC BÁCH KHOA HÀ NỘI

TRƯỜNG CÔNG NGHỆ THÔNG TIN VÀ TRUYỀN THÔNG


********

BÁO CÁO
Bài tập thực hành tuần 7
Học phần: Thực hành kiến trúc máy tính

Giảng viên hướng dẫn: Lê Bá Vui


Sinh viên thực hiện: Nguyễn Đình Hiếu -
20215049
Mã lớp: 139363
1. Assignment 1:
- Thử chạy với đầu vào là -50.
- Trước khi chạy lệnh: jal abs

- Sau khi chạy lệnh: jal abs

- Kết quả: Chạy đúng

- Nhận xét: Khi chạy lệnh jal abs (địa chỉ lệnh 0x00400004) thì thanh ghi
$ra được gán địa chỉ của câu lệnh tiếp theo (0x00400008) và thanh ghi
$pc được gán bằng địa chỉ 0x00400018 (địa chỉ nhãn abs).
- Kết quả cuối cùng được nạp vào thanh ghi $s0:

2. Assignment 2:
- Kết quả chạy với ví dụ mẫu:

Thanh ghi $s0 = 7 lưu giá trị lớn nhất


- Thay đổi đầu vào: $a0 = -10, $a1 = 8, $a2 = 1
- Trước khi chạy lệnh jal max

- Sau khi chạy lệnh jal max


- Kết quả thu được $s0 = 8

- Nhận xét: Khi chạy lệnh jal thì thanh ghi $ra được gán bằng địa chỉ của
câu lệnh theo sau lệnh jal trong nhãn main, còn thanh ghi $pc được gán
bằng địa chỉ của nhãn max để thực hiện câu lệnh từ nhãn max. Sau khi
chạy lệnh jr $ra thì pc được gán bằng địa chỉ trong $ra (địa chỉ của câu
lệnh theo sau lệnh jal trong nhãn main).

3. Assignment 3:
- Trước khi chạy lệnh addi trong nhãn push:
$sp = 0x7fffeffc
- Sau khi chạy lệnh addi trong nhãn push:

$sp = 0x7fffeff4
$sp giảm đi 8 byte => Stack được cấp phát thêm 2 vùng nhớ.
Sau đó lần lượt ghi giá trị trong $s0, $s1 vào các ô nhớ ở địa chỉ $sp + 4, $sp +
0.
- Sau khi chạy lệnh add ở nhãn pop:
Thực hiện đổi chỗ hai số bằng cách load giá trị tại ô nhớ có địa chỉ $sp + 0 vào
$s0, load giá trị tại ô nhớ có địa chỉ $sp + 4 vào $s1.
Lệnh add $sp, $sp, 8 giúp giải phóng stack, trả lại đỉnh stack, khi đó $sp =
0x7fffeffc bằng giá trị $sp trước khi chạy lệnh addi trong nhãn push.

4. Assignment 4:

- Kết quả khi chạy chương trình: 6! = 720 (Đúng)


- Nhận xét sự thay đổi các thanh ghi $pc, $ra, $sp, $fp
- Trước khi chạy lệnh jal WARP:

- Sau khi chạy lệnh jal WARP:

 $ra lưu địa chỉ lệnh sau lệnh jal WARP, $pc lưu địa chỉ nhãn WARP
- Sau khi chạy các lệnh
sw $fp,-4($sp) # (1)
addi $fp,$sp,0 # (2)
addi $sp,$sp,-8 # (3)
sw $ra,0($sp) # (4)

 Lệnh (1) lưu giá trị frame-point cũ (0x00000000) vào ô nhớ phía trước
đỉnh stack hiện tại ($sp - 4). Lệnh (2) khởi tạo giá trị frame-point mới
chính là đỉnh stack hiện tại ($sp). Lệnh (3) cấp phát cho stack thêm 2
vùng nhớ để lưu giá trị $fp, $ra. Lệnh (4) lưu giá trị $ra vào vùng nhớ
mới cấp phát thêm.
- Tiếp theo chương trình chạy đến nhãn FACT. Sau khi thực hiện các lệnh:
sw $fp,-4($sp) # (1)
addi $fp,$sp,0 # (2)
addi $sp,$sp,-12 # (3)
sw $ra,4($sp) # (4)
sw $a0,0($sp) # (5)

Tương tự như trên lệnh (1) lưu giá trị fp hiện tại, lệnh (2) khởi tạo giá trị
frame-point mới chính là đỉnh stack. Lệnh (3) cấp phát 3 vùng nhớ để lưu $fp,
$ra, $a0, Lệnh (4) lưu $ra vào ô nhớ $sp + 4, lệnh (5) lưu $a0 vào ô nhớ $sp.
- Ở trong thủ tục đệ quy recursive, ta cứ giảm dần giá trị $a0 rồi gọi tới
nhãn FACT để lưu các giá trị $a0, $fp, $ra tương ứng. Khi $a0 = 1, ta lần
lượt lấy $ra, $a0 để thực hiện nhân bằng các lệnh sau:
lw $ra,4($sp) # (1)
lw $a0,0($sp) # (2)
addi $sp,$fp,0 # (3)
lw $fp,-4($sp) # (4)
jr $ra # (5)

Lệnh (1), (2), (3), (4) lần lượt: khôi phục giá trị $ra, $a0, $sp, $fp. Rồi
thực hiện jr tới $ra (chính là câu lệnh nop sau lệnh jal FACT trong nhãn
recursive) để thực hiện nhân lần lượt các giá trị $a0 lưu trong stack. Khi
lấy hết giá trị $a0. Lệnh jr $ra sẽ nhảy tới lệnh nop phía sau lệnh jal
FACT trong nhãn WARP để thực hiện nốt thủ tục WARP.

- Vẽ stack với trường hợp n = 3


0x7fffeff8 $fp = 0x00000000
0x7fffeff4 $ra = 0x00400004
0x7fffeff0 $fp = 0x7fffeffc
0x7fffefec $ra = 0x00400038
0x7fffefe8 $a0 = 0x00000003
0x7fffefe4 $fp = 0x7fffeff4
0x7fffefe0 $ra = 0x00400080
0x7fffefdc $a0 = 0x00000002
0x7fffefd8 $fp = 0x7fffefe8
0x7fffefd4 $ra = 0x00400080
0x7fffefd0 $a0 = 0x00000001
5. Assignment 5:
- Source Code:
.data
largest: .asciiz "Largest: "
smallest: .asciiz "\nSmallest: "
comma: .asciiz ", "
.text
main: li $s0, 6
li $s1, -12
li $s2, 589
li $s3, 12
li $s4, -78
li $s5, -22
li $s6, 243
li $s7, -67

jal saveNumbers
nop
li $v0, 4 # Print message Largest
la $a0, largest
syscall
add $a0, $t0, $zero # Print Max
li $v0, 1
syscall
li $v0, 4 # Print message Comma
la $a0, comma
syscall
add $a0, $t5, $zero
li $v0, 1 # Print the register number of Max
syscall
li $v0, 4 # Print message Smallest
la $a0, smallest
syscall
add $a0, $t1, $zero # Print Min
li $v0, 1
syscall
li $v0, 4 # Print message Comma
la $a0, comma
syscall
add $a0, $t6, $zero
li $v0, 1 # Print the register number of Min
syscall
endmain: li $v0, 10 # Exit
syscall
#----------------------------------------------------------------------
# Return $t0 = Max
# Return $t1 = Min
# Index of Max = $t5
# Index of Min = $t6
#return $v0 the largest value
#----------------------------------------------------------------------
swapMax:add $t0,$t3,$zero
add $t5,$t2,$zero
jr $ra
swapMin:add $t1,$t3,$zero
add $t6,$t2,$zero
jr $ra
saveNumbers:
add $t9,$sp,$zero # Save address of origin $sp
addi $sp,$sp, -32
sw $s1, 0($sp)
sw $s2, 4($sp)
sw $s3, 8($sp)
sw $s4, 12($sp)
sw $s5, 16($sp)
sw $s6, 20($sp)
sw $s7, 24($sp)
sw $ra, 28($sp) # Save $ra for main
add $t0,$s0,$zero # Max = $s0
add $t1,$s0,$zero # Min = $s0
li $t5, 0 # Index of Max to 0
li $t6, 0 # Index of Min to 0
li $t2, 0 #i=0
findMaxMin:
addi $sp,$sp,4
lw $t3,-4($sp)
sub $t4, $sp, $t9
beq $t4,$zero, done # If $sp = $fp branch to the 'done'
nop
addi $t2,$t2,1 # i++
sub $t4,$t0,$t3
bltzal $t4, swapMax # If $t3 > Max branch to the swapMax
nop
sub $t4,$t3,$t1
bltzal $t4, swapMin # If $t3 < Min branch to the swapMin
nop
j findMaxMin # Repeat
done: lw $ra, -4($sp)
jr $ra # Return to calling program
- Kết quả: Chạy đúng

You might also like