Zahlen Test --> gerade oder ungerade in Assembler

Diskutiere Zahlen Test --> gerade oder ungerade in Assembler im Hausaufgaben Bereich.
Kirby_Sike

Kirby_Sike

Alsooo wir sollen ein Programm in Assembler schreiben, dass eine ganze Zahl einließt und überprüft ob diese Zahl gerade oder ungerade ist. Soweit so gut, jedoch bekomme ich bei meinem Code eine Endlosschleife und sehe ehrlich gesagt meinen Fehler nicht :( Könnte mir jemand auf die Sprünge helfen?

Hier ist eine Liste mit allen Befehlen:

12781
12782

Mein Code:

Code:
#Einlesen einer Zahl
addi zero t0 1
sysmove exc t0
syscall

#Zahl nach a0 kopieren
sysmove a0 I[0]

#Prüfen ob Zahl gerade ist
ldd t1 zero 0
ldd t2 zero 0
ldd t3 zero 1 #Register mit Inhalt 1
ldd t4 zero 0 #Register mit 0

#divide:
subi a0 t2 2 # Subtraktion  mit 2
ldd t2 a0 0 #Move nach a0
beq a0 t3 11 #Vergleich a0 mit 1
beq a0 t4 13 #Vergleiche a0 mit 0
jmp 6

#ungerade:
cout ungerade
syscall

#gerade:
cout gerade
syscall
 
mihe7

mihe7

Mir ist die Syntax noch nicht klar. Wie viele Bytes haben die Befehle? Sind die Zahlen 8 Bit breit? Wie funktioniert cout? Usw. Da fehlt die Häfte der Doku. Aber das Prinzip wäre IMO:
Code:
# Prüfen, ob Zahl gerade ist
xor t0 t0 t0   # t0 := 0
addi t0 t1 1   # t1 := t0+1 = 1
and a0 t1 t0  # t0 := a0 & 1
beq t0 t1 ungerade # if t0 == t1 (also 1), dann weiter mit ungerade, sonst mit gerade
#gerade:
cout gerade
syscall

#ungerade:
cout ungerade
syscall
 
Kirby_Sike

Kirby_Sike

Mir ist die Syntax noch nicht klar. Wie viele Bytes haben die Befehle? Sind die Zahlen 8 Bit breit? Wie funktioniert cout? Usw. Da fehlt die Häfte der Doku.
Also die größe der Befehle ist mir ehrlich gesagt unbekannt :( Ich kann dir mal die Documentation des Assemblers schicken :)

Ich glaube jedoch dass xor t0 t0 t0 # t0 := 0 gegen die Konvention verstößt, da nur ein Befehl pro Zeile ausgeführt werden darf wegen lesen und schreiben ins selbe Register, dass wurde mir zumindest in der letzten Übungsserie angestrichen

Wie funktioniert cout?
So wie ich das verstanden habe ist count einfach ein print Befehl :)

# Prüfen, ob Zahl gerade ist
xor t0 t0 t0 # t0 := 0
addi t0 t1 1 # t1 := t0+1 = 1
and a0 t1 t0 # t0 := a0 & 1
beq t0 t1 ungerade # if t0 == t1 (also 1), dann weiter mit ungerade, sonst mit gerade
Was macht xor genau? In der Dokumentation steht bitweises Exklusiv-Oder, jedoch kann ich mir nicht wirklich vorstellen was es genau tut. Warum addierst du auf t0? Habe ich vielleicht etwas falsch verstanden bei der division in assembler? Ich dachte man müsste subtrahieren.
 

Anhänge

Zuletzt bearbeitet:
mihe7

mihe7

Was macht xor genau? In der Dokumentation steht bitweises Exklusiv-Oder, jedoch kann ich mir nicht wirklich vorstellen was es genau tut.
XOR = Antivalenz = entweder oder :)

Wertetabelle:
Code:
A | B | A XOR B
0 | 0 | 0
0 | 1 | 1
1 | 0 | 1
1 | 1 | 0
Bitweises XOR:
Code:
10101010
01010101 
-------- XOR
11111111
Dagegen
Code:
10101010
00001111
-------- XOR
10100101
Ein XOR zweier gleicher Zahlen liefert also 0.
Warum addierst du auf t0?
Um eine 1 in t1 zu erhalten :) In den Befehlen habe ich keinen gefunden, mit dem ich ein Register mit einem Immediate (Wert) setzen hätte können. Wo ein Immediate zugelassen ist: addi (darum auch das i am Ende).

Habe ich vielleicht etwas falsch verstanden bei der division in assembler? Ich dachte man müsste subtrahieren.
Könnte man, muss man aber nicht. Eine Binärzahl ist ungerade, wenn das 1er-Bit gesetzt ist :)
 
Kirby_Sike

Kirby_Sike

Ahhhh jetzt fühle ich mich um einiges schlauer xD

