ΑΝΩΤΑΤΟ ΤΕΧΝΟΛΟΓΙΚΟ ΕΚΠΑΙ ΕΥΤΙΚΟ Ι ΡΥΜΑ ΣΕΡΡΩΝ ΣΧΟΛΗ ΤΕΧΝΟΛΟΓΙΚΩΝ ΕΦΑΡΜΟΓΩΝ ΤΜΗΜΑ ΠΛΗΡΟΦΟΡΙΚΗΣ ΚΑΙ ΕΠΙΚΟΙΝΩΝΙΩΝ ΑΡΧΙΤΕΚΤΟΝΙΚΗ Η/Υ Project 19 Sermac ;-) Σέρρες 2008
Θέµα Να κατασκευαστεί πρόγραµµα σε γλώσσα µηχανής του 8088 που να µπορεί να επιλύει εξισώσεις µίας µεταβλητής 1ου βαθµού της µορφής Αχ+Β=0. Οι συντελεστές της εξίσωσης θα βρίσκονται σε µεταβλητές διευθύνσεις, ενώ τα αποτελέσµατα θα γράφονται σε σταθερές διευθύνσεις. Να ελεγχθούν οι περιπτώσεις αόριστης (ταυτότητας) και αδύνατης εξίσωσης. Σηµείωση: θα χρειαστεί η υλοποίηση ρουτίνας διαίρεσης. Γενικές γνώσεις Ονοµάζουµε εξίσωση 1 ου βαθµού µε έναν άγνωστο κάθε εξίσωση που µπορεί να γραφτεί µε τη µορφή: αx+β=0, όπου x ο άγνωστος και α, β γνωστοί σταθεροί αριθµοί. Ο αριθµός που θέτουµε στη θέση του x ώστε να φθάσουµε σε µαθηµατική ισότητα λέγεται ρίζα της εξίσωσης. Λύση της πρωτοβάθµιας εξίσωσης αx+β=0: Αν α 0 και β 0 τότε η εξίσωση έχει ακριβώς µία λύση, την x=-β/α. Αν α 0 και β=0 τότε η εξίσωση δεν νοείται γιατί το µηδέν δεν διαιρείται. Αν α=0 και β 0 τότε κανένα x δεν ικανοποιεί την εξίσωση και η λύση είναι αδύνατη. Αν α=0 και β=0 τότε κάθε x ικανοποιεί την εξίσωση και η λύση λέµε ότι είναι αόριστη. - 2 -
Λογικό διάγραµµα - 3 -
Υλοποίηση µε γλώσσα C++ #include<stdio.h> #include<conio.h> main() float A,B,x; printf("dose ton arithmo A:\t"); scanf("%f",&a); printf("dose ton arithmo B:\t"); scanf("%f",&b); if(a==0) if(b==0) printf("aoristi"); else printf("adinati"); else getch(); if(b==0) printf("de noeitai"); else x=-b/a; printf("x=%f",x); Download: http://sermac.files.googlepages.com/project19.cpp Παραδείγµατα - 4 -
Υλοποίηση µε γλώσσα Assembly #make_bin# MOV DX,00H MOV AX,00H MOV AX,[0202H+SI] MOV BX,[0200H+SI] ;Μηδενισµός υπόλοιπου ;Μηδενισµός AX ;Μεταβλητές θέσεις µνήµης ;Μεταβλητές θέσεις µνήµης CMP BX,00 ;Έλεγξε α JE A_MIDEN_ELEGXOS_B ;Αν α=0 άλµα, αλλιώς (αν α<>0) συνέχισε CMP AX,00 ;Έλεγξε β (ενώ α<>0) JE MIDEN ;Αν β=0 άλµα, αλλιώς (αν β<>0) συνέχισε PUSH BX CALL LISI ;Αποθήκευση στη στοίβα ;Κλήση υπορουτίνας υπολογισµού λύσης POP BX ;Ανάκτηση από τη στοίβα JMP END ;Άλµα στο τέλος A_MIDEN_ELEGXOS_B: CMP AX,00 JE AORISTI MOV AL,02 JMP END AORISTI: MOV AL,01 JMP END MIDEN: MOV AL,03 JMP END LISI: IDIV BX NEG AX MOV [0204H],AX MOV [0206H],DX RET END: HLT ;Έλεγξε β (ενώ α=0) ;Αν β=0 άλµα, αλλιώς (αν β<>0) συνέχισε ;AL δείχνει 02 (Α ΥΝΑΤΗ x=-β/0) ;Άλµα στο τέλος ;AL δείχνει 01 (ΑΟΡΙΣΤΗ x=-0/0) ;Άλµα στο τέλος ;AL δείχνει 03 ( Ε ΝΟΕΙΤΑΙ x=-0/α) ;Άλµα στο τέλος ;x=-β/α ; ιαίρεση µε πρόσηµο ;Αλλαγή προσήµου ;Πηλίκο ;Υπόλοιπο ;Επιστροφή από υπορουτίνα ;Τέλος Download: http://sermac.files.googlepages.com/project19.asm Επεξήγηση του κώδικα Αρχικά µηδενίζουµε τον καταχωρητή DX στον οποίο θα µεταφερθεί το υπόλοιπο της διαίρεσης που θα κάνουµε στη συνέχεια. Οµοίως, µηδενίζουµε και τον καταχωρητή AΧ όπου θα αποθηκευτούν τα αποτελέσµατα. Αυτά τα κάνουµε για να βεβαιωθούµε ότι η τιµές των καταχωρητών είναι σίγουρα µηδέν στην αρχή του προγράµµατος και δεν υπάρχουν δεδοµένα από προηγούµενη εκτέλεση. Επειδή οι συντελεστές της εξίσωσης πρέπει να βρίσκονται σε µεταβλητές διευθύνσεις, χρησιµοποιούµε τον καταχωρητή SI ως δείκτη. Στη συνέχεια, το πρόγραµµα µεταφέρει την τιµή β στον καταχωρητή AX και την τιµή α στον καταχωρητή AX. Με τη βοήθεια της εντολής CMP (Compare) ελέγχουµε την τιµή του α. Αν το α είναι µηδέν τότε το πρόγραµµα κάνει άλµα µε την εντολή JE (Jump Equal) στη διακλάδωση A_MIDEN_ELEGXOS_B. Στη διακλάδωση A_MIDEN_ELEGXOS_B γίνεται έλεγχος του β. Αν είναι ίσο µε µηδέν τότε γίνεται άλµα στην διακλάδωση AORISTI, όπου δίνεται στον καταχωρητή AL η τιµή 01 για να µπορούµε να ξεχωρίσουµε ότι η περίπτωση που είχαµε ήταν αδύνατη. Αν το β είναι διάφορο του µηδενός τότε η εξίσωση είναι αδύνατη και δίνεται στον καταχωρητή AL η τιµή 02. - 5 -
Σε περίπτωση, τώρα, που το α δεν είναι ίσο µε το µηδέν, γίνεται έλεγχος για την τιµή του β. Αν το β είναι µηδέν βρισκόµαστε σε µια κατάσταση όπου η πράξη δε νοείται και το πρόγραµµα κάνει άλµα στην διακλάδωση MIDEN, όπου ο καταχωρητής AL παίρνει την τιµή 03. Αν το β δεν είναι µηδέν έχουµε µία λύση, την x=-β/α. Για την εύρεση της λύσης αυτής καλούµε την υπορουτίνα LISI, η οποία υλοποιεί τη διαίρεση β/α, αφού πλέον αυτοί σίγουρα δεν είναι µηδέν. Για τη διαίρεση χρησιµοποιείται η εντολή IDIV (Integer Divide signed) η οποία µας επιτρέπει να διαιρούµε προσηµασµένους αριθµούς. Αφού εκτελέσουµε τη διαίρεση, αλλάζουµε το πρόσηµο του πηλίκου µε την εντολή NEG (Negative) και µεταφέρουµε πηλίκο και υπόλοιπο στις αντίστοιχες θέσεις µνήµης. Πριν την κλήση της υπορουτίνας κάνουµε χρήση της εντολής PUSH για να αντιγράψουµε τα περιεχόµενα του καταχωρητή BX, ενώ µετά την κλήση της υπορουτίνας χρησιµοποιούµε την εντολή POP για να ανακτήσουµε τα περιεχόµενα του καταχωρητή που χρησιµοποιήσαµε από τη στοίβα. Τέλος, όλες οι διακλαδώσεις τελειώνουν µε άλµα JMP στο τέλος, το οποίο σταµατάει τον emulator και τελειώνει το πρόγραµµα µας. Παραδείγµατα Για α=2 και β=8: Εισαγωγή τιµών Αποτελέσµατα Για α=-2 και β=8: - 6 -
Για α=0 και β=0: Εισαγωγή τιµών Αποτελέσµατα Για α=0 και β=5: Για α=26 και β=0: - 7 -