เมื่อเกิด Exception ขึ้น Processor จะทำการเปลี่ยน Mode และกำหนดค่าให้ PC ด้วยค่า Exception vector ซึ่งอยู่ใน Vector table โดยมี Reset vector เก็บที่ตำแหน่ง 0x00000000 แล้ว Vector ตัวต่อมาจะอยู่ถัดไปทีละ 4 byte
Exception | Mode | Address |
Reset | Supervisor | 0x00000000 |
Undefined instruction | Undefined | 0x00000004 |
Software interrupt (SWI) | Supervisor | 0x00000008 |
Prefetch Abort (instruction fetch memory abort) | Abort | 0x0000000C |
Data Abort (data access memory abort) | Abort | 0x00000010 |
----NB --------------------------------- | ------------- | 0x00000014 |
IRQ (interrupt) | IRQ | 0x00000018 |
FIQ (fast interrupt) | FIQ | 0x0000001C |
แต่จะมีตำแหน่งที่ 0x00000014 ไม่มีใน Vector table จุดนี้เรียก NB ซึ่งเป็นช่องที่ใช้ใน ARM รุ่นก่อนๆ และมีไว้เพื่อให้โปรแกรมเก่า สามารถทำงานบน ARM7 ได้ด้วย
Priority | Exception |
1 (Highest) | Reset |
2 | Data Abort |
3 | FIQ |
4 | IRQ |
5 | Prefetch Abort |
6 (Lowest) | Undefined instruction SWI |
ส่วนหากเกิดมี Exception ขึ้นมาหลายอันพร้อมกัน ทำอย่างไร จะกล่าวไว้ภายหลัง
เมื่อเกิด Exception ขึ้นอย่างเช่น เกิด IRQ Exception ก็จะมีขั้นตอนการทำงานดังนี้
1.ตำแหน่งของคำสั่งที่จะถูกทำงานถัดไป จะถูกเก็บลงใน LR แล้วนำค่า CPSR คัดลอกลงบน SPSR ของ Exception mode นั้น (ตามที่ยกตัวอย่างก็คือ SPSR_irq)
2.กำหนดค่าใหม่ให้กับ PC ด้วยค่าตำแหน่งของ Interrupt Service Routine (ISR) ที่ถูกเก็บไว้จากตารางตาม Exception ที่เกิดขึ้น (ค่าจาก 0x00000018 -IRQ) พร้อมกับการเปลี่ยน Mode และจัดการกับ Register (เมื่อเข้าสู่ IRQ Exception R13-14 จะกลายเป็น R13-14 _irq แทน นอกจากนั้นยัง Set ค่าที่ I-bit ของ CPSR เพื่อไม่ให้เกิดการ Interrupt ซ้อนขึ้นมาบนสาย IRQ แต่ถ้าหากเราต้องการให้มีการ Interrupt ซ้อนได้ภายในโปรแกรมของเราต้องทำการ Enable ที่ I-bit เอง รวมทั้งเก็บค่า LR ลองใน Stack ก่อน เพื่อเราจะได้เอามาใช้ในการกลับเข้ามาทำงานเดิมได้)
3.จะเข้าไปทำงานที่ ISR สิ่งแรกที่เราต้องทำคือเอาค่าของ R0-12 ที่เราจะนำมาใช้งานใน ISR ออกมา push ลง IRQ Stack ก่อนที่จะเริ่มทำงานต่างๆในนั้น
4.สิ่งที่ต้องทำอันดับแรกเมื่อทำงานเสร็จคือเราต้องคือ นำค่า CPSR ก่อนหน้า จาก SPSR กลับมาใส่ที่ SPSR รวมถึงการ Enable ให้ Interrupt นั้นกลับมาทำงานได้ แล้วจึงเข้าสู่การกลับไปยัง Mode เดิมเพื่อทำงานต่อไป แต่ว่าคำสั่งของ ARM ไม่มีคำสั่งในการกลับจาก Interrupt เราจึงต้องทำการกำหนดค่าให้กับ PC เองด้วยคำสั่งธรรมดา ซึ่งในแต่ละ mode ก็มีการกลับเข้าไปทำงานที่แตกต่างกันออกไป เราจะเริ่มพิจารณาจากคำสั่ง SWI (Software interrupt) ก่อนโดยเมื่อคำสั่ง SWI ทำงานตำแหน่งของคำสั่งถัดไป (PC) จะถูกเก็บลงบน LR แล้วเข้าสู่การทำงานใน Exception นั้นๆ และในการกลับมาจาก Exception เราจะต้องนำค่า LR กลับเข้าไปใส่ยัง PC เพื่อกลับไปทำงาน เช่นเดียวกับการทำการสลับไปกลับ User mode จึงการปรับปรุงคำสั่ง MOV (move) เป็น MOVS ซึ่งใช้ในการออกมากจาก Software interrupt
ส่วนคำสั่งสำหรับ FIQ และ IRQ เมื่อเกิด Exception ขึ้นคำสั่งที่กำลังทำงานจะหยุดและถูกทิ้งไป แล้วเข้าไปจัดการกับ Exception นั้น เมื่อกลับมาจากการทำงาน ค่า LR ที่เก็บไว้ไม่ได้รวมกับคำสั่งที่ถูกทิ้งไป เพื่อขณะเข้ามา Exception ก็ยังคงนำ PC ใส่ที่เช่นกัน LR ซึ่งมีตำแหน่งเกินจะคำสั่งที่แล้ว 4 byte ดังนั้นเพื่อให้กลับมาทำงานยังคำสั่งที่ถูกต้อง เราจะต้องย้อนตำแหน่งกลับไปที่ 4 byte ก่อนหน้า ทำให้มีการนำเอา SUB (subtract) มาใช้เพื่อทำการกลับไปทำงาน สำหรับ IRQ, FIQ หรือ Program Abort SUBS R15, R14, #4 ; R15 = R14 – 4 = (PC - 4)
สำหรับในกรณ๊ Data Abort เมื่อเกิด Exception ขึ้นเนื่องจากคำสั่งก่อนหน้าคำสั่งที่กำลังทำงาน อย่างเช่น มีคำสั่งหนึ่งเข้าใช้หน่วยความจำเสร็จแล้วคำสั่งต่อไปก็ถูกทำงาน แต่ขณะคำสั่งนั้นกำลังทำงานก็มี Exception ที่เกิดจากหน่วยความจำที่เราใช้งานคำสั่งก่อนหน้า เราก็ต้องทิ้งคำสั่งปัจจุบันไป ซึ่งรวมแล้วเราเสียคำสั่งไปสองอัน จึงทำให้เมื่อกลับมาทำงานเราต้องย้อนไป 8 byte = (4 byte * 2) จึงใช้คำสั่งดังนี้SUBS R15, R14, #8 ; R15 = R14 – 4 = (PC - 8)
ไม่มีความคิดเห็น:
แสดงความคิดเห็น