Ich bin trotzdem verwirrt ob der xor Befehl der Konvention entspricht xD:

Konvention:
  • Pro Zeile darf höchstens 1 Befehl stehen.
  • Befehlsname und die jeweiligen Argumente müssen mit mindestens einem Leerzeichen oder einem
    Tabulator getrennt sein. Vor dem Befehlsnamen darf kein Leerzeichen stehen.
  • Bei den reinen Maschinenbefehlen wird nicht zwischen Majuskeln und Minuskeln, also Groß- und Kleinschreibung, unterschieden. Das gilt insbesondere für die Registernamen.
  • Neben den oben aufgezählten Maschinenbefehlen dürfen noch beliebig viele Pseudoinstruktionen benutzt werden. Diese müssen im Reiter „Systemeinstellungen“ deklariert und realisiert worden sein.
  • Bei allen Instruktionen müssen die Registernamen benutzen werden, die im Reiter „Register- und Speicherbelegung“ in der Registerbanktabelle aufgeführt sind.
  • Ein-/Ausgaberegister können nicht als Operanden von Maschinenbefehlen dienen, sondern nur als
    Operanden von Systembefehlen, da sie sich nicht in der Registerbank des Prozessors befinden.
 
Kirby_Sike

Kirby_Sike

Ja ich weiß und ich habe gerade etwas nachgedacht und gemerkt dass meine Frage kein Sinn macht xD

# ---> Kommentar Zeichen
 
mihe7

mihe7

Sehe zwar kein Problem mit der Konvention, aber dann halt per Addition... (ich wusste vor der Doku nicht, was es mit zero auf sich hat) Und: der Assembler kann Labels :)
Code:
# Einlesen
addi zero t1 1
sysmove exc t1
syscall
sysmove a0 I[0]

# Prüfen, ob Zahl gerade ist
addi zero t0 0
and a0 t1 t0 
beq t0 t1 ungerade 

# gerade
cout gerade
jmp ende

# ungerade
ungerade:
cout ungerade

# ende
ende:
sysmove exc zero
syscall
 
Kirby_Sike

Kirby_Sike

Danke für deine Hilfe :) Ich muss sagen das hat gerade mein Wissen bezogen auf den Uni Assembler um einiges geboostet xD Du bist einfach ein Master of Everything xD
 
Kirby_Sike

Kirby_Sike

@mihe7 Ich hätte noch eine Frage, wenn ich jetzt zwei Zahlen einlesen möchte und prüfen will ob die zweite Zahl in den Natürlichen Zahlen liegt muss ich doch einfach prüfen ob 0 größer als das Speicher Register der Zahl ist ?

Also wie folgt:

Code:
# Einlesen Zahl 1
addi zero t1 1
sysmove exc t1
syscall
sysmove a0 I[0]

# Einlesen Zahl 2
einlesen:
addi zero t2 1
sysmove exc t2
syscall
sysmove a1 I[1]
bgt zero a1 einlesen
 
mihe7

mihe7

Natürlichen Zahlen liegt muss ich doch einfach prüfen ob 0 größer als das Speicher Register der Zahl ist ?
Deine Idee ist also, wenn 0 > x gilt, dann ist x keine natürliche Zahl. Das ist mathematisch richtig, wenn man die 0 als natürliche Zahl zählt, ob der Vergleich so funktioniert, ist eine andere Sache - und davon würde ich nicht ausgehen.

Für den Prozessor ist ein Register einfach Wort mit einer bestimmen Länge, hier 8 Bit. Was diese 8 Bit darstellen, weiß der Prozessor nicht (es könnte spezielle Prozessorbefehle geben, was hier aber nicht der Fall ist, wie ich meine).

Werden zwei Register verglichen, passiert das über eine logische Schaltung. So lange die Bits der beiden Register - vom höchstwertigen Bit ausgehend - gleich sind, sind die Register gleich. An der ersten Position, an der das nicht mehr zutrifft, weiß man, welches Register größer ist:
Code:
r1  11100000
r2  11110000
    ^^^^
    ===<
Hier wäre also r1 < r2.

Die Frage ist jetzt, was die Register darstellen. Das können Zahlen ohne Vorzeichen sein, dann hat man je Register einen Wertebereich von 0 bis 255. In dem Fall stimmt der Vergleich: 00000001 < 11111111 (binär) entspricht 1 < 255 (dezimal).

Wenn es Zahlen mit Vorzeichen sind, dann ist die Frage, wie diese dargestellt werden. Üblicherweise wird das Zweierkomplement verwendet. Um eine Zahl zu negieren, werden die Bits invertiert und anschließend wird eine 1 addiert.

Wenn wir Beispielsweise die 1 negieren wollen, um -1 zu erhalten:
Code:
00000001    # 1 binär
11111110    # invertiert
11111111    # 1 addiert
-1 wird im Zweierkomplement also binär mit 11111111 dargestellt.

