3.5. Nhóm lệnh truy cập bộ nhớ
3.5.2. Các chế độ địa chỉ
Ta có hai chế độ đánh địa chỉ thông dụng là chỉ số trước (Pre-index) và chỉ số sau (Post-index). Chế độ đánh địa chỉ chỉ số trước sẽ tính toán địa chỉ từ một thanh ghi cơ sở cộng với địa chỉ dịch (offset), sau đó cập nhật địa chỉ thanh ghi nền bằng với địa chỉ mới. Trong chế độ chỉ số trước, địa chỉ thanh ghi nền không thay đổi. Trong chế độ chỉ số sau, địa chỉ thanh ghi nền chỉ được thay đổi sau khi địa chỉ đó đã được sử dụng. Thông thường, chế độ chỉ số trước được dùng khi cần truy cập phần tử của cấu trúc dữ liệu.
Tập lệnh ARM cho phép các chế độ đánh địa chỉ khác nhau. Các chế độ địa chỉ với các câu lệnh truyền dữ liệu được mô tả trong Bảng 3.8.
82
Bảng 3.8. Các chế độ địa chỉ Phương pháp
chỉ số
Địa chỉ dữ liệu Thanh ghi địa chỉ nền
Ví dụ Chỉ số trước và
ghi ngược
Mem[base + offset]
Base + offset LDR R0, [R1,
#4]!
Chỉ số trước không cập nhật
Mem [base + offset]
Không cập nhật LDR R0, [R1, #4]
Chỉ số sau Mem [base] Base + offset LDR R0, [R1], #4
a) Giá trị tức thời trong chế độ chỉ số trước
Địa chỉ bộ nhớ của dữ liệu được truyền là tổng của giá trị thanh ghi và một giá trị dịch tức thời.
Ví dụ 3.11 – Minh họa giá trị tức thời
LDRB R0, [R1, #0x3] ;Đọc giá trị byte từ địa chỉ R1 + 0x3, và lưu giá trị đọc vào R0
Giá trị dịch có thể có giá trị dương hay âm. Bảng 3.9 dưới chỉ ra một số câu lệnh nạp và lưu trữ giá trị hay gặp.
Bảng 3.9. Các lệnh truy cập bộ nhớ với giá trị tức thời
Truy cập bộ nhớ theo kiểu chỉ số trước
Mô tả
LDRB Rd, [Rn, #offset] Đọc byte dữ liệu từ địa chỉ Rn + offset
LDRSB Rd, [Rn, #offset] Đọc và đặt dấu cho byte dữ liệu ở địa chỉ Rn + offset
LDRH Rd, [Rn, #offset] Đọc nửa từ tại địa chỉ Rn + offset LDRSH Rd, [Rn, #offset] Đọc nửa từ và đặt dấu cho dữ liệu tại địa
chỉ Rn + offset
LDR Rd, [Rn, #offset] Đọc từ tại vị trí Rn + offset LDRD Rd1, Rd2, [Rn, #offset] Đọc hai từ tại vị trí Rn + offset STRB Rd, [Rn, #offset] Lưu trữ byte tại vị trí Rn + offset STRH Rd, [Rn, #offset] Lưu trữ nửa từ tại vị trí Rn + offset STR Rd, [Rn, #offset] Lưu một từ vào vị trí Rn + offset STRD Rd1, Rd2, [Rn, #offset] Lưu hai từ vào vị trí Rn + offset
83
Các chế độ địa chỉ hỗ trợ việc ghi đè lên thanh ghi trỏ về địa chỉ ô nhớ Ví dụ 3.12 – Chế độ tức thời có ghi đè địa chỉ
LDR R0, [R1, #0x8]! ; Sau khi truy cập ô nhớ R1 + 0x8, giá trị R1 được cập nhật lên thành R1 + 0x8
Dấu chấm than (“!”) chỉ thị cho chương trình biết rằng thanh ghi chứa địa chỉ ô nhớ có được cập nhật (ghi ngược lại) hay không khi câu lệnh hoàn thành. Địa chỉ được sử dụng cho việc truyền sử dụng sử dụng tổng R1 + 0x8 đã được tính toán kể cả khi dấu chấm than không được thêm vào. Các giá trị có thể ghi lại với các câu lệnh nạp và lưu trữ được tổng hợp trong Bảng 3.10.
Bảng 3.10. Các lệnh truy cập bộ nhớ với giá trị trực tiếp và ghi ngược
Ví dụ truy cập chỉ số trước và ghi ngược
Mô tả LDRB Rd, [Rn, #offset]! Đọc byte và ghi ngược
LDRSB Rd, [Rn, #offset]! Đọc và đặt dấu cho byte, ghi ngược LDRH Rd, [Rn, #offset]! Đọc nửa từ và ghi ngược
LDRSH Rd, [Rn, #offset]! Đọc và đặt dấu cho nửa từ, ghi ngược LDR Rd, [Rn, #offset]! Đọc từ và ghi ngược
LDRD Rd1, Rd2, [Rn, #offset]! Đọc double-word và ghi ngược STRB Rd, [Rn, #offset]! Lưu byte vào bộ nhớ và ghi ngược STRH Rd, [Rn, #offset]! Lưu nửa từ vào bộ nhớ và ghi ngược STR Rd, [Rn, #offset]! Lưu từ vào bộ nhớ và ghi ngược
STRD Rd1, Rd2, [Rn, #offset]! Lưu double-word vào bộ nhớ và ghi ngược
Chú ý rằng các lệnh này không được dùng với thanh ghi R15 (PC) hay R13 (SP). Thêm vào đó, phiên bản 16-bit của các câu lệnh này chỉ hỗ trợ các thanh ghi ở bank thấp (R0-R7)
a) Địa chỉ liên quan thanh ghi PC
Một địa chỉ bộ nhớ có thể được tạo ra từ giá trị thanh ghi PC hiện thời và một giá trị dịch. Các lệnh truy cập bộ nhớ với địa chỉ liên quan thanh ghi PC được nêu trong Bảng 3.11 dưới.
84
Bảng 3.11. Các lệnh truy cập bộ nhớ với địa chỉ liên quan thanh ghi PC Các lệnh truy cập bộ nhớ với
địa chỉ liên quan PC
Mô tả
LDRB Rt, [PC, #offset] Nạp giá trị byte dấu vào thanh ghi Rt từ địa chỉ dịch PC
LDRSB Rt, [PC, #offset] Nạp và đặt dấu cho dữ liệu byte vào Rt từ địa chỉ dịch PC
LDRH Rt, [PC, #offset] Nạp nửa từ không dấu vào Rt từ địa chỉ dịch PC
LDRSH Rt, [PC, #offset] Nạp và đặt dấu cho dữ liệu nửa từ vào Rt từ địa chỉ dịch PC
LDR Rt, [PC, #offset] Nạp một từ vào thanh ghi Rt sử dụng địa chỉ dịch PC
LDRD Rt, Rt2, [PC, #offset] Nạp double-word vào Rt và Rt2 sử dụng địa chỉ dịch PC
b) Giá trị dịch thanh ghi
Một chế độ hữu dụng là dịch giá trị thanh ghi. Phương pháp này thường được dùng trong quá trình truy cập vào mảng dữ liệu với địa chỉ là sự kết hợp giữa địa chỉ nền và giá trị dịch. Để giúp cho việc tính toán địa chỉ này hiệu quả hơn, giá trị chỉ số có thể được dịch đi 0-3 bits trước khi được cộng vào thanh ghi nền.
Ví dụ 3.13 – Minh họa giá trị dịch thanh ghi
LDR R3, [R0, R2, LSL #2] ; Đọc giá trị ô nhớ [R0 + (R2<<2)]
vào thanh ghi R3
Việc dịch bit là không bắt buộc. Ta có thể có một phép toán đơn giản như:
STR R5, [R0, R7] ; Ghi giá trị R5 vào ô nhớ [R0 + R7]
Tương tự với việc sử dụng các giá trị tức thời, các câu lệnh cho phép thao tác với nhiều kích thước dữ liệu như trong Bảng 3.12.
Bảng 3.12. Các lệnh truy cập bộ nhớ với giá trị dịch thanh ghi
Truy cập ô nhớ từ thanh ghi Mô tả
LDRB Rd, [Rn, Rm {, LSL#n}] Đọc giá trị byte từ ô nhớ Rn + (Rm <<n) LDRSB Rd, [Rn, Rm {, LSL#n}] Đọc và đặt dấu cho byte tại vị trí Rn + (Rm
<<n)
LDRH Rd, [Rn, Rm {, LSL#n}] Đọc nửa từ tại ô nhớ Rn + (Rm <<n) LDRSH Rd, [Rn, Rm {, LSL#n}] Đọc và đặt dấu cho nửa từ tại vị trí ô nhớ Rn
+ (Rm <<n)
85
LDR Rd, [Rn, Rm {, LSL#n}] Đọc từ tại ô nhớ Rn + (Rm <<n) STRB Rd, [Rn, Rm {, LSL#n}] Lưu byte vào ô nhớ Rn + (Rm <<n) STRH Rd, [Rn, Rm {, LSL#n}] Lưu nửa từ vào ô nhớ Rn + (Rm <<n) STR Rd, [Rn, Rm {, LSL#n}] Lưu từ vào ô nhớ Rn + (Rm <<n)
c) Giá trị tức thời trong chế độ chỉ số sau
Các lệnh truy cập bộ nhớ với chế độ địa chỉ chỉ số sau (post-index) cũng có các giá trị dịch tức thời. Tuy nhiên, giá trị dịch đó không được sử dụng trong quá trình truy cập bộ nhớ, mà nó được sử dụng để cập nhật thanh ghi địa chỉ sau khi việc truyền dữ liệu đã hoàn thành.
Ví dụ 3.14 – Minh họa giá trị tức thời chế độ chỉ số sau
LDR R0, [R1], #offset ; Đọc giá trị ô nhớ [R1], và cập nhật R1 lên R1 + offset
Khi chế độ địa chỉ chỉ số sau được sử dụng, ta không cần phải sử dụng dấu chấm than (“!”) vì thanh ghi chứa địa chỉ nền luôn được tự động cập nhật khi việc truyền dữ liệu hoàn thành. Các câu lệnh truy cập bộ nhớ chỉ số sau được tổng hợp trong Bảng 3.13.
Bảng 3.13. Các lệnh truy cập bộ nhớ chế độ chỉ số sau
Truy cập chỉ số sau Mô tả
LDRB Rd, [Rn], #offset Đọc giá trị byte từ ô nhớ Rn, cập nhật giá trị Rn
= Rn + offset
LDRSB Rd, [Rn], #offset Đoc giá trị byte và đặt dấu từ ô nhớ Rn, cập nhật giá trị Rn = Rn + offset
LDRH Rd, [Rn], #offset Đọc nửa từ tại ô nhớ [Rn], cập nhật Rn = Rn + offset
LDRSH Rd, [Rn], #offset Đọc và đặt dấu cho nửa từ tại ô nhớ [Rn], cập nhật Rn = Rn + offset
LDR Rd, [Rn], #offset Đọc từ tại ô nhớ [Rn], sau đó cập nhật Rn = Rn + offset
LDRD Rd1, Rd2, [Rn],
#offset
Đọc double word tại ô nhớ [Rn], sau đó cập nhật Rn = Rn + offset
STRB Rd, [Rn], #offset Lưu giá trị byte vào ô nhớ [Rn], cập nhật Rn = Rn + offset
STRH Rd, [Rn], #offset Lưu giá trị nửa từ vào ô nhớ [Rn], cập nhật Rn = Rn + offset
STR Rd, [Rn], #offset Lưu giá trị từ vào ô nhớ [Rn], cập nhật Rn = Rn + offset
STRD Rd1, Rd2, [Rn],
#offset
Lưu giá trị vào Rn, cập nhật Rn = Rn + offset
86
Ví dụ 3.15 – Thao tác lệnh LDR ở các chế độ địa chỉ khác nhau PRE R0 = 0x00000000
R1 = 0x00009000
mem32[0x00009000] = 0x01010101 mem32[0x00009004] = 0x02020202 LDR R0, [R1, #4]!
Preindexing with writeback:
POST (1) R0 = 0x02020202 R1 = 0x00009004 Preindexing
POST (2) R0 = 0x02020202 R1 = 0x00009000 Postindexing
POST (3) R0 = 0x01010101 R1 = 0x00009004
Ví dụ trên cho thấy ảnh hưởng của các chế độ địa chỉ lên giá trị thanh ghi R1 là thanh ghi chứa địa chỉ và giá trị của thanh ghi R0 là dữ liệu được trỏ đến bởi địa chỉ chứa trong thanh ghi R1.