จากโจทย์เกี่ยวกับ ARM Instruction Set Architecture (ISA) ข้อ 1-17 ผมจะสรุปขั้นตอนการทำการบ้านให้กระชับและชัดเจน เพื่อให้คุณทำงานได้เร็วขึ้น พร้อมแนะนำคำตอบสำหรับส่วนที่ต้องอธิบายหรือบันทึกผล โดยอิงจากเนื้อหาที่ให้มาและการทดลองใน CPUlator (https://cpulator.01xz.net/?sys=arm-de1soc)
ไปที่ Editor > Assemble
ป้อนโค้ด:
.global _start
_start:
MOV R0, #5
MOV R1, #-2
MOV R2, R0
MOV R3, R1
LDR R4, =list
LDR R5, [R4]
STR R2, [R4]
LDR R6, [R4]
.data
list:
.word 'A', 'B', 'C', -1, -2, -3, 1, 2, 3, 0x77, 0x8888, 0x99999999
Assemble และกด F2 (Step) ทีละขั้น
บันทึกผลลงตาราง:
| Assembly | Machine Code | Register ที่เปลี่ยนและค่าที่ได้ | อธิบายความหมายของคำสั่ง |
|---|---|---|---|
| MOV R0, #5 | E3A00005 | R0 = 5 | ย้ายค่า 5 ไปที่ R0 |
| MOV R1, #-2 | E3E01001 | R1 = -2 | ย้ายค่า -2 ไปที่ R1 |
| MOV R2, R0 | E1A02000 | R2 = 5 | ย้ายค่าจาก R0 (5) ไปที่ R2 |
| MOV R3, R1 | E1A03001 | R3 = -2 | ย้ายค่าจาก R1 (-2) ไปที่ R3 |
| LDR R4, =list | E59F4004 | R4 = ที่อยู่ของ list | โหลดที่อยู่ของ list ไปที่ R4 |
| LDR R5, [R4] | E5945000 | R5 = 0x41 ('A') | โหลดค่าจากหน่วยความจำที่ R4 ชี้ไปที่ R5 |
| STR R2, [R4] | E5842000 | Memory[list] = 5 | เก็บค่าจาก R2 (5) ไปที่หน่วยความจำที่ R4 ชี้ |
| LDR R6, [R4] | E5946000 | R6 = 5 | โหลดค่าจากหน่วยความจำที่ R4 ชี้ไปที่ R6 |
list ซึ่ง R4 ชี้อยู่ คำสั่ง LDR R5, [R4] โหลดค่าแรกของ list (คือ 'A' หรือ 0x41) จากหน่วยความจำไปยัง R5list เป็น .word มีขนาด 32 บิต (4 ไบต์)STR R2, [R4] เก็บค่า 5 จาก R2 ไปที่ตำแหน่งแรกของ list แทนที่ค่าเดิม ('A') ทำให้หน่วยความจำที่ list เปลี่ยนจาก 0x41 เป็น 0x05ป้อนโค้ด:
.global _start
_start:
MOV R0, #7
MOV R1, #3
AND R2, R0, R1
ORR R3, R0, R1
EOR R4, R0, R1
MVN R5, R0
ADDS R6, R0, R1
SUBS R7, R0, R1
MULS R8, R0, R1
CMP R0, R1
CMP R1, R0
CMP R0, R0
Assemble และ Step (F2) บันทึกผล:
| Assembly | Machine Code | Register ที่เปลี่ยนและค่าที่ได้ | N Z C V | อธิบายความหมาย |
|---|---|---|---|---|
| MOV R0, #7 | E3A00007 | R0 = 7 | 0 0 0 0 | ย้ายค่า 7 ไป R0 |
| MOV R1, #3 | E3A01003 | R1 = 3 | 0 0 0 0 | ย้ายค่า 3 ไป R1 |
| AND R2, R0, R1 | E0022001 | R2 = 3 | 0 0 0 0 | R2 = R0 AND R1 (7 & 3 = 3) |
| ORR R3, R0, R1 | E1833001 | R3 = 7 | 0 0 0 0 | R3 = R0 OR R1 (7 |
| EOR R4, R0, R1 | E0244001 | R4 = 4 | 0 0 0 0 | R4 = R0 XOR R1 (7 ^ 3 = 4) |
| MVN R5, R0 | E1E05000 | R5 = 0xFFFFFFF8 | 0 0 0 0 | R5 = NOT R0 (~7 = -8) |
| ADDS R6, R0, R1 | E0966001 | R6 = 10 | 0 0 0 0 | R6 = R0 + R1 (7 + 3 = 10), ตั้ง Flags |
| SUBS R7, R0, R1 | E0577001 | R7 = 4 | 0 0 1 0 | R7 = R0 - R1 (7 - 3 = 4), ตั้ง Flags |
| MULS R8, R0, R1 | E0087190 | R8 = 21 | 0 0 0 0 | R8 = R0 * R1 (7 * 3 = 21), ตั้ง Flags |
| CMP R0, R1 | E1500001 | - | 0 0 1 0 | เปรียบเทียบ R0 > R1 (7 > 3) |
| CMP R1, R0 | E1510000 | - | 1 0 0 0 | เปรียบเทียบ R1 < R0 (3 < 7) |
| CMP R0, R0 | E1500000 | - | 0 1 1 0 | เปรียบเทียบ R0 = R0 (7 = 7) |
ADDS, SUBS, MULS, และ CMP มีผลต่อ Flags เพราะมีตัว S (Set Flags) หรือออกแบบมาเพื่อตั้งค่า N, Z, C, V ตามผลลัพธ์การคำนวณ เพื่อใช้ในการควบคุมเงื่อนไขต่อไปADDEQ แทนการแยกเงื่อนไข ส่วน x86 ใช้ CISC คำสั่งซับซ้อนกว่าและจำนวนมากกว่าป้อนโค้ด:
.global _start
_start:
MOV R0, #7
MOV R1, #3
MOV R2, #9
CMP R0, R1
BEQ Label_EQ
Label_NE:
BGT Label_GT
Label_LT:
LSL R3, R2, #5
B Label_END
Label_EQ:
ROR R4, R2, #2
B Label_END
Label_GT:
ASR R5, R2, #2
Label_END:
ทดลองเปลี่ยนค่า R0, R1 และบันทึกผล:
Label_GT, R5 = 2 (9 >> 2)Label_LT, R3 = 288 (9 << 5)Label_EQ, R4 = 0x40000002 (9 ROR 2)Flowchart:
Start → MOV R0, R1, R2 → CMP R0, R1
→ (Z=1?) → Yes → Label_EQ (ROR R4) → Label_END
→ No → (N=V?) → Yes → Label_GT (ASR R5) → Label_END
→ No → Label_LT (LSL R3) → Label_END
คำตอบ: โปรแกรมเปรียบเทียบ R0 กับ R1 แล้วเลือกคำสั่ง Shift/Rotate ตามเงื่อนไข
ตาราง:
| R0 | R1 | R0-R1 | N Z C V | เงื่อนไข |
|---|---|---|---|---|
| 7 | 5 | 2 | 0 0 1 0 | R0 > R1 |
| 5 | 7 | -2 | 1 0 0 0 | R0 < R1 |
| 5 | 5 | 0 | 0 1 1 0 | R0 = R1 |
| -5 | -5 | 0 | 0 1 1 0 | R0 = R1 |
| -5 | -7 | 2 | 0 0 1 0 | R0 > R1 |
| -7 | -5 | -2 | 1 0 0 0 | R0 < R1 |
คำตอบข้อ 14: ARM และ x86 มี Flags คล้ายกัน (N, Z, C, V) แต่ ARM ใช้ Conditional Execution ทำให้ลด Branch ได้ x86 ต้องใช้คำสั่ง Branch เยอะกว่า
ป้อนโค้ด:
.global _start
_start:
MOV R0, #7
MOV R1, #3
MOV R2, #9
CMP R0, R1
ROREQ R4, R2, #2
ASRGT R5, R2, #2
LSLLT R3, R2, #5
ทดลองเปลี่ยน R0, R1:
คำตอบข้อ 16: ข้อ 15 ใช้ Conditional Execution ทำงานในคำสั่งเดียว ลด Branch เมื่อเทียบกับข้อ 11 ที่ใช้ Branch แยก