Programm dass Subtrahieren soll durch Addition?
Hallo Leute heute eine etwas untypische Aufgabe:
Wir schreiben das Jahr 2042. Nach einer extremen Verschärfung der Finanzkrise können die Universitäten nur noch sehr preiswerte Rechner anschaffen. Zum Glück hat der führende Prozessorhersteller Inrola gerade einen neuen Chip namens Untium auf den Markt gebracht. Dieser Chip ist so preiswert, weil er nur noch genau eine Instruktion hat nämlich „subtract-and-branch-on-less-zero“. Dieser Befehl hat vier Parameter, Quelle 1 (Q1), Quelle 2 (Q2), Zielregister (ZR) und Sprungadresse (SA). Wird der Befehl aufgerufen, berechnet er Q1 − Q2, schreibt das Ergebnis in ZR und springt dann nach SA, wenn das Ergebnis, das er in ZR geschrieben hat, kleiner als 0 ist (sonst folgt die Bearbeitung des Befehls in der folgenden Zeile). Der Untium-Prozessor verfügt über 6 Ganzzahlregister, $1 bis $6. Als Quelle kann entweder ein Register oder eine ganzzahlige Konstante angegeben werden, ZR ist immer ein Register. SA gibt die Nummer des Befehls an, zu dem eventuell gesprungen werden soll.Als Studierende kommt Ihnen die Ehre zuteil, den ersten Rechner dieses Typs, den SPOZ-I zu testen. Da zu einem so frühen Zeitpunkt noch keine Compiler zur Verfügung stehen, müssen sie den 1-Befehl-Assembler benutzen. Ein Assemblerprogramm besteht aus Zeilen der Form:
Q1, Q2, ZR, SA // optional kann hier ein Kommentar stehen
Ich soll jetzt herausfinden, sie eine wie eine Addition durchgeführt werden kann. Dabei seien die Sum-
manden in den Registern $1 und $2 vorgegeben. Die Summe soll nach der Berechnung in $3 stehen. Ich bin da leider nicht gehirntechnisch in der Lage, die Aufgabe zu lProgramm dass Subtrahieren soll durch Additionösen...
1 Antwort
Als erstes sollten Sie sich mit der Syntax des 1-Befehl-Assemblers vertraut machen. Ein Assemblerprogramm besteht aus einer oder mehreren Zeilen, die jeweils einen Befehl darstellen. Ein Befehl hat die folgende Form:
Q1, Q2, ZR, SA
Hierbei sind Q1, Q2 und ZR entweder Registerbezeichnungen ($1 bis $6) oder ganzzahlige Konstanten. SA ist die Nummer des Befehls, zu dem eventuell gesprungen werden soll. Nach dem Befehl kann optional ein Kommentar stehen, der von // bis zum Ende der Zeile reicht.
Die Syntax des Befehls selbst ist bereits beschrieben: Der Befehl subtract-and-branch-on-less-zero berechnet Q1 - Q2, schreibt das Ergebnis in ZR und springt dann nach SA, wenn das Ergebnis kleiner als 0 ist. Andernfalls wird der Befehl in der nächsten Zeile fortgesetzt.
Beachten Sie, dass der Untium-Prozessor nur einen einzigen Befehl ausführen kann. Daher ist es notwendig, alle benötigten Berechnungen in einem einzigen Befehl auszuführen.
Ein Beispielprogramm könnte wie folgt aussehen:
// Addiere 10 und 20 und speichere das Ergebnis in Register $1
10, -20, $1, 5 // Springe zu Befehl 5, wenn das Ergebnis negativ ist
30, 0, $1, 6 // Schreibe 30 in Register $1 und springe zum nächsten Befehl
0, 0, 0, 0 // Ende des Programms
In diesem Beispiel wird zuerst 10 und -20 addiert, das Ergebnis in Register $1 gespeichert und dann überprüft, ob das Ergebnis negativ ist. Falls ja, wird zu Befehl 5 gesprungen, wo das Programm endet. Andernfalls wird die nächste Zeile ausgeführt, die den Wert 30 in Register $1 schreibt und zum nächsten Befehl springt. Der letzte Befehl stellt das Ende des Programms dar.
class UntiumProcessor:
def __init__(self):
self.registers = [0] * 6
def run_program(self, program):
current_instruction = 0
while current_instruction < len(program):
instruction = program[current_instruction].strip().split(',')
q1, q2, zr, sa = [x.strip() for x in instruction]
q1_value = self.get_value(q1)
q2_value = self.get_value(q2)
result = q1_value - q2_value
self.set_value(zr, result)
if result < 0:
current_instruction = int(sa)
else:
current_instruction += 1
def get_value(self, operand):
if operand.startswith('$'):
return self.registers[int(operand[1:]) - 1]
else:
return int(operand)
def set_value(self, register, value):
self.registers[int(register[1:]) - 1] = value
Dieser Code definiert eine Klasse
UntiumProcessor
, die einen Untium-Prozessor simuliert. Die
run_program
-Methode nimmt ein Assemblerprogramm als Eingabe und führt es aus. Dabei wird jede Zeile des Programms nacheinander ausgeführt, bis das Ende des Programms erreicht ist.
Die
get_value
-Methode wird verwendet, um den Wert einer Operanden zu erhalten. Wenn die Operandenbezeichnung mit
$
beginnt, wird der Wert aus dem entsprechenden Register gelesen. Andernfalls wird der Operand als Konstante interpretiert.
Die
set_value
-Methode wird verwendet, um den Wert in ein Register zu schreiben.
Um diese Klasse zu verwenden, können Sie ein Assemblerprogramm als Textzeilen definieren und es an die
run_program
-Methode übergeben.