11 LC3 Programming

Shared by: 5E35cTB
Categories
Tags
-
Stats
views:
69
posted:
5/18/2012
language:
Thai
pages:
37
Document Sample
scope of work template
							ลิขสิทธิ์ของ อ.ชัชวิทย์ อาภรณ์ เทวัญ
ภาควิชาคณิตศาสตร์ และวิทยาการคอมพิวเตอร์                                   ๑
คณะวิทยาศาสตร์ จุฬาลงกรณ์ มหาวิทยาลัย
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 ผมไม่ได้สอน
           ้
(ข้ามไปไม่ตองทา)
๓๖
๓๗

						
Related docs
Other docs by 5E35cTB
El Ni�o - La Ni�a
Views: 10  |  Downloads: 0
ARC Quick Sheet
Views: 6  |  Downloads: 0
QUESTION TAGS or TAG QUESTIONS
Views: 158  |  Downloads: 0
Christmas 2010 Lunch Menu EMAIL
Views: 22  |  Downloads: 0
P7RFP Addendum1 20120217
Views: 2  |  Downloads: 0
CALENDER SEPT 2012 JULY 2013
Views: 12  |  Downloads: 0
SHIP PHOTOGRAPH OFFER #
Views: 4  |  Downloads: 0