• Phần dưới kế tiếp hiển thị mã của chương trình ở dạng hợp ngữ, dạng mã máy số hex cột thứ 2 từ trái qua, và địa chỉ tương ứng của mỗi lệnh cột đầu tiên bên trái.. • Phần dưới kế tiếp h
Trang 11 Giới thiệu PCSPim
PCSpim là chương trình chạy và mô phỏng chương trình hợp ngữ dành cho MIPS Sau khi cài đặt PCSpim và chạy chương trình (Start -> All Programs -> PCSpim.exe), cửa sổ chương trình PCSpim hiện lên như hình 1
Hình 1: Cửa sổ chương trình PCSpim
Cửa sổ hiển thị chia làm 4 phần:
• Phần trên cùng hiển thị nội dung của 32 thanh ghi của CPU và FPU Nội dung sẽ
tự động cập nhật khi chương trình hợp ngữ chạy
• Phần dưới kế tiếp hiển thị mã của chương trình ở dạng hợp ngữ, dạng mã máy (số hex cột thứ 2 từ trái qua), và địa chỉ tương ứng của mỗi lệnh (cột đầu tiên bên trái)
• Phần dưới kế tiếp hiển thị dữ liệu khai báo trong chương trình hợp ngữ (ví dụ: mảng hay chuỗi) và dữ liệu trong vùng ngăn xếp khi chương trình hợp ngữ được thực thi
• Phần dưới cùng hiển thị các thông tin phụ của SPIM, thông tin về lỗi nếu có Chương trình hợp ngữ muốn chạy được phải được load trước Đế load chương trình hợp ngữ (ở dạng một file có đuôi mở rộng là *.asm hay *.s), thực hiện thao tác File menu -> Open -> chọn file chứa chương trình cần load Để tạo file *.asm, chúng ta có thể dùng các chương trình soạn thảo thô như Notepad, Notepad++, EditPlus…
Trang 2Hình 2 Load file chứa chương trình nguồn
Sau khi chương trình hợp ngữ đã được load, chúng ta
có thể thực hiện chạy chương trình và quan sát sự thay
đối giá trị các thanh ghi, các ô nhớ, vị trí và lệnh đang
được thực thi … Các tác vụ chạy chương trình ở trong
Simulator menu
Các bước để chạy và quan sát quá trình chạy của
chương trình hợp ngữ trên PCSpim:
• Chọn Simulator -> Breakpoints… (hoặc nhấn
Ctrl+B) Cửa sổ hiện ra điền vào textbox
Address giá trị 0x00400000, chọn Add
• Chọn Simulator -> Go (hoặc nhấn F5) Điền
giá trị 0x00400000 vào texbox Starting
Address, chọn OK Giá trị của thanh ghi PC
Trang 3Cách khác để chạy chương trình nguồn: Simularor -> SetValue…, cửa sổ hiện ra, điền
vào textbox Register Name giá trị PC, điền vào textbox Value giá trị 0x00400000 Sau đó
nhấn F10 để chạy từng bước hay F5 để chạy cho đến khi gặp breakpoints
2 Các kiến thức cơ sở
2.1 Đổi qua lại giữ số thập lục phân (hexadecimal) và số nhị phân (binary)
Số thập lục phân được tạo thành từ 16 ký số: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f Số
nhị phân tạo thành từ 2 ký số: 0, 1 Một ký số thập lục phân tương ứng với số nhị phân gồm 4
ký số theo bảng sau:
Ví dụ:
Số thập lục phân 0xeca86420 chuyển sang số nhị phân:
Số nhị phân 1 0011 0101 0111 1001 1011 1101 1111 chuyển sang số thập lục phân:
phần: vùng chứa mã (text segment),
vùng chứa dữ liệu (data segment)
Trang 4và vùng nhớ stack (stack segment) Bộ xử lý tương tác với bộ nhớ thông qua việc di chuyển
dữ liệu giữa các ô nhớ và các thanh ghi Có hai thao tác để thực hiện việc di chuyển dữ liệu
giữa bộ nhớ và thanh ghi: load và store Dữ liệu di chuyển được tổ chức thành nhóm một,
hai hay bốn byte liên tục nhau theo chiều tăng địa chỉ ô nhớ
• load: nhóm byte liên tục nhau theo chiều tăng địa chỉ ô nhớ bắt đầu từ địa chỉ
được chỉ định được copy vào thanh ghi
• store: nhóm dữ liệu 1, 2 byte thấp của thanh ghi hay cả 4 byte của thanh ghi được copy vào bộ nhớ từ địa chỉ được chỉ định
2.3 Tổ chức thanh ghi
MIPS có tấc cả 32 thanh ghi 32-bit có thê sử dụng trong ngôn ngữ assembly được liệt kê trong bảng sau:
Bộ xử lý MIPS có bộ tính toán số học/luận lý (ALU) bên trong thực hiện các phép toán
số học và luận lý trên số nguyên 32-bit Phép toán thực
hiện bởi ALU gồm hai toán hạng Một toán hạng là số
nguyên chứa trong thanh ghi, toán hạng còn lại có thể
chứa trên thanh ghi hay là một phần của lệnh thực hiện
phép toán (hằng số) Kết quả của phép toán luôn đặt vào
thanh ghi
Trang 516 bit không dấu
AND từng bit and rd, rs, rt rd Å bitwise AND of rs with rt
AND từng bit với
hằng số 16 bit
const Nhảy nếu bằng beq rs, rt, addr nhảy đến addr nếu rs == rt Cần
phải thêm delay theo sau (nop) Nhảy nếu lớn hơn
hay bằng 0
rs >= 0 Cần thêm delay Nhảy nếu nhỏ hơn
0
rs < 0 Cần thêm delay Nhảy nếu khác bne rs, rt, addr nhảy đến addr nếu rs != rt Cần
thêm delay Chia hai số bù 2 div rs, rt lo Å rs div rt; hi Å rs mod rt
hai số rs và rt ở dạng bù 2 Chia hai số không
dấu
hai số rs và rt ở dạng không dấu Nhảy không điều
kiện
PC Å địa chỉ của target Nhảy không điều
kiện và link
PC Å địa chỉ của target, thêm nop
Nhảy không điều
kiện theo giá trị
Trang 6offset, offset là số bù 2 Load byte và mở
rộng số 0 đầu
ô nhớ có địa chỉ base + offset, offset là số bù 2
Load half-word
và mở rộng dấu
mở rộng dấu từ ô nhớ có địa chỉ base + offset , offset là số bù 2 Load half-word
và mở rộng số 0
mở rộng 0 từ ô nhớ có địa chỉ base + offset, offset là số bù 2 Load hằng vào 16
bit cao
2 byte thấp của rd Å 0x0000 Load word lw rd, offset(base) rd Å word bộ nhớ có địa chỉ
base + offset, offset là số bù 2 Chuyển giá trị từ
hi vào thanh ghi
không dấu
hai số không dấu NOT từng bit nor rd, rs, $0 rd Å NOT từng bit của rs NOR từng bit nor rd, rs, rt rd Å NOR từng bit của rs và rt
OR từng bit or rd, rs, rt rd Å OR từng bit của rs và rt
OR từng bit với
hằng 16 bit
hằng sau khi mở rộng 0 Lưu byte thấp của
thanh ghi vào bộ
Trang 7bit; 0 <= shft <32 Trừ hai thanh ghi
dạng bù 2
bù 2 Trừ hai thanh ghi
dạng không dấu
không dấu Lưu thanh ghi vào
bộ nhớ
$rs; offset dạng bù 2 XOR từng bit xor rd, rs, rt rd Å XOR từng bit rs và rt
XOR từng bit với
hằng
sau khi mở rộng 0
Trang 84 Cú pháp của MIPS Assempler
Chú thích (comment) chuỗi các từ bắt đầu bằng #, tất cả các từ bắt đầu từ # cho đến cuối
dòng đều được bỏ qua
Tên định danh (identifier) là chuỗi các ký tự chữ, số, dấu gạch dưới (_) và dấu chấm (.)
không bắt đầu bằng số Tên không được trùng với các từ dành riêng là opcode của lệnh
Các ví dụ về tên định danh hợp lệ:
main, loop, end_if, case1.2
Các ví dụ về tên định danh không hợp lệ:
1value # số đứng đầu
b # trùng với opcode lệnh nhảy
add # trùng với opcode lệnh cộng
Nhãn bao gồm tên định danh theo sau là dấu hai chấm (:) được đặt ở đầu dòng
Ví dụ:
Số (number) mặc định là cơ số 10 Số thập lục phân (hexadecimal) thêm 0x vào phía
trước Hai số 256 và 0x100 diễn tả số có cùng giá trị
Chuỗi (string) được đặt giữa hai dấu nháy kép (“) Ví dụ: “Hello world!\n” Các ký tự
đặt biệt cho phép trong chuỗi:
Chỉ thị (directive) được hỗ trợ gồm có:
.text <addr> Tất cả các phần theo sau cho tới chỉ thị mới (.text, ktext, data, kdata) được
đặt trong vùng nhớ chương trình (code segment) Tham số addr nếu có quy
định địa chỉ bắt đầu của vùng nhớ chương trình dùng để lưu các phần trong phân đoạn mã chương trình này Phần theo sau thường là các lệnh
.ktext <addr> Tất cả các phần theo sau cho tới chỉ thị mới (.text, ktext, data, kdata) được
đặt vào vùng nhớ nhân (kernel) của hệ điều hành Tham số addr nếu có quy
định địa chỉ bắt đầu của vùng nhớ dùng để lưu Phần theo sau thường là các lệnh
.globl sym Khai báo nhãn sym là toàn cục và có thể được tham khảo từ file khác
.data <addr> Tất cả các phần theo sau cho tới chỉ thị mới (.text, ktext, data, kdata) được
đặt trong vùng nhớ dữ liệu nhân (kernel data segment) Tham số addr nếu
có quy định địa chỉ bắt đầu của vùng nhớ dùng để lưu
newline \n
tab \t
quote \”
.data item: .word 1
.text globl main # must be global main:
…
Trang 9.kdata <addr> Tất cả các phần theo sau cho tới chỉ thị mới (.text, ktext, data, kdata) được
đặt trong vùng nhớ dữ liệu (data segment) Tham số addr nếu có quy định
địa chỉ bắt đầu của vùng nhớ dùng để lưu
.ascii str Lưu chuỗi str vào bộ nhớ, không có ký tự kết thúc chuỗi (giá trị = 0) sau
cùng
.asciiz str Lưu chuỗi str vào bộ nhớ, thêm ký tự kết thúc chuỗi (giá trị = 0) sau cùng
.byte b1, ,bn Lưu n byte liên tiếp nhau b1, ,bn vào bộ nhớ
.half h1, ,hn Lưu n phần tử 16-bit liên tiếp nhau h1, ,hn vào bộ nhớ
.word w1, ,wn Lưu n phần tử 32-bit liên tiếp nhau w1, ,wn vào bộ nhớ
.float f1, ,fn Lưu n số thực dấu chấm động độ chính xác đơn liên tiếp nhau f1, ,fn vào bộ
.extern sym n Khai báo dữ liệu lưu ở sym có kích thước n byte và sym là nhãn toàn cục
Dữ liệu vùng nhớ này được truy xuất thông qua thanh ghi $gp
Trang 105 Các chương trình mẫu
5.1 Các lệnh luận lý:
Thiết lập các tham số trong menu Simulator -> Settings:
Bare Machine ON, Allow Pseudo Instructions OFF, Load Trap File OFF, Delayed Branches ON, Delayed Loads ON, Mapped IO OFF, Quiet OFF
5.2 Các lệnh số học:
Thiết lập các tham số trong menu Simulator -> Settings:
Bare Machine ON, Allow Pseudo Instructions OFF, Load Trap File OFF, Delayed Branches ON, Delayed Loads ON, Mapped IO OFF, Quiet OFF
Trang 115.3 Các lệnh thao tác bộ nhớ
Thiết lập các tham số trong menu Simulator -> Settings:
Bare Machine ON, Allow Pseudo Instructions OFF, Load Trap File OFF, Delayed Branches ON, Delayed Loads ON, Mapped IO OFF, Quiet OFF
## Follows the hardware rule of keeping a new mult
## two instructions away from a previous mflo
Trang 125.4 Các lệnh nhảy
Thiết lập các tham số trong menu Simulator -> Settings:
Bare Machine ON, Allow Pseudo Instructions OFF, Load Trap File OFF, Delayed Branches ON, Delayed Loads ON, Mapped IO OFF, Quiet OFF
## Find the Significant bits in a pattern
## The significant bits are the leftmost one bit and
## all its to its right
## Approach: Count the number of right shifts needed
## before the pattern becomes all zeros
lui $8,0x1000 # $8 is base register
sb $9,3($8) # least significant byte
srl $9,$9,8 # move next byte to low order
sb $9,2($8) # bits 8-15
srl $9,$9,8 # move next byte to low order
sb $9,1($8) # bits 16-23
srl $9,$9,8 # move next byte to low order
sb $9,0($8) # most significant byte
data
tape: # base register points here
space 1024 # tape buffer (1K bytes)
## End of file
Trang 135.5 Các ví dụ xử lý chuỗi, xử lý mảng
Các lệnh đã biết cho đến giờ:
Thiết lập các tham số trong menu Simulator -> Settings:
Bare Machine ON, Allow Pseudo Instructions OFF, Load Trap File OFF, Delayed Branches ON, Delayed Loads ON, Mapped IO OFF, Quiet OFF
loop: beq $8,$0,exit # done when pattern == 00
sll $0,$0,0 # delay or nop after a branch
# or jump instruction srl $8,$8,1 # shift right one bit
addu $7,$7,1 # increment shift count
## Write a program that converts the string to all lower case
## characters Do this by adding 0x20 to each character in the string
## Register Use:
##
## $8 - current character
## $10 - character pointer
Trang 145.6 Các lệnh mã giả mở rộng
Thiết lập các tham số trong menu Simulator -> Settings:
SPIM set Bare Machine OFF, Allow Pseudo Instructions ON, Load Trap File OFF, Delayed Branches ON, Delayed Loads ON, Mapped IO OFF, Quiet OFF
Ví dụ theo sau thực hiện việc tính hóa đơn bữa ăn:
tổng phí = tiền thức ăn + 8% tiền thuế +15% tiền phục vụ
addiu $8,$8,0x20 # uncapitalize char
sb $8,($10) # replace char in string
addiu $10,$10,1 # advance the char pointer
lbu $8,($10) # get the next char of the string
j loop # end while
li d,value # load register $d with the positive or negative
# integer "value" Value may be a 16 or a 32-bit integer
lw d,exp # Load register $d with the value at address "exp"
# "exp" is often a symbolic address
la d,exp # load register $d with the address described by the
# expression "exp" "exp" is often a symbolic address
nop # no operation do nothing for one machine cycle
sw d,exp # Store register $d into the word at address exp
# exp can be any of several expression types
# that evaluate to an address
mul d,s,t # multiply $s by $t put the result in $d
div d,s,t # divide $s by $t Put the quotient in $d Operands are # two's complement
divu d,s,t # divide $s by $t Put the quotient in $d Operands are # unsigned
remu d,s,t # divide $s by $t Put the remainder in $d Operands are # unsigned
Trang 15# Get meal cost
main: li $v0,4 # print prompt
lw $s1,tip # get tip rate
lw $s2,tax # get tax rate
addu $s3,$s1,$s2 # (tax + tip) in percent
mul $s4,$s0,$s3 # mealcost*(total rate)
div $s4,$s4,100 # mealcost*(total rate)/100
addu $s5,$s0,$s4 # total bill
tip: .word 15 # tip rate in percent
tax: .word 8 # tax rate in percent
prompt: asciiz "Enter food cost: "
head1 : asciiz " Tax plus tip: "
head2 : asciiz "\n Total cost: "
Trang 165.7 Các chương trình xử lý xuất nhập
SPIM cung cấp các hàm hệ thống dùng để xử lý các thao tác xuất nhập sau:
Công việc Mã trong $v0 Tham số Giá trị trả về
print integer 1 $a0 == integer
print float 2 $f12 == float
print double 3 ($f12, $f13) == double
print string 4 $a0 == address of string
read string 8 $a0 == buffer address
$a1 == buffer length allocate memory 9 $a0 == number of bytes $v0 == address
exit 10
Sau đây là ví dụ sử dụng hàm hệ thống để in chuỗi ký tự và kết thúc chương trình:
Thiết lập các tham số trong menu Simulator -> Settings:
Bare Machine OFF, Allow Pseudo Instructions ON, Load Trap File ON, Delayed Branches ON, Delayed Loads ON, Mapped IO OFF, Quiet OFF
Ví dụ sau in ra mẫu thư nhắc nhở trả sách một cách tự động sau khi người dùng nhập tên người mượn sách trả trễ:
li $v0,4 # code 4 == print string
la $a0,string # $a0 == address of the string
syscall # Invoke the exception handler
Trang 175.8 Dùng stack tính toán biểu thức
Thanh ghi stack pointer ($sp) dùng để quản lý stack Thanh ghi này chỉ đến phần tử trên đỉnh ở vùng nhớ stack Khi chương trình bắt đầu chạy, $sp có giá trị khởi tạo 0x7FFFFFFC Vùng nhớ stack mở rộng xuống dưới đồng nghĩa giá trị thanh ghi $sp giảm đi
Tác vụ PUSH phần tử vào stack tiến hành hai việc:
• Thứ nhất, thay đổi giá trị thanh ghi $sp để trỏ đến phần tử đỉnh mới
• Thứ hai, lưu giá trị vào vị trí đỉnh mới
Tương tự, tác vụ POP phần tử ra stack tiến hành hai việc:
• Thứ nhất, lưu giá trị phần tử đỉnh stack vào biến
• Thứ hai, thay đổi giá trị thanh ghi $sp trỏ đến phần tử đỉnh mới
li $v0,8 # code 8 == read string
la $a0,name # $a0 == address of buffer
li $a1,24 # $a1 == buffer length
syscall # Invoke the operating system
# print the letter
prompt: asciiz "enter name, followed by comma-enter: "
letter: ascii "\n\nDear "
name: .space 24
body: .ascii "\nYour library books are way\n"
.ascii "overdue Please return them\n"
.ascii "before we give your name\n"
.ascii "to the enforcement squad.\n"
# end of file