1. Zweck des Experiments
- Analysieren und verstehen Sie die zugewiesenen zu lösenden Probleme.
- Verwenden Sie den Assembler-Code von LC-3, um zugehörige Programme zu entwerfen und zu realisieren.
- Debuggen Sie verwandte Programme und führen Sie sie über den LC-3-Emulator aus, um korrekte Ergebnisse zu erhalten.
2. Experimenteller Inhalt
Sortieren Sie die Noten der Schüler mithilfe eines Arrays.
Hintergrund: Eine Lehrerin benötigt Ihre Hilfe, um die Note des Schülers zu ermitteln. Sie möchte die Abschlussnote des Schülers anhand der Rangfolge der Schülernote in der Klasse und des Testergebnisses ermitteln.
Die spezifischen Notenanforderungen lauten wie folgt:
- Wenn die Punktzahl des Schülers zu den besten 25 % der Klasse gehört und das Testergebnis 85 Punkte oder mehr beträgt, kann der Schüler eine Eins erhalten
- Wenn ein Schüler keine Eins erreichen kann, aber mit einem Testergebnis von 75 oder mehr zu den besten 50 % der Klasse gehört, kann er eine Zwei erhalten
- Der Rest der Schüler ist allesamt C
Spezifische Situation:
- Insgesamt gibt es 16 Schüler und jeder Schüler hat nur eine Note
- Schreiben Sie ein Programm zum Sortieren der Noten für diese Klasse in Assembler.
- Ihr Programm muss die Noten der Schüler sortieren und dann die Anzahl der Schüler zählen, die die Noten „Eins“ und „Zwei“ erhalten haben. Programm beginnt mit x3000
Eingabe in das Programm:
- Unbewertete Noten der 16 Schüler der Klasse;
- Jeder Bruch ist eine Ganzzahl von 0 bis 100, dargestellt durch eine 16-Bit-Zahl ohne Vorzeichen
- Punkte werden an 16 aufeinanderfolgenden Speicherorten gespeichert – ein Punkt pro Ort; beginnend mit x3200;
- Der letzte Bruch wird in x320F gespeichert
- Sie können davon ausgehen, dass sich alle Bewertungen voneinander unterscheiden (jede Bewertung ist einzigartig).
Die Ausgabe des Programms (Ihr Programm muss zwei Ausgaben haben):
- Die Noten von 16 Schülern werden sortiert. Die Punkte müssen in absteigender Reihenfolge in aufeinanderfolgenden Speicherorten sortiert werden – ein Punktestand pro Speicheradresse, gespeichert ab x4000; d. h. x4000 speichert den höchsten Punktestand
- Die Anzahl der Schüler, die die Noten „A“ und „B“ erhalten haben. Die Anzahl der Schüler mit der Note „A“ muss in x4100 gespeichert werden und die Anzahl der Schüler mit der Note „B“ muss in x4101 gespeichert werden
3. Experimentelle Verfahren und Ergebnisse
1. Die allgemeine Idee und Durchführung des Experiments
Zunächst sollten die Originaldaten von 16 Scores in den Speicher x3200 eingegeben und durch eine Schleife auf x4000 kopiert werden.
Verwenden Sie die Blasensortierung, um die neue Adresse in absteigender Reihenfolge zu sortieren und so die Rangfolge zu ermitteln. Filtern Sie abschließend das Array bei x4000, um die Anzahl der Schüler zu zählen, die die Noten A und B erhalten haben. Das Gesamtflussdiagramm sieht wie folgt aus:
Das Obige ist ein abstrakter und allgemeiner Prozess, und die spezifische Implementierungsmethode wird im Folgenden erweitert. Das spezifische Flussdiagramm jedes Schritts wird unten bereitgestellt.
a) Vervollständigen Sie die Kopie von 16 Daten
Das Flussdiagramm des Algorithmus sieht wie folgt aus:
Es ist leicht zu erkennen, dass die Schleife die Do-Loop-Struktur annimmt.
Es gibt viele Orte, auf die man achten sollte. Um beispielsweise R3 einen Wert zuzuweisen, muss dieser aufgrund der Beschränkung des unmittelbaren Werts in [-16, 15] zweimal abgeschlossen werden. Und wenn Sie *R2 <- *R1 realisieren möchten, können Sie zur Vervollständigung zwei Anweisungen LDR und STR verwenden. Außerdem verwende ich Register R0, um die neue Adresse x4000 langfristig zu halten. Der Assembler-Code ist in der Abbildung dargestellt:
b) Blasensortierung von 16 Daten
Um den Prozess verständlicher zu machen, habe ich den Algorithmus zunächst in der Sprache C++ implementiert, wie in der folgenden Abbildung dargestellt: Das
entsprechende Flussdiagramm des Algorithmus sieht wie folgt aus:
Denn in der Sprache C++ habe ich eine for-Schleife verwendet. Bei der Übertragung in die Assemblersprache habe ich dann die Jump-to-middle-Struktur übernommen. Der Assembler-Code lautet wie folgt:
c) Screening und Bewertung von 16 Daten
Um das Verständnis zu erleichtern, verwenden Sie zunächst die C++-Programmierung. Da die Anzahl der Schüler, die C erreichen, nicht gezählt werden muss, kann der Zyklus nach 8 Runden beendet werden. Der Code lautet wie folgt:
gefolgt vom Flussdiagramm.
Im Assemblierungsprozess können keine komplexen Ausdrücke für die if-Anweisung verwendet werden, daher werden mehr bedingte Sprünge verwendet, ähnlich der goto-Anweisung von C++. Die Implementierung der Schleife übernimmt weiterhin die Jump-to-Middle-Struktur.
Da mehrere Vergleiche mit Daten wie 85 und 75 erforderlich sind, wird bei Verwendung der Subtraktion häufig die Operation des Invertierens und Addierens von eins zum Register durchgeführt, was zweifellos eine Verschwendung von Raum-Zeit-Ressourcen darstellt. Um dieses Problem zu lösen, werden nur -85 und -75 im Register gespeichert, sodass sie beim Vergleich direkt addiert werden können (entspricht einer Subtraktion), was besser ist.
2. Laden des Assembler-Codes
Schließen Sie die Bearbeitung weiterhin in LC3Edit ab, generieren Sie die OBJ-Datei und laden Sie sie wie in der Abbildung gezeigt in den LC3-Simulator. Speichern Sie die Originaldaten der Schülernoten am Speicherort x3200. Anschließend kann das Experiment durchgeführt werden.
3. Code-Funktionstest und Korrektheitsprüfung.
Im Folgenden werden hauptsächlich zwei repräsentative Beispiele verwendet. In diesen beiden Probengruppen gibt es keine wiederholten Werte und Grenzwerte .
Beispiel 1: 75 85 90 60 73 87 100 38 66 80 76 82 93 95 74 86
Das laufende Ergebnis ist in der folgenden Abbildung dargestellt:
Es ist ersichtlich, dass die Daten auf x4000 kopiert wurden. Die Sortierfunktion funktioniert einwandfrei.
Der Wert bei 4100 ist 4 und der Wert bei x4101 ist 4. Erklären Sie, dass 4 Schüler die Note A und 4 die Note B erhalten haben. Dies steht im Einklang mit den Berechnungsergebnissen.
Beispiel 2: 75 85 60 61 73 84 100 38 66 53 76 82 72 95 74 80
Das laufende Ergebnis ist in der folgenden Abbildung dargestellt:
Es ist ersichtlich, dass die sortierten Daten bei x4000 angezeigt werden.
Gleichzeitig ist bei x4100 und x4101 zu erkennen, dass 3 Personen die Note A und 5 Personen die Note B erhielten. Dieses Ergebnis entspricht der objektiven Realität.
Vollständiger Code
;author: CAO-Wuhui
;date: 2021.5.17
;function: Sort students' grades
;
;
;
.ORIG x3000 ;起始地址
;
;完成对原始数据的拷贝
;
LD R1 DATA ;R1指向源地址
LD R2 RESULT ;R2指向目的地址
AND R0 R0 #0 ;R0长期指向目的地址
ADD R0 R0 R2
AND R3 R3 #0
ADD R3 R3 #1
ADD R3 R3 #15 ;R3 = 16,循环次数
;
;循环,do-loop结构,将输入数据拷贝到目的地址
;
INIT_LOOP LDR R4 R1 #0 ;R4 = *R1
STR R4 R2 #0 ;*R2 = R4
;
ADD R1 R1 #1
ADD R2 R2 #1
ADD R3 R3 #-1
BRp INIT_LOOP
;
;冒泡排序,双重循环均采用 jump-to-middle 结构
;
AND R1 R1 #0
ADD R1 R1 #1 ;i = 1
BRnzp MIDDLE1
LOOP1 AND R2 R2 #0 ;j = 0
BRnzp MIDDLE2 ;
LOOP2 ADD R3 R0 R2
ADD R4 R3 #1
LDR R5 R3 #0 ;R5 <- *R3
LDR R6 R4 #0 ;R6 <- *R4
NOT R7 R6
ADD R7 R7 #1
ADD R7 R7 R5
BRzp END2
;
;exchange arr[j] and arr[j + 1]
;
STR R5 R4 #0
STR R6 R3 #0
END2 ADD R2 R2 #1
MIDDLE2 ADD R3 R1 R2
ADD R3 R3 #-16
BRn LOOP2
ADD R1 R1 #1
MIDDLE1 ADD R3 R1 #-16
BRn LOOP1
;
;排序结束
;以下开始筛选等级
;循环依旧采用 jump-to-middle 结构
;
AND R1 R1 #0 ;i = 0
;
;初始化R6 = -85,R7 = -75
;
LD R6 A_GRADE ;
LD R7 B_GRADE ;
NOT R6 R6
ADD R6 R6 #1
NOT R7 R7
ADD R7 R7 #1
;
AND R2 R2 #0 ;cntA = 0,A的人数
AND R3 R3 #0 ;cntB = 0,B的人数
;
BRnzp MIDDLE3
LOOP3 ADD R4 R1 #-4
BRzp IS_B
;
ADD R4 R0 R1 ;R4 = arr[i]
LDR R4 R4 #0 ;
ADD R5 R4 R6 ;if
BRn IS_B
ADD R2 R2 #1 ;cntA++
BRnzp NEXT
;
IS_B ADD R4 R0 R1 ;R4 = arr[i]
LDR R4 R4 #0 ;
ADD R5 R4 R7 ;if
BRn NEXT
ADD R3 R3 #1 ;cntB++
;
NEXT ADD R1 R1 #1
MIDDLE3 ADD R4 R1 #-8
BRn LOOP3
;
;最后将结果保存到指定位置
;
LD R1 A_CNT
STR R2 R1 #0
LD R1 B_CNT
STR R3 R1 #0
;
HALT
;
DATA .FILL x3200
RESULT .FILL x4000
A_CNT .FILL x4100
B_CNT .FILL x4101
A_GRADE .FILL x0055
B_GRADE .FILL x004B
.END