Klar ist jetzt, dass der Vergleich nicht das gewünschte Ergebnis liefert, denn 00000001 < 11111111 (binär) würde jetzt dezimal 1 < -1 entsprechen.

Tatsächlich lässt sich viel einfacher feststellen, ob eine Zahl negativ ist, denn das 8. Bit ist das Vorzeichen. Daher lassen sich Zahlen von -128 bis +127 darstellen.

Wenn Du also eine Zahl im Zweierkomplement hast, brauchst Du nur zu testen, ob das 8. Bit gesetzt ist. Falls ja, hast Du eine negative Zahl.
 
Kirby_Sike

Kirby_Sike

Danke für deine Hilfe um die Uhrzeit :) Nehmen wir mal an dass wir die Natürlichen Zahlen ohne die 0 haben wollen, dann müsste man doch einfach prüfen bei 8 bit Zahlen ob 1 (011111111 im ZK) > Register X ist und wenn true dann geht er weiter und wenn nicht kommt die Eingabeaufforderung erneut ?
 
mihe7

mihe7

ob 1 (011111111 im ZK)
1 ist im ZK auch 00000001. 01111111 wäre 127 - ganz normal. Nur die negativen Zahlen werden anders dargestellt.

Nachtrag: und ja, wenn 01111111 > registerX ist, dann liegt registerX im Bereich von 0 bis 127. Wenn Du die 0 nicht haben willst, musst Du nochmal explizit auf 0 prüfen.
 
Zuletzt bearbeitet:
Kirby_Sike

Kirby_Sike

1 ist im ZK auch 00000001. 01111111 wäre 127 - ganz normal. Nur die negativen Zahlen werden anders dargestellt.

Nachtrag: und ja, wenn 01111111 > registerX ist, dann liegt registerX im Bereich von 0 bis 127. Wenn Du die 0 nicht haben willst, musst Du nochmal explizit auf 0 prüfen.
Okee Dankeschön :) ja gut ich glaube nach dem Pensum an Mathe heute in der Uni hatte mein Gehirn da scheinbar ein Timeout xD
1 ist im ZK auch 00000001
War das nicht die 1 im Einerkomplement oder verwirre ich mich gerade selber :) ?
 
Zuletzt bearbeitet:
mihe7

mihe7

War das nicht die 1 im Einerkomplement oder verwirre ich mich gerade selber :) ?
Letzteres: positive Zahlen werden immer gleich dargestellt. Unterschiede gibt es in der Darstellung negativer Zahlen. Ist das höchstwertige Bit eine 0, dann unterscheiden sich vorzeichenlose Ganzzahlen nicht von vorzeichenbehafteten Ganzzahlen.
 
Kirby_Sike

Kirby_Sike

@mihe7 könntest du mir eventuell nochmal für dumme erklären, wie ich es mir vorstellen kann wenn register verglichen werden. Also in dem Befehlsatz PHILO's...Ich hatte and sowas gedacht:

t3 ist einfach ein Register das die Zahl 0 enthält. Ich möchte prüfen ob die Ziffer größer als 0 ist und wenn nicht, dann neu einlesen.

Code:
einlesen:
addi zero t2 1
sysmove exc t2
syscall
sysmove a1 I[1]
bgt t3 a1 einlesen
 
mihe7

mihe7

Der Vergleich ist ganz einfach. Du hast zwei vorzeichenlose binäre Zahlen und die werden nicht anders verglichen dezimale Zahlen: 0 < 1 < 10 < 11 < 100 < 101 < 110 < 111 < 1000 usw.

Das einzige Problem ist, dass die Befehle keine negativen Zahlen kennen. Es gibt keine Zahl kleiner 0. Es obliegt dem Programmierer, wie er negative Zahlen darstellt. Der Programmierer des "Betriebssystems" in PHILO hat festgelegt, dass bei Eingabe (syscall) einer negativen Zahl das Zweierkomplement verwendet wird.

Ein Vergleich zweier negativen Zahlen ist somit auch kein Problem: denn -2 < -1, was unmittelbar auch in ZK-Darstellung 11111110 < 11111111 zutrifft.

Problematisch ist der Vergleich einer negativen und einer nicht-negativen Zahl, der Befehl weiß ja nicht, ob eine Zahl negativ oder positiv ist. Was Du machen kannst: Du kannst fragen, ob eine Zahl größer als 127 (01111111) ist. Dann nämlich ist das 8. Bit, das Vorzeichenbit, gesetzt.

Code:
addi zero t3 127
einlesen: ...
...
bgt a1 t3 einlesen     # falls a1 > 127, also Vorzeichenbit gesetzt, dann weiter mit einlesen
 
Thema: 

Zahlen Test --> gerade oder ungerade in Assembler

Passende Stellenanzeigen aus deiner Region:
Anzeige

Neue Themen

Anzeige

Anzeige
Oben