Προηγμένοι Μικροεπεξεργαστές Εργαστήριο 3 Switching in PM
Περιγραφή Διαχείριση διεργασιών μέσα από protected mode. Υπάρχων κώδικας: Περνάει σε protected mode Αρχικοποιεί όλες τις δομές Δίνει τον έλεγχο σε μία protected mode συνάρτηση με το όνομα main
Περιγραφή Συνέχεια Υπάρχων κώδικας: Όταν χτυπάει το IRQ0 αυξάνει τον timer δίνει τον έλεγχο στο default task (συνάρτηση main()) μέσω call στον selector του default task (TSS_SEL) Υπάρχουν άλλα δύο tasks χρήστη: TASK1_SEL, entry_point = task1 TASK2_SEL, entry_point = task2
Σκοπός Υλοποίηση μίας main για το default task που θα έχει τον ρόλο του scheduler
Στόχος Πιο αναλυτικά Πρέπει να γράψουμε: μία συνάρτηση main που θα καλείται από την αρχικοποίηση του protected mode θα εκτελείται μέχρι τα active bits και των δύο διεργασιών χρήστη να γίνουν μηδέν θα εξετάζει ποιες από τις δύο διεργασίες (TASK1_TSS_SEL και TASK2_TSS_SEL) είναι ενεργές θα κάνει task ing ανάμεσα σε όσες διεργασίες είναι ενεργές
Δομή κώδικα Το κεντρικό μας αρχείο περιέχει μόνο τον κώδικα της εφαρμογής Τα υπόλοιπα βρίσκονται σε βοηθητικά αρχεία που κάνουμε include στο κεντρικό μας: macros.mac stdlib.asm gdt.asm idt.asm stdio_32bit.asm
Αρχείο macros.mac Περιέχει τις δηλώσεις των structs seg_descriptor: Περιγράφει τους descriptors task_state_seg: Περιγράφει τα TSS struc seg_descriptor limit0_15: resw 1 base0_15: resw 1 base16_23: resb 1 type_dpl: resb 1 limit16_19: resb 1 base24_31: resb 1 endstruc struc task_state_seg tss_back_link: resd 1 tss_esp0: resd 1... endstruc
Αρχείο macros.mac Όπως και στο προηγούμενο εργαστήριο: Δέσμευση και αρχικοποίηση - παράδειγμα: label: istruc struct_name at member_1, dw value... at member_n, db value iend Προσπέλαση - παράδειγμα: mov eax,[struct_variable + member_n]
Αρχείο stdlib.asm Περιέχει την αρχικοποίηση και τον τερματισμό του συστήματος Περιέχει το πέρασμα στο protected mode και την επιστροφή στο real mode Διεπαφή με τον κώδικά μας: Περνάμε στο stdlib.asm κάνοντας jump στην start, από την αρχή του αρχείου μας Το stdlib.asm δίνει τον έλεγχο σε μία protected mode συνάρτηση με το όνομα main
Αρχείο stdlib.asm Αλλαγές σε σχέση με το παρελθόν: Η αρχικοποίηση των base addresses των descriptors γίνεται με χρήση της συνάρτησης initialize_descriptor_base() Αρχικοποιούμε τα TSS των δύο tasks χρήστη με την συνάρτηση initialize_tss() Δίνουμε παραμετρικά: backlink, code selector, data selectors, stack selector, stack pointer, entry point
Αρχεία gdt.asm και idt.asm Περιέχουν τα descriptor tables και σχετικές μεταβλητές Αλλαγές: Έχουν δεσμευτεί TSS descriptors και stack descriptors για τα δύο tasks χρήστη
Αρχείο stdio_32bits.asm Περιέχει τις συναρτήσεις εκτύπωσης και καθαρισμού που υλοποιήσαμε στο προηγούμενο εργαστήριο Δεν χρησιμοποιούνται σε αυτό το εργαστήριο
Αρχείο PM_task_.asm Το κεντρικό μας αρχείο Περιέχει τον κώδικα της εφαρμογής μας Περιέχει τα includes των υπόλοιπων αρχείων
Αρχείο PM_task_.asm Δεδομένα: active1, active2: αρχικοποιούνται σε 1, μηδενίζονται στον τερματισμό του αντίστοιχου task timer: ο μετρητής των ticks του hardware timer BSS: Στοίβες για real mode και για κάθε ένα από τα protected mode tasks
Αρχείο PM_task_.asm Κώδικας: main() -> την γράφετε εσείς task1() -> γεμίζει την οθόνη με κόκκινα χαμόγελα από πάνω προς τα κάτω. To tss στο οποίο δείχνει ο TASK1_TSS_SEL, έχει eip αρχικοποιημένο σε task1 task2() -> γεμίζει την οθόνη με πράσινα χαμόγελα από κάτω προς τα πάνω. To tss στο οποίο δείχνει ο TASK2_TSS_SEL, έχει eip αρχικοποιημένο σε task2
Αρχείο PM_task_.asm ISR: unhand timer_isr Εξυπηρετεί μέσω interrupt gate το int 0x08h Αυξάνει την μεταβλητή timer Κάνει call στο TSS_SEL:0, δηλαδή task στο task του scheduler
Scheduler task 1 task 2 IRQ0 IRQ0 timer_isr main() call TSS_SEL:0 Πρέπει: def_task_busy_bit = 0 Μετά: taskx_busy_bit = 1 def_task_busy_bit = 1 def_task_nt = 1 def_task_backlink = taskx
Scheduler 1 ος Τρόπος task 1 task 2 IRQ0 IRQ0 timer_isr main() Πρέπει: taskx_busy_bit = 0 jmp taskx_tss_sel:0 Μετά: taskx_busy_bit = 1 taskx_nt = 0 def_task_busy_bit = 0 call TSS_SEL:0 Πρέπει: def_task_busy_bit = 0 Μετά: taskx_busy_bit = 1 def_task_busy_bit = 1 def_task_nt = 1 def_task_backlink = taskx
Scheduler 2 ος Τρόπος task 1 task 2 IRQ0 IRQ0 timer_isr main() Πρέπει: taskx_busy_bit = 0 call taskx_tss_sel:0 Μετά: taskx_busy_bit = 1 taskx_nt = 1 def_task_busy_bit = 1 call TSS_SEL:0 Πρέπει: def_task_busy_bit = 0 Μετά: taskx_busy_bit = 1 def_task_busy_bit = 1 def_task_nt = 1 def_task_backlink = taskx
Scheduler 3 ος Τρόπος task 1 task 2 IRQ0 IRQ0 timer_isr main() iret με def_task_backlink = taskx_tss_sel Πρέπει: taskx_busy_bit = 1 Μετά: taskx_busy_bit = 1 taskx_nt = 0 def_task_busy_bit = 0 def_task_nt = 0 call TSS_SEL:0 Πρέπει: def_task_busy_bit = 0 Μετά: taskx_busy_bit = 1 def_task_busy_bit = 1 def_task_nt = 1 def_task_backlink = taskx