11 LC3 Programming
Shared by: 5E35cTB
-
Stats
- views:
- 69
- posted:
- 5/18/2012
- language:
- Thai
- pages:
- 37
Document Sample


ลิขสิทธิ์ของ อ.ชัชวิทย์ อาภรณ์ เทวัญ
ภาควิชาคณิตศาสตร์ และวิทยาการคอมพิวเตอร์ ๑
คณะวิทยาศาสตร์ จุฬาลงกรณ์ มหาวิทยาลัย
Last updated: May 18, 2012 22:34
บทที่ 11
LC3 Programming
••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
••วัตถุประสงค์ของการเรียนในบทนี้
เขียนโปรแกรมด้วยชุดคาสั่งของ LC3
••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
••
ในบทนี้เราจะมาเขียนโปรแกรมด้วยชุดคาสั่งขอ
ง LC3
่
ซึ่งมีสถาปัตยกรรมชุดคาสั่งทีแตกต่างจาก
Stack CPU โดยสิ้นเชิง
ุ
และยังมีอปกรณ์รับอินพุทและแสดงเอาพุท เช่น
คีย์บอร์ดและจอภาพ
ในการฝึกเขียนโปรแกรมให้ใช้ LC3 Simulator
จากเว็บไซต์ของรายวิชาที่ URL ดังนี้
http://pioneer.netserv.chula.ac.th/~achatch
a/2301274.html
๒
๓
LC3 assembly language
ในบทที่แล้วเราได้เห็น machine code ของ
LC3 ไปแล้ว
แต่เวลาเขียนโปรแกรมเราจะใช้ภาษา
assembly แล้วค่อยใช้ assembler แปลให้เป็น
machine code
คาสั่ง Add
Register mode: ADD R0, R1, R2 ; R[0] = R[1]
+ R[2]
Immediate mode: ADD R0, R1, #1 ;
R[0] = R[1] + 1
คาสั่ง And
Register mode: AND R0, R1, R2 ; R[0] = R[1]
& R[2]
Immediate mode: AND R0, R1, #255
; R[0] = R[1] & x0F
คาสั่ง Branch
PC-relative mode: BRn A (label) ; PC +=
offset, if n=1
BRzp A (label) ; PC +=
offset, if z=p=1
๔
คาสั่ง Jump
Register mode: JMP R0 ; PC = R[0]
คาสั่ง Jump Subroutine
PC-relative mode: JSR A (label) ;
R[7] = PC
; PC += offset
Register mode: JSSR R0 ; R[7] = PC
; PC = R[0]
คาสั่ง Load
PC-relative mode: LD R0, A ; R[0] =
M[PC + offset]
Indirect mode: LDI R0, A ; R[0] =
M[M[PC+offset]]
Base + offset mode: LDR R0, R1, #1 ;
R[0] = M[R[1] + 1]
คาสั่ง Load Effective Address
PC-relative mode: LEA R0, A ; R[0] = PC
+ offset
คาสั่ง Not
Register mode: NOT R0, R1 ; R[0] = ~R[1]
๕
คาสั่ง Store
PC-relative mode: ST R0, A ; M[PC +
offset] = R[0]
Indirect mode: STI R0, A ; M[M[PC+offset]]
= R[0]
Base + offset mode: STR R0, R1, #1 ;
M[R[1] + 1] = R[0]
คาสั่ง Return / Return from Interrupt / Trap to
Subroutine
Register mode: RET ; PC = R[7]
Register mode: RTI ; PC = R[7],
change mode
Immediate mode: TRAP x21 ; R[7] = PC,
PC = M[x21]
Variable
ตัวแปรจะประกาศไว้ใน assembler directives
เช่น มีตัวแปร A ก็ประกาศว่า
A .BLKW 1
ี
แต่ถ้าจะให้มค่าเริ่มต้นด้วย เช่น A = 1
ก็ประกาศว่า
A .FILL 0x0001
๖
ถ้าไม่ใช้ assembler directives
โปรแกรมเมอร์จะจาเอาเองก็ได้
ว่าตัวแปรนั้นอยู่ที่ address ใด
Array
อาร์เรย์ก็ประกาศเหมือนตัวแปรธรรมดา
เพียงแต่เพิ่มจานวน block ตามต้องการ เช่น
มีอาร์เรย์ 3 ช่องก็ประกาศว่า
A .BLKW 3
ี
แต่ถ้าจะให้มค่าเริ่มต้นด้วย เช่น A = {1, 2, 3}
ก็ประกาศว่า
A .FILL 0x0001
.FILL 0x0002
.FILL 0x0003
ตัวแปรแบบสตริง (array ของ character)
S .STRINGZ “Hello, World!”
Jump
ถ้าต้องการกระโดดจาก code
บรรทัดนึงไปยังอีกบรรทัดนึง ก็ทาได้หลายแบบ
เช่น
BRnzp A (label) ;
๗
กระโดดไปยัง A
่
แต่คาสัง BRnzp จะกระโดดไปได้ไม่ไกลกว่า
offset 9 บิท (2’com)
ถ้าจะกระโดดไปไกลกว่านั้นก็ต้องใช้คาสั่ง
LD R0, A (label) ; A
อยู่ไม่ไกลจากบรรทัดนี้มาก
JMP R0
………
A ้
.FILL ตาแหน่งที่ตองการจะกระโดดไป
เช่น 0x1000
If-then
โค้ดตามรูปนี้เลย
รูปที่ 11.1 โครงสร้างโปรแกรมแบบ if-then
ของ LC3
๘
If-else
โค้ดตามรูปนี้เลย
รูปที่ 11.2 โครงสร้างโปรแกรมแบบ if-else
ของ LC3
Condition
ไม่ว่าเราจะโปรแกรมเงื่อนไขอะไรก็ตาม LC3 มี
้ ่
condition code เพียง 3 บิทเท่านัน และคาสัง
BR จะทางานตาม condition code เสมอ
่
ดังนั้นเราต้องแปลงเงือนไขของเราให้เข้ากับ
condition code แล้วค่อยใช้คาสั่ง BR เช่น
A = 0, A != 0 LD R0, A
BRz … ; branch if A = 0
BRnp … ; branch if
A != 0
A >= 2 LD R1, A
๙
ADDR0, R1, #-2
BRzp … ; branch if
A – 2 >= 0
A>B LD R1, A
LD R2, B
NOTR2, R2
ADDR2, R2, #1
ADDR0, R1, R2
BRp … ; branch if A – B
>0
For-loop
ทาเหมือน Stack CPU ดูรูปที่ 9.5
While-loop
ทาเหมือน Stack CPU ดูรูปที่ 9.6
Functional Call & Recursive Call
ปัญหาของ LC3 คือไม่มีฮาร์ดแวร์สาหรับ Data
Stack (DS) และ Return Stack (RS)
๑๐
ดังนั้นจะเป็นหน้าที่ของโปรแกรมเมอร์ที่จะตัด
memory บางส่วนมาทา stack
เมื่อมีการเรียกใช้ฟังก์ชันจะเกิด stack frame
(หรือ activation record) ขึ้น
Stack frame ของการ call ฟังก์ชัน 1
้
ครังประกอบด้วยส่วนต่างๆ ดังแสดงในรูปที่
11.3 ทั้งก้อน stack frame คือ object 1
ชิ้นที่เราจะ push ลงไปใน stack
รูปที่ 11.3 Stack frame หรือ Activation
record
บล็อคสี่เหลี่ยม 1 ชิ้นคือ memory 1 ช่อง
้
มีขนาด 16 บิท pointer ที่จะชีไปที่ stack frame
่
จะชี้ไปที่ชอง frame pointer ดังนั้นถ้าเราเอา
๑๑
R5 เป็น pointer ก็จะ access ค่าต่างๆ ใน
stack frame ได้ดังนี้
LD R0, R5, #0 ; R0 = frame pointer
LD R0, R5, #-1 ; R0 = local variable
ตัวที่ 1
LD R0, R5, #-2 ; R0 = local variable
ตัวที่ 2
LD R0, R5, #-3 ; R0 = local variable
ตัวที่ 3
LD R0, R5, #1 ; R0 = return
address
LD R0, R5, #2 ; R0 = return value
LD R0, R5, #3 ; R0 = argument
ตัวสุดท้าย
แต่ละ record ใน stack frame คือ
Local variable หมายถึง ตัวแปร local
ั
ที่ประกาศและใช้อยู่ในฟังก์ชนนี้
ั
(ฟังก์ชนนี้เป็น callee)
๑๒
่
Frame pointer คือ ฟังก์ชันทีชี้กลับไปที่
stack frame ของ caller (caller ก็ต้องมี
stack frame ด้วย)
่
Return address คือ เมือทาฟังก์ชันนี้
(callee) เสร็จแล้ว ต้องเซ็ต PC =
return address
เพื่อกลับไปทางานต่อใน caller
ให้ถูกต้อง
Return value คือ ค่าที่ return
ั
จากฟังก์ชนนี้ (caller)
Argument คือ arg ที่ callee ส่งมาให้
caller
ผมให้ stack เริ่มต้นจาก address 0xFDFF
และ stack จะโตขึ้นไปทาง address x0000
การทา function call มีขั้นตอนดังนี้ (ให้ R5 ชี้ที่
ั
stack frame ปัจจุบน, R6 ชี้ที่ TOS)
1. Caller เริ่ม push argument ลงไปใน
stack (เริ่มสร้าง stack frame ใหม่แล้ว)
่
2. เรียกคาสัง JSR หรือ JSRR
เพื่อกระโดดไปทางานใน callee
๑๓
3. Callee จะสร้าง stack frame ใหม่ให้เสร็จ
โดยบันทึกค่า R7 ลงช่อง return address,
เซ็ต frame pointer ให้ชี้กลับไปที่ stack
frame ของ caller, ใส่ local variable
(ถ้ามี) ลงใน stack
4. Caller ทาการคานวณผลลัพธ์จนเสร็จ
และเขียนผลลัพธ์ลงในช่อง return value
5. เมื่อจะ return กลับ caller ต้องเลื่อน R6
้
(TOS) ให้ไปชีที่ return value, เอา return
address กลับมาไว้ที่ R7, เซ็ต R5
ให้ชี้กลับไปยัง stack frame ของ caller
่
6. เรียกคาสัง RET
่
7. Caller จะรู้วาผลลัพธ์จาก function call
อยู่ที่ TOS (R6)
8. Caller จะอ่านผลลัพธ์มาใช้ แล้วทาลาย
stack frame ของ callee ทิ้งไป
ลองดูตัวอย่างต่อไปนี้
function sum(a, b) {
return a + b
๑๔
}
main(void) {
x = sum(1,2)
}
เขียนโปรแกรมด้วย LC3
.ORIG x3000
; make a stack frame for main program (OS will do
this)
LD R6, TOS
LD R0, ZERO
ADD R6, R6, #-1
STR R0, R6, #0 ; push 0 (return value)
ADD R6, R6, #-1
STR R0, R6, #0 ; push 0 (return address)
ADD R6, R6, #-1
STR R0, R6, #0 ; push 0 (frame pointer)
ADD R5, R6, #0 ; R5 = R6, set frame pointer
ADD R6, R6, #-1 ; local variable (x)
; main program
LD R0, ONE
๑๕
ADD R6, R6, #-1
STR R0, R6, #0 ; push argument, 1
LD R0, TWO
ADD R6, R6, #-1
STR R0, R6, #0 ; push argument, 2
JSR SUM
LDR R0, R6, #0
STR R0, R5, #-1 ; x = R0
ADD R6, R6, #3 ; pop 3 items, destroy
callee's stack frame
HALT
SUM ADD R6, R6, #-2
STR R7, R6, #0 ; push R7 (save return
address)
ADD R6, R6, #-1
STR R5, R6, #0 ; push R5 (save frame
pointer)
ADD R5, R6, #0 ; R5 = R6 (move to the new
frame)
LDR R1, R5, #4 ; R1 = the 1st argument
๑๖
LDR R2, R5, #3 ; R2 = the 2nd argument
ADD R0, R1, R2
STR R0, R5, #2 ; save return value
ADD R6, R6, #2 ; R6 += 2 (-> return value)
LDR R7, R5, #1 ; restore R7 (if R7 has been
overwritten)
LDR R5, R5, #0 ; R5 -> caller's stack frame
RET
ZERO .FILL 0x0000
ONE .FILL 0x0001
TWO .FILL 0x0002
TOS .FILL 0xFE00 ; 0xFDFF + 1
.END
Memory-mapped I/O
ที่ผ่านมาได้แสดงให้ดูแล้วว่าไมโครโปรเซสเซอ
ร์อ่านและเขียน memory ได้อย่างไร
ุ
ทีนี้ถ้ามีอปกรณ์ input/output
แล้วไมโครโปรเซสเซอร์จะอ่านและเขียนอุปกร
ณ์เหล่านั้นได้อย่างไร วิธีหนึ่งก็คือใช้ mapped
๑๗
ุ ่
I/O หลักการคือทาให้อปกรณ์นั้นอยูใน
memory space เช่น คีย์บอร์ด อยู่ที่ address
0xFF01
เมื่อจะอ่านค่าจากคีย์บอร์ดก็ให้โหลดค่าจาก
address 0xFF01 ได้เลย
ั
(ขอไม่อธิบายว่าออกแบบฮาร์ดแวร์ยงไง
ให้ลองจินตนาการดูเอง)
้
แต่วิธีนี้มีขอเสียก็คือจะเสีย memory space
ไปบางส่วน
ถ้าไม่ทา memory-mapped I/O ก็ต้องใช้
instruction พิเศษ เช่น ไมโครโปรเซสเซอร์มี
instruction ที่ใช้จัดการกับอุปกรณ์ I/O
Keyboard
ิ
คีย์บอร์ดที่ต่อกับ LC3 มีรีจสเตอร์ 2 ตัวคือ
KBSR และ KBDR ดังรูปที่ 11.4
่ ่ ื
บิททีทาเครืองหมายกากบาทไว้คอไม่ได้ใช้
๑๘
รูปที่ 11.4 KBSR และ KBDR
ถ้า MSB ของ KBSR = 0
์ ้
คือยังไม่มีการกดคียบอร์ด แต่ถา KBSR = 1
์
คือคียบอร์ดถูกกดแล้ว
่
และปุมที่ถูกกดจะแสดงใน KBDR เป็นรหัส
ASCII
้
ต่อไปนีคือตัวอย่างโปรแกรมที่รอให้มีการกดคีย์
์
บอร์ดและอ่านค่าจากคียบอร์ดมาเก็บไว้ใน R[0]
.ORIG x3000
START LDI R1, KBSR
BRzp START
LDI R0, KBDR
HALT
KBSR .FILL 0xFE00
KBDR .FILL 0xFE02
.END
Monitor
๑๙
ี
มอนิเตอร์ก็ใช้รจิสเตอร์สองตัวเหมือนคีย์บอร์ดคื
อ Display Status Register (DSR) และ
่
Display Data Register (DDR) ซึ่งอยูที่
address 0xFE04 และ 0xFE06 ตามลาดับ
้
ต่อไปนีคือโปรแกรมที่พิมพ์ตัวอักษรใน R[0]
ออกไปที่จอภาพ ใน simulator
่
สามารถกาหนดค่าเริมต้นให้ R[0] ได้โดยใช้
่
Set Value ลองกาหนดค่าเริมต้นให้ R[0] เป็น
0x0041
.ORIG x3000
START LDI R1, DSR
BRzp START ; DSR = 0 คือ busy, 1
คือ ready
STI R0, DDR
HALT
DSR .FILL 0xFE04
DDR .FILL 0xFE06
.END
Trap
่
คาสัง trap เป็นการเรียกใช้ subroutine
ของระบบ (หมายถึง ระบบปฏิบัติการ หรือ
๒๐
operating system)
ลองดูตัวอย่างโปรแกรมต่อไปนี้
เมื่อป้อนอินพุทเป็นอักษรตัวใหญ่
โปรแกรมจะเอาพุทเป็นอักษรตัวเล็ก
และโปรแกรมจะหยุดเมื่อกด 7
.ORIG x3000
LD R2, TERM
LD R3, ASCII
START TRAP x23 ; R[0] <- keyboard
ADD R1, R2, R0
BRz EXIT
ADD R0, R0, R3
TRAP x21 ; monitor <- R[0]
BRnzp START
TERM .FILL 0xFFC9 ; character 7 (2’com)
ASCII .FILL 0x0020 ;
ใช้แปลงตัวใหญ่เป็นตัวเล็ก
EXIT TRAP x25 ; HALT
.END
Trap vector ใน memory address ที่ x21,
้ ่ ่
x23, x25 จะชีไปที่ routine ทีทาหน้าทีต่อไปนี้
๒๑
x21 เขียน R[0] (รอให้ ready) ไปที่
monitor
x23 อ่าน keyboard (รอให้มีการกด)
มาเก็บใน R[0]
x25 ให้ shutdown หรือ halt
่
routine นี้เป็นส่วนหนึงของ operating system
ซึ่งถูกโหลดมาก่อนที่ user program
จะทางานแล้ว
Character output service routine (x21)
Character input service routine (x23)
๒๒
๒๓
HALT service routine (x25)
Interrupt-driven I/O
ตัวอย่างการเขียนโปรแกรมในหัวข้อ keyboard
และ monitor เรียกว่า “polling” ข้อเสียของ
polling คือ CPU ต้องคอยเฝ้าดู status register
ไว้ตลอด ทาให้เสีย CPU time
่
ไปโดยเปล่าประโยชน์ แทนทีจะเอา CPU
ไปทางานอย่างอื่น
่
ในหัวข้อนี้จะแสดงให้เห็นว่าเราสามารถเปลียนโ
หมดการทางานของอุปกรณ์ I/O ให้เป็นแบบ
“interrupt” ได้ ตัวอย่างการใช้ interrupt ใน
์ ้
LC3 เช่น การอ่านคียบอร์ด เราไม่ตองใช้ CPU
ไปคอยอ่านค่า KBSR อยู่ตลอดเวลา (ปล่อย
๒๔
่
CPU ไปทางานอย่างอืนได้) ต่อเมื่อมีการกดปุ่ม
คีย์บอร์ดจะส่งสัญญาณ interrupt ไปบอก CPU
ั
เอง เมื่อ CPU ได้รบสัญญาณ interrupt
่ ์
(รู้วามาจากคียบอร์ด) ก็จะกระโดดไปทางานใน
์ ่ ่
subroutine ที่ใช้จัดการกับคียบอร์ด ซึงอยูที่
address ที่บรรจุอยู่ในช่อง x0180 ดังนั้น CPU
ก็จะเซ็ต PC ให้มีค่าเท่ากับ MEM[x0180]
๒๕
่
CPU โดยทัวๆ ไปจะต้องมีอย่างน้อย 2 โหมด
คือ 1) supervisor หรือ privilege mode และ 2)
user mode โหมดแรกจะทาได้ทุกอย่าง
ไม่ว่าจะเป็นการ execute คาสั่งใดๆ
และอ่าน/เขียนรีจิสเตอร์ได้ทุกตัว
่
โหมดทีสองจะถูกจากัดสิทธิ เช่น ไม่สามารถ
execute บางคาสั่ง หรือ
้
ไม่สามารถอ่าน/เขียนรีจิสเตอร์บางตัวได้ ที่ตองมี
2 โหมดเพราะว่าโหมดแรกใช้สาหรับ operating
system และโหมดที่สองใช้สาหรับ user
program ใน LC3 user mode จะ execute
่ ิ
คาสัง RTI ไม่ได้ และแก้ไขรีจสเตอร์บางตัวเช่น
Processor Status Register (PSR) ไม่ได้
่
โดยปกติเมือ user program ทางาน CPU
จะอยู่ใน user mode เมื่อเกิด interrupt
่
จะเปลียนโหมดเป็น supervisor mode
เพื่ออ่าน/เขียนรีจิสเตอร์ของอุปกรณ์ที่ทาให้เกิด
interrupt
้
รีจิสเตอร์พวกนีจะไม่สามารถอ่านเขียนใน user
mode ได้ ลองนึกถึงระบบที่มี user program
๒๖
อยู่หลายๆ โปรแกรม แล้วถ้า user program
ุ ่
ต้องการใช้อปกรณ์อย่างหนึง เช่น printer
ก็จะเกิดการแย่งกันใช้งาน ดังนั้นก็ต้องให้
operating system
ซึ่งเป็นคนกลางคอยจัดลาดับการใช้งานให้
(เรื่องนี้จะไปเรียนต่อในวิชา 2301371
Operating Systems)
การ enable ให้คีย์บอร์ดทางานแบบ interrupt
ทาได้โดยเซ็ตบิทที่ 14 ของ KBSR ให้เป็น “1”
ดังแสดงในรูปที่ 11.5
รูปที่ 11.5 Interrupt enable
๒๗
Operating system ของ LC3 แบ่งการใช้
memory ดังรูปที่ 11.6 สามส่วนแรกเป็น vector
table สาหรับ Trap, Exception, และ Interrupt
์ ้
LC3 simulator มี interrupt เฉพาะคียบอร์ดเท่านัน
่
โดยมี interrupt vector อยูที่ x0180 ส่วน
exception ใน LC3 มีสองตัว ซึ่งจะสร้างสัญญาณ
interrupt ขึ้น เมื่อเกิดเหตุการณ์ต่อไปนี้
Privilege mode violation
่
เช่น execute คาสัง RTI ใน user mode
Illegal opcode
เช่น opcode = 1101 (ไม่มี opcode นี้ใน
LC3)
่
โดยมี interrupt vector อยูที่ x0100 และ x0101
ตามลาดับ (exception ก็เป็น interrupt ประเภทหนึ่ง
ทางานเหมือน interrupt) memory
ส่วนถัดมาจะเป็นของ operating system, user
program และสุดท้ายเป็น memory-mapped I/O
ิ
(map ไปยังรีจสเตอร์ของอุปกรณ์ต่างๆ)
๒๘
รูปที่ 11.6 Interrupt enable
ตัวอย่างโปรแกรมต่อไปนี้จะใช้การ interrupt
้ ์
เพื่อแสดง character ที่ปอนทางคียบอร์ด
ให้นามาแสดงที่จอภาพ USP หมายถึง user stack
pointer (หรือ TOS ของ user stack)
.ORIG x3000
LD R6, USP
LEA R0, INTR
STI R0, VECT
LD R0, ENAB
STI R0, KBSR
WAIT BRnzp WAIT
๒๙
HALT
INTR LDI R0, KBDR
TRAP x21
RTI
VECT .FILL x0180
ENAB .FILL x4000
KBSR .FILL xFE00
KBDR .FILL xFE02
USP .FILL xFE00
.END
้
เวลา “step over” โปรแกรมนีใน LC3 simulator
มันจะไม่เข้าไปทางานใน interrupt service
routine ต้องใช้วิธีสังเกตค่าในรีจิสเตอร์ R0
ที่จะเปลี่ยนไปตามปุ่ม (character) ที่เรากด
โดยปกติ OS จะเป็นโปรแกรมที่ได้ใช้ CPU ก่อน
แล้วส่งต่อให้ user program ดังนั้นขณะที่ user
program ทางาน supervisor stack pointer
จะเก็บอยู่ใน Saved.SSP ซึ่งเมื่อ
๓๐
Processor Status Register
รีจิสเตอร์อีกตัวนึงใน LC3
ที่ผมไม่ได้กล่าวถึงตั้งแต่แรกคือ process status
register หรือ PSR แสดงในรูปที่ 11.7
รูปที่ 11.7 Processor Status Register
(PSR)
้
เราจะใช้แค่บางบิทของรีจิสเตอร์เท่านัน
บิทที่ 15 ถ้าเป็น 0 คือ supervisor mode, 1
คือ user mode
บิทที่ 10,9, 8 คือ priority level
ั
ของโปรแกรมปัจจุบน
อุปกรณ์ (device) ที่มี priority level
สูงกว่าจะสามารถ
interrupt โปรแกรมที่ priority
ต่ากว่าได้ เช่น คีย์บอร์ด
มี PL = 4 เป็นต้น (max = 7, min = 0)
๓๑
บิทที่ 2, 1, 0 คือ condition code
่
ตามทีสอนไปแล้ว
๓๒
Interrupt Priority
ุ ้
ในกรณีที่มีอปกรณ์หลายๆ ชิน สร้างสัญญาณ
interrupt ขึ้นพร้อมๆ กัน จะต้องมีวงจรที่ใช้เลือก
interrupt ที่มี priority level สูงสุด
และต้องเช็คด้วยว่า priority level
สูงกว่าโปรแกรมปัจจุบันหรือไม่ ดังรูปที่ 11.8
รูปที่ 11.8 Processor Status Register
(PSR)
๓๓
เมื่อ interrupt แล้ว OS จะต้องทาอะไรบ้าง
ต่อไปนี้เป็นหน้าที่ของ “operating system”
ั
ที่จะต้องทาเมื่อ CPU ได้รบสัญญาณ interrupt
เปลี่ยน user mode เป็น supervisor mode,
PSR[15] = 0, PSR[10:8] = PL ของอุปกรณ์ที่
interrupt, PSR[2:0] = 000
save “user stack pointer” และโหลด
“supervisor stack pointer” โดยทาดังนี้
(Saved.USP และ Saved.SSP
ิ ่
เป็นรีจิสเตอร์พเศษที่ใช้เพืองานนี้โดยเฉพาะ)
o Saved.USP = R[6] // R[6] เก็บ stack
pointer เสมอ
o R[6] = Saved.SSP
แต่ถ้าเป็น interrupt ซ้อน interrupt
้
ก็ไม่ต้องทาขันตอนนี้ เพราะ R[6] จะเป็น
Saved.SSP อยู่แล้ว
push ค่า PC และ PSR ลง supervisor stack
save รีจิสเตอร์ เช่น R0, R1, … ด้วย ถ้า
callee จะใช้
๓๔
เซ็ต PC ด้วย interrupt vector
เริ่มทา interrupt service routine
่
interrupt service routine จะจบด้วยคาสัง RTI
ซึ่งมีการทางานดังนี้
ิ
pop ค่าริจสเตอร์ R0, R1, … ที่เซฟไว้ (ถ้ามี)
pop ค่า PSR และ PC ออกมาจาก supervisor
stack
ถ้าเป็น user mode (ดู PSR ที่ pop ออกมา)
ให้เซฟ supervisor stack pointer และโหลด
user stack pointer ด้วย
o Save.SSP = R[6]
o R[6] = Saved.USP
แต่ถ้าเป็น interrupt ซ้อน interrupt จะยังอยู่ใน
supervisor mode ก็ไม่ต้องทาอะไร
เซ็ต PC = ค่า PC ที่ pop ออกมาจาก
supervisor stack
กลับไปทางานต่อจากจุดที่ถูก interrupt
่
Note- คาสัง RTI ทางานได้ใน supervisor mode
เท่านั้น
่
- ในขณะทีทา interrupt service routine
๓๕
หนึ่งอยู่ (ยังไม่เสร็จ)
ก็อาจจะโดน interrupt ซ้อนได้
แบบฝึกหัด
เรื่อง synchronous กับ asynchronous ผมไม่ได้สอน
้
(ข้ามไปไม่ตองทา)
๓๖
๓๗
Get documents